├── .github └── workflows │ └── test.yml ├── .gitignore ├── .gitmodules ├── AUTHORS ├── COPYING ├── ChangeLog ├── Doxyfile ├── Makefile.am ├── NEWS ├── README ├── README.md ├── autogen.sh ├── configure.ac ├── doc ├── TODO ├── css │ ├── elements.css │ ├── ie.css │ ├── reset.css │ └── screen.css └── user-guide │ ├── Makefile │ ├── customization.xsl │ └── user-guide.xml ├── examples ├── .gitignore ├── Makefile.am ├── anonymous_unions.c ├── array_metadata.c ├── arrays.c ├── arrays.h ├── basic.c ├── bitfields.c ├── bitfields.h ├── builtins.c ├── builtins.h ├── decl_rarray.c ├── decl_rarray.h ├── deserialization_2_args.c ├── deserialization_3_args.c ├── deserializing_xml.c ├── double_pointer.c ├── dwarf.c ├── dwarf_types.c ├── emptystruct.c ├── emptystruct.h ├── enums.c ├── enums.h ├── enums_metadata.c ├── field_types.c ├── function_pointer_metadata.c ├── function_pointers.c ├── function_type.c ├── get_set_field.c ├── gjobs.c ├── gjobs.xml ├── justabuiltin.c ├── load_cinit.c ├── load_json.c ├── load_scm.c ├── marshalling_arrays.c ├── marshalling_arrays.h ├── marshalling_enumerations.c ├── marshalling_enumerations.h ├── marshalling_pointers.c ├── marshalling_pointers.h ├── marshalling_pointers_to_functions.c ├── marshalling_pointers_to_functions.h ├── marshalling_structures_basic_types.c ├── marshalling_structures_basic_types.h ├── marshalling_unions.c ├── multidimensional_arrays.c ├── named_union.c ├── named_union.h ├── save_cinit.c ├── save_json.c ├── save_scm.c ├── separate.c ├── separate_employee.c ├── separate_employee.h ├── separate_employee_decl.h ├── simple_structure.c ├── simple_structure.h ├── simplified_grammar.c ├── simplified_grammar.h ├── specified_width.c ├── specified_width.h ├── suffixes_comments_userdata.c ├── suffixes_comments_userdata.h ├── type_descriptors.c ├── type_prefixes.c └── type_prefixes.h ├── gcov ├── check_gcov.sh └── configure_gcov.sh ├── huge_enterprise_app ├── Makefile ├── file.c.in ├── file.h.in ├── main.c └── test.sh ├── src ├── .gitignore ├── Makefile.am ├── cinit_load.l ├── cinit_load.y ├── cinit_save.c ├── json_load.l ├── json_load.y ├── json_save.c ├── lexer.h ├── metaresc.c ├── metaresc.h ├── mr_btree.c ├── mr_btree.h ├── mr_dwarf.c ├── mr_export.h.in ├── mr_extra.c ├── mr_hsort.c ├── mr_hsort.h ├── mr_ic.c ├── mr_ic.h ├── mr_load.c ├── mr_load.h ├── mr_message.c ├── mr_pp.sh ├── mr_print.c ├── mr_protos.h ├── mr_save.c ├── mr_save.h ├── mr_stringify.c ├── mr_stringify.h ├── mr_udo_init.c ├── mr_udo_init.h ├── mr_value.c ├── mr_value.h ├── scm_load.l ├── scm_load.y ├── scm_save.c ├── xdr.c ├── xml1_load.l ├── xml1_load.y ├── xml2_load.c ├── xml_save.c ├── yaml_load.c └── yaml_save.c └── tests ├── .gitignore ├── Makefile.am ├── array.c ├── bitfield.c ├── bool.c ├── btree.c ├── char.c ├── complex_double.c ├── complex_float.c ├── complex_long_double.c ├── double.c ├── dw_export.c ├── dw_mr_types.h ├── dw_types.c ├── dw_types_init.c ├── enum.c ├── expr.c ├── float.c ├── flt_values.h ├── function.c ├── generic_ic.c ├── ic.c ├── int.h ├── int128.c ├── int16.c ├── int32.c ├── int64.c ├── int8.c ├── long_double.c ├── mem_allocations.c ├── mem_failures.c ├── mem_failures.h ├── mf_cinit_load.c ├── mf_cinit_save.c ├── mf_json_load.c ├── mf_json_save.c ├── mf_mr_copy.c ├── mf_mr_save.c ├── mf_scm_load.c ├── mf_scm_save.c ├── mf_xdr_load.c ├── mf_xdr_save.c ├── mf_xml1_load.c ├── mf_xml1_save.c ├── mf_xml2_load.c ├── mf_xml2_save.c ├── mf_yaml_load.c ├── mf_yaml_save.c ├── mr_copy.c ├── mr_hash_cmp.c ├── mr_ptr.c ├── mr_types.c ├── perf.h ├── perf_cinit.c ├── perf_json.c ├── perf_save.c ├── perf_scm.c ├── perf_xml1.c ├── pointer_int.c ├── pointer_other.c ├── regression.h ├── resizable_pointer.c ├── smoke.h ├── smoke_cinit.c ├── smoke_json.c ├── smoke_scm.c ├── smoke_xdr.c ├── smoke_xml1.c ├── smoke_xml2.c ├── smoke_yaml.c ├── string.c ├── union.c ├── union.h └── union_resolution_complexity.c /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | x86-ubuntu-gcc-clang: 7 | runs-on: ubuntu-latest 8 | name: x86 Ubuntu with 9 | strategy: 10 | matrix: 11 | include: 12 | - cc: gcc 13 | - cc: clang 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: update packages 17 | run: sudo apt-get update -y 18 | - name: install dependencies 19 | run: sudo apt-get install -y autoconf automake libtool pkg-config flex bison libxml2-dev libyaml-dev libtirpc-dev check valgrind python3 20 | - name: submodule update 21 | run: git submodule update --init --recursive --remote 22 | - name: autoconf/automake 23 | run: ./autogen.sh 24 | - name: configure 25 | run: ./configure CFLAGS="-I/usr/include/tirpc -Werror" LIBS=-ltirpc CC=${{matrix.cc}} || ( cat config.log ; false ) 26 | - name: make check 27 | run: make check -j 2 || ( cat tests/test-suite.log ; false ) 28 | - name: check with valgrind 29 | run: | 30 | cd tests 31 | sed -i.bak -e "s/long double, long_double/double, long_double/" mr_types.c 32 | rm -f mr_types 33 | CK_TIMEOUT_MULTIPLIER=2 make valgrind -j 2 || ( cat test-suite.log ; false ) 34 | - name: check with address sanitizer 35 | run: | 36 | make clean 37 | sed -i.bak -e "s/test_sanitized \\\/test_sanitized/" -e "s/test_tied//" -e "s/test_dwarfdumpMacos.sh//" libdwarf-code/test/Makefile.am 38 | sed -i.bak -e "s/bool, _bool/uint8_t, _bool/" tests/mr_types.c 39 | make check -j 2 CFLAGS="-I/usr/include/tirpc -Werror -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer" 40 | 41 | macos-clang: 42 | runs-on: macos-latest 43 | name: Macos with clang 44 | steps: 45 | - uses: actions/checkout@v4 46 | - name: install dependencies 47 | run: brew install autoconf automake libtool pkg-config flex bison libxml2 libyaml check python3 48 | - name: submodule update 49 | run: git submodule update --init --recursive --remote 50 | - name: autoconf/automake 51 | run: ./autogen.sh 52 | - name: configure 53 | run: ./configure CFLAGS=-Werror HAVE_BISON=yes YACC=$(brew --prefix)/opt/bison/bin/bison 54 | - name: make check 55 | run: make check -j 2 || ( cat tests/test-suite.log ; false ) 56 | 57 | freebsd-clang: 58 | runs-on: ubuntu-latest 59 | name: FreeBSD with clang 60 | steps: 61 | - uses: actions/checkout@v4 62 | - name: Test in FreeBSD 63 | id: test 64 | uses: vmactions/freebsd-vm@v1 65 | with: 66 | usesh: true 67 | prepare: pkg install -y git autoconf automake libtool pkgconf flex bison libxml2 libyaml check python3 68 | run: | 69 | git config --global --add safe.directory `pwd` 70 | git submodule update --init --recursive --remote 71 | ./autogen.sh 72 | ./configure CFLAGS="-I/usr/local/include/ -Werror" --without-perftest 73 | make check -j 2 || ( cat tests/test-suite.log ; false ) 74 | 75 | windows: 76 | runs-on: windows-latest 77 | name: Windows with 78 | strategy: 79 | matrix: 80 | include: 81 | - { sys: mingw64, env: x86_64 } 82 | - { sys: ucrt64, env: ucrt-x86_64 } 83 | - { sys: clang64, env: clang-x86_64 } 84 | defaults: 85 | run: 86 | shell: msys2 {0} 87 | steps: 88 | - uses: actions/checkout@v4 89 | - uses: msys2/setup-msys2@v2 90 | with: 91 | msystem: ${{matrix.sys}} 92 | update: true 93 | install: base-devel git autoconf automake libtool pkg-config flex bison python3 mingw-w64-${{matrix.env}}-check mingw-w64-${{matrix.env}}-libxml2 mingw-w64-${{matrix.env}}-libyaml mingw-w64-${{matrix.env}}-toolchain 94 | - name: submodule update 95 | run: git submodule update --init --recursive --remote 96 | - name: autoconf/automake 97 | run: ./autogen.sh 98 | - name: configure 99 | run: ./configure CFLAGS=-Werror --disable-static --enable-shared --without-perftest 100 | - name: patch libtool 101 | run: sed -i.bak -e "s/\(allow_undefined=\)yes/\1no/" libtool 102 | - name: make check 103 | run: make check || ( cat tests/test-suite.log ; false ) 104 | - name: archive build artifacts 105 | uses: actions/upload-artifact@v4 106 | with: 107 | name: win-${{matrix.env}}-${{matrix.sys}} 108 | path: | 109 | src/.libs/libmetaresc.* 110 | src/.libs/mr_dwarf* 111 | src/metaresc.h 112 | src/mr_protos.h 113 | src/mr_export.h 114 | src/mr_pp.h 115 | tests/test-suite.log 116 | 117 | # non-x86-ubuntu-clang: 118 | # runs-on: ubuntu-latest 119 | # name: non-x86 Ubuntu with 120 | # strategy: 121 | # matrix: 122 | # include: 123 | # - { arch: aarch64, cc: gcc } 124 | # - { arch: aarch64, cc: clang } 125 | # - { arch: riscv64, cc: gcc } 126 | # - { arch: riscv64, cc: clang } 127 | # - { arch: ppc64le, cc: gcc } 128 | # - { arch: ppc64le, cc: clang } 129 | # steps: 130 | # - uses: actions/checkout@v4 131 | # - uses: uraimo/run-on-arch-action@v2 132 | # name: Run commands 133 | # id: build-and-check 134 | # with: 135 | # arch: ${{matrix.arch}} 136 | # distro: ubuntu_latest 137 | 138 | # # Not required, but speeds up builds by storing container images in 139 | # # a GitHub package registry. 140 | # githubToken: ${{ github.token }} 141 | 142 | # run: | 143 | # apt-get update -y 144 | # apt-get install -y git gcc clang make autoconf automake libtool pkg-config flex bison libxml2-dev libyaml-dev check python3 145 | # git config --global --add safe.directory '*' 146 | # git submodule update --init --recursive --remote 147 | # ./autogen.sh 148 | # ./configure CFLAGS="-I/usr/include/tirpc -Werror" LIBS=-ltirpc CC=${{matrix.cc}} --without-perftest 149 | # make check || ( cat tests/test-suite.log ; false ) 150 | 151 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.la 2 | *.lex.[ch] 3 | *.lo 4 | *.o 5 | *.tab.[ch] 6 | /Makefile 7 | /Makefile.in 8 | INSTALL 9 | aclocal.m4 10 | autom4te.cache/* 11 | compile 12 | config.guess 13 | config.log 14 | config.status 15 | config.sub 16 | configure 17 | depcomp 18 | examples/Makefile.in 19 | install-sh 20 | libtool 21 | ltmain.sh 22 | m4/* 23 | missing 24 | src/.deps/* 25 | src/.libs/* 26 | src/stamp-h1 27 | src/stamp-h2 28 | test-driver 29 | tests/.deps/* 30 | tests/.libs/* 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libdwarf-code"] 2 | path = libdwarf-code 3 | url = https://github.com/davea42/libdwarf-code.git 4 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Herman Narkaytis aka Smash 2 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2001-2021 Herman Narkaytis. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is fur- 8 | nished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 15 | NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Tue Aug 16 22:34:01 2001 Herman Narkaytis 2 | 3 | * Start of the project 4 | 5 | Wed Jul 16 19:57:01 2008 Herman Narkaytis 6 | 7 | * Registered on SourceForge and imported project into SVN 8 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ## Process this file with automake to produce Makefile.in 2 | 3 | ACLOCAL_AMFLAGS = -I m4 4 | 5 | SUBDIRS = src tests examples 6 | 7 | docs: Doxyfile 8 | doxygen $< 9 | 10 | distclean-local: 11 | find . "(" -name '*.gcda' -o -name '*.gcno' -o -name '*.gcov' ")" -delete 12 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Version 1.0 released, 8/2001. 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexanderchuranov/Metaresc/1ce1751cf998d2a28328cacd32e7ca8d474194a7/README -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Run this to generate all the auto-generated files needed by the GNU 4 | # configure program 5 | 6 | autoreconf --warnings=all --install --verbose --force 7 | -------------------------------------------------------------------------------- /doc/TODO: -------------------------------------------------------------------------------- 1 | * verify that macro arguments are positional 2 | * verify that user-data must be enclosed in braces 3 | * inline all TODOs in docs as comments :-) 4 | -------------------------------------------------------------------------------- /doc/css/elements.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | padding: 1em 10%; 4 | background: #fff; 5 | } 6 | 7 | a { font-family: sans; } 8 | 9 | hr { 10 | 11 | border-style: none; 12 | border-bottom: 1px solid black; 13 | } 14 | 15 | h1, h2, h3, h4, h5, h6 { 16 | margin: 0.5em 0px; 17 | margin-left: -1em; 18 | text-align: left; 19 | font-family: sans; 20 | } 21 | 22 | h1 { font-size: 200%; } 23 | h2 { font-size: 180%; } 24 | h3 { font-size: 160%; } 25 | h4 { font-size: 140%; } 26 | h5 { font-size: 120%; } 27 | 28 | dl, dt, dd { 29 | text-align: left; 30 | } 31 | 32 | dd { 33 | margin-left: 2em; 34 | } 35 | 36 | p { 37 | margin: 0.5em 0px; 38 | text-align: justify; 39 | } 40 | 41 | pre { 42 | white-space: pre; 43 | text-align: left; 44 | font-family: monospace; 45 | } 46 | 47 | code { 48 | text-align: left; 49 | font-family: monospace; 50 | } 51 | 52 | li { 53 | margin-left: 2em; 54 | } 55 | 56 | sub { font-style: italic; } 57 | sup { font-size: 70%; } 58 | -------------------------------------------------------------------------------- /doc/css/ie.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | ie.css 4 | 5 | Contains every hack for Internet Explorer, 6 | so that our core files stay sweet and nimble. 7 | 8 | -------------------------------------------------------------- */ 9 | 10 | /* Make sure the layout is centered in IE5 */ 11 | body { text-align: center; } 12 | .container { text-align: left; } 13 | 14 | /* Fixes IE margin bugs */ 15 | * html .column, * html div.span-1, * html div.span-2, 16 | * html div.span-3, * html div.span-4, * html div.span-5, 17 | * html div.span-6, * html div.span-7, * html div.span-8, 18 | * html div.span-9, * html div.span-10, * html div.span-11, 19 | * html div.span-12, * html div.span-13, * html div.span-14, 20 | * html div.span-15, * html div.span-16, * html div.span-17, 21 | * html div.span-18, * html div.span-19, * html div.span-20, 22 | * html div.span-21, * html div.span-22, * html div.span-23, 23 | * html div.span-24 { overflow-x: hidden; } 24 | 25 | 26 | /* Elements 27 | -------------------------------------------------------------- */ 28 | 29 | /* Fixes incorrect styling of legend in IE6. */ 30 | * html legend { margin:0px -8px 16px 0; padding:0; } 31 | 32 | /* Fixes incorrect placement of ol numbers in IE6/7. */ 33 | ol { margin-left:2em; } 34 | 35 | /* Fixes wrong line-height on sup/sub in IE. */ 36 | sup { vertical-align: text-top; } 37 | sub { vertical-align: text-bottom; } 38 | 39 | /* Fixes IE7 missing wrapping of code elements. */ 40 | html>body p code { *white-space: normal; } 41 | 42 | /* IE 6&7 has problems with setting proper
margins. */ 43 | hr { margin: -8px auto 11px; } 44 | 45 | /* Explicitly set interpolation, allowing dynamically resized images to not look horrible */ 46 | img { -ms-interpolation-mode: bicubic; } 47 | 48 | /* Clearing 49 | -------------------------------------------------------------- */ 50 | 51 | /* Makes clearfix actually work in IE */ 52 | .clearfix, .container {display: inline-block;} 53 | * html .clearfix, 54 | * html .container {height: 1%;} 55 | 56 | 57 | /* Forms 58 | -------------------------------------------------------------- */ 59 | 60 | /* Fixes padding on fieldset */ 61 | fieldset {padding-top: 0;} 62 | 63 | /* Fixes rule that IE 6 ignores */ 64 | input.text, input.title {background-color:#fff;border:1px solid #bbb;} 65 | input.text:focus, input.title:focus {border-color:#666;} 66 | input.text, input.title, textarea, select {margin:0.5em 0;} 67 | input.checkbox, input.radio {position:relative; top:.25em;} 68 | 69 | /* Fixes alignment of inline form elements */ 70 | form.inline div, form.inline p {vertical-align:middle;} 71 | form.inline label {position:relative;top:-0.25em;} 72 | form.inline input.checkbox, form.inline input.radio, 73 | form.inline input.button, form.inline button { 74 | margin:0.5em 0; 75 | } 76 | button, input.button {position:relative;top:0.25em;} -------------------------------------------------------------------------------- /doc/css/reset.css: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------- 2 | 3 | reset.css 4 | * Resets default browser CSS. 5 | 6 | -------------------------------------------------------------- */ 7 | 8 | html, body, div, span, object, iframe, 9 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 10 | a, abbr, acronym, address, code, 11 | del, dfn, em, img, q, dl, dt, dd, ol, ul, li, 12 | fieldset, form, label, legend, 13 | table, caption, tbody, tfoot, thead, tr, th, td { 14 | margin: 0; 15 | padding: 0; 16 | border: 0; 17 | font-weight: inherit; 18 | font-style: inherit; 19 | font-size: 100%; 20 | font-family: inherit; 21 | vertical-align: baseline; 22 | } 23 | 24 | body { 25 | line-height: 1.5; 26 | } 27 | 28 | /* Tables still need 'cellspacing="0"' in the markup. */ 29 | table { border-collapse: separate; border-spacing: 0; } 30 | caption, th, td { font-weight: normal; } 31 | table, td, th { vertical-align: middle; } 32 | 33 | /* Remove possible quote marks (") from ,
. */ 34 | blockquote:before, blockquote:after, q:before, q:after { content: ""; } 35 | blockquote, q { quotes: "" ""; } 36 | 37 | /* Remove annoying border on linked images. */ 38 | a img { border: none; } 39 | -------------------------------------------------------------------------------- /doc/css/screen.css: -------------------------------------------------------------------------------- 1 | 2 | @import "reset.css"; 3 | /*@import "ie.css";*/ 4 | @import "elements.css"; 5 | 6 | .navheader table { 7 | margin-bottom: 1em; 8 | } 9 | 10 | .book { 11 | margin-bottom: 1em; 12 | } 13 | 14 | .toc, .toc > dl { 15 | margin: 1em 0px; 16 | } 17 | 18 | .toc dl { 19 | margin-bottom: 1.2em; 20 | } 21 | 22 | .section { margin-bottom: 3em; } 23 | .simplesect { margin: 2em 0px; } 24 | 25 | .table-contents table, .informaltable table { 26 | width: 100%; 27 | border-collapse: collapse; 28 | } 29 | 30 | .table-contents th, .informaltable th { 31 | background: #eee; 32 | } 33 | 34 | .table-contents th, .table-contents td, .informaltable th, .informaltable td { 35 | padding: 0.2em 0.5em 0.7em; 36 | border: 1px solid black; 37 | vertical-align: top; 38 | } 39 | 40 | .glosslist dt { font-style: italic; } 41 | 42 | .emphasis { font-style: italic; } 43 | 44 | .screen, .programlisting { 45 | margin: 1em 0px; 46 | padding: 0.3em 0.5em; 47 | background: #e0e0e0; 48 | color: black; 49 | border: 1px solid #bbb; 50 | } 51 | -------------------------------------------------------------------------------- /doc/user-guide/Makefile: -------------------------------------------------------------------------------- 1 | 2 | SOURCE = user-guide.xml 3 | HTML_DEST = ${HOME}/web/nginx-root/html/metaresc/user-guide 4 | 5 | # docbook stuff 6 | 7 | DOCBOOK_ROOT = /usr/local/share/xml/docbook/5.0 8 | 9 | STYLESHEET = ./customization.xsl 10 | SCHEMA = ${DOCBOOK_ROOT}/xsd/docbook.xsd 11 | 12 | all: ${SOURCE} 13 | xsltproc --xinclude ${XSLT_PARAMS} ${STYLESHEET} $< 14 | 15 | test: ${SOURCE} 16 | xmllint --xinclude --noout --schema ${SCHEMA} ${.ALLSRC} 17 | 18 | deploy: all 19 | rm -f ${HTML_DEST}/* 20 | mv *html ${HTML_DEST}/ 21 | 22 | clean: 23 | rm -f *.html *.tmp 24 | 25 | .PHONY: test clean 26 | -------------------------------------------------------------------------------- /doc/user-guide/customization.xsl: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | /css/metaresc/screen.css 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | /.deps 2 | /.libs 3 | /Makefile 4 | /anonymous_unions 5 | /array_metadata 6 | /arrays 7 | /basic 8 | /bitfields 9 | /builtins 10 | /builtins_auto 11 | /decl_rarray 12 | /deserialization_2_args 13 | /deserialization_3_args 14 | /deserializing_xml 15 | /double_pointer 16 | /dwarf 17 | /dwarf_no_types 18 | /dwarf_types.h 19 | /emptystruct 20 | /enums 21 | /enums_metadata 22 | /field_types 23 | /function_pointer_metadata 24 | /function_pointers 25 | /function_type 26 | /get_set_field 27 | /gjobs 28 | /justabuiltin 29 | /load_cinit 30 | /load_json 31 | /load_scm 32 | /marshalling_arrays 33 | /marshalling_bit_fields 34 | /marshalling_enumerations 35 | /marshalling_pointers 36 | /marshalling_pointers_to_functions 37 | /marshalling_structures_basic_types 38 | /marshalling_unions 39 | /multidimensional_arrays 40 | /named_union 41 | /save_cinit 42 | /save_json 43 | /save_scm 44 | /separate 45 | /simple_structure 46 | /simplified_grammar 47 | /specified_width 48 | /suffixes_comments_userdata 49 | /type_descriptors 50 | /type_prefixes 51 | -------------------------------------------------------------------------------- /examples/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- makefile -*- 2 | 3 | AM_CFLAGS = @AM_CFLAGS@ 4 | AM_LDFLAGS = @AM_LDFLAGS@ 5 | AM_CPPFLAGS = -I$(top_srcdir)/src 6 | LIBS += ../src/libmetaresc.la $(LIBXML2_LIBS) 7 | 8 | noinst_PROGRAMS = gjobs basic separate emptystruct justabuiltin builtins suffixes_comments_userdata arrays simple_structure specified_width enums named_union anonymous_unions type_prefixes function_pointers function_type double_pointer bitfields marshalling_structures_basic_types marshalling_enumerations marshalling_arrays marshalling_unions marshalling_pointers marshalling_pointers_to_functions deserialization_3_args deserialization_2_args deserializing_xml save_json simplified_grammar multidimensional_arrays decl_rarray save_cinit save_scm type_descriptors field_types get_set_field function_pointer_metadata array_metadata enums_metadata 9 | 10 | if HAVE_LIBDWARF 11 | noinst_PROGRAMS += dwarf dwarf_no_types 12 | endif 13 | 14 | if HAVE_BISON_FLEX 15 | noinst_PROGRAMS += load_scm load_json load_cinit 16 | endif 17 | 18 | separate_SOURCES = separate.c separate_employee.c 19 | dwarf_SOURCES = dwarf.c dwarf_types.c 20 | dwarf_no_types_SOURCES = dwarf.c 21 | dwarf_types.c: dwarf_types.h 22 | 23 | dwarf_types.h: dwarf_no_types$(EXEEXT) 24 | type dsymutil && dsymutil .libs/$? || echo "dsymutil not found" 25 | ../src/mr_dwarf .libs/$? > $@ 26 | 27 | -------------------------------------------------------------------------------- /examples/anonymous_unions.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | TYPEDEF_STRUCT (struct_t, 7 | (char *, name), 8 | ANON_UNION (), 9 | (int, x), 10 | (float, y), 11 | END_ANON_UNION (), 12 | (char *, description) 13 | ) 14 | 15 | int main () 16 | { 17 | struct_t my_struct; 18 | my_struct.name = my_struct.description = "string"; 19 | my_struct.y = 1; 20 | printf ("my_struct.x = 0x%08x my_struct.y = %f\n", my_struct.x, my_struct.y); 21 | return (EXIT_SUCCESS); 22 | } 23 | -------------------------------------------------------------------------------- /examples/array_metadata.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (example_t, 8 | (int, a1, [7]), 9 | (long, a2, [11][3]), 10 | (double, a3, [5][2][9]), 11 | (bool, a4, [7][5][3][1]), 12 | ) 13 | 14 | int print_array_field_info (mr_td_t * td, char name[]) 15 | { 16 | mr_fd_t const * fdp = mr_get_fd_by_name (td, name); 17 | 18 | if (NULL == fdp) 19 | { 20 | fprintf (stderr, 21 | "error: can't obtain type information for field '%s'\n", 22 | name); 23 | return (EXIT_FAILURE); 24 | } 25 | 26 | if (fdp->stype.mr_type != MR_TYPE_ARRAY) 27 | { 28 | fprintf (stderr, 29 | "error: the '%s' field is not an array\n", 30 | name); 31 | return (EXIT_FAILURE); 32 | } 33 | 34 | printf("field declaration: %s %s", fdp->stype.type, fdp->name.str); 35 | 36 | int i; 37 | for (i = 0; i < fdp->stype.dim.size / sizeof (fdp->stype.dim.dim[0]); ++i) 38 | printf("[%d]", (int)fdp->stype.dim.dim[i]); 39 | 40 | printf("\n"); 41 | 42 | return (EXIT_SUCCESS); 43 | } 44 | 45 | int main () 46 | { 47 | char type_name[] = "example_t"; 48 | mr_td_t * td = mr_get_td_by_name (type_name); 49 | 50 | if (NULL == td) 51 | { 52 | printf ("error: can't obtain type information for '%s'\n", 53 | type_name); 54 | return (EXIT_FAILURE); 55 | } 56 | print_array_field_info(td, "a1"); 57 | print_array_field_info(td, "a2"); 58 | print_array_field_info(td, "a3"); 59 | print_array_field_info(td, "a4"); 60 | return (EXIT_SUCCESS); 61 | } 62 | -------------------------------------------------------------------------------- /examples/arrays.c: -------------------------------------------------------------------------------- 1 | 2 | #include "arrays.h" 3 | 4 | int main () 5 | { 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /examples/arrays.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (example_t, 5 | (int, a, [11][3]) 6 | ) 7 | -------------------------------------------------------------------------------- /examples/basic.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | int 14 | main (int argc, char * argv[]) 15 | { 16 | employee_t employee = { "John", "Doe", 123456 }; 17 | MR_PRINT ((employee_t, &employee, XML)); 18 | return (EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /examples/bitfields.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "bitfields.h" 7 | 8 | int main () 9 | { 10 | date_t today; 11 | const time_t time_stamp = time (NULL); 12 | struct tm * break_down_time = localtime (&time_stamp); 13 | 14 | memset (&today, 0, sizeof(today)); 15 | today.year = break_down_time->tm_year + 1900; 16 | today.month = break_down_time->tm_mon; 17 | today.day = break_down_time->tm_mday; 18 | today.hour = break_down_time->tm_hour; 19 | today.minute = break_down_time->tm_min; 20 | 21 | MR_PRINT ("sizeof (date_t) = ", sizeof (date_t), "\n", (date_t, &today, JSON)); 22 | 23 | return (EXIT_SUCCESS); 24 | } 25 | -------------------------------------------------------------------------------- /examples/bitfields.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_ENUM (month_t, 5 | JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC) 6 | 7 | TYPEDEF_STRUCT (date_t, 8 | (unsigned int, year, :12), 9 | (month_t, month, :4), 10 | (unsigned int, day, :5), 11 | (unsigned int, hour, :5), 12 | (unsigned int, minute, :6), 13 | ) 14 | -------------------------------------------------------------------------------- /examples/builtins.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | int 9 | main (int argc, char * argv[]) 10 | { 11 | builtins_t b; 12 | memset (&b, -1, sizeof (b)); 13 | MR_PRINT ((builtins_t, &b, XML)); 14 | return (EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /examples/builtins.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (builtins_t, 5 | 6 | (char, _char), // The type char, 7 | 8 | (signed char, _schar), // the signed 9 | (short int, _short), 10 | (int, _int), 11 | (long int, _long), 12 | (long long int, _llint), 13 | 14 | (_Bool, _bool), // and unsigned integer types, 15 | (unsigned char, _uchar), 16 | (unsigned int, _uint), 17 | (unsigned short int, _ushort), 18 | (unsigned long int, _ulong), 19 | (unsigned long long int, _ull), 20 | 21 | (float, _float), // and the floating types 22 | (double, _double), 23 | (long double, _ldouble), 24 | (float _Complex, _fcompl), 25 | (double _Complex, _dcompl), 26 | (long double _Complex, _ldcompl) 27 | ) // are collectively called 28 | // the basic types. 29 | // 30 | // ISO/IEC 9899:1999, §6.2.5 (14) 31 | -------------------------------------------------------------------------------- /examples/decl_rarray.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "decl_rarray.h" 4 | 5 | static organization_t firm = { 6 | .name = "Gen-sys", 7 | .size = 3 * sizeof (employee_t), 8 | .employees = (employee_t[]){ 9 | { "Will", "Rodman", 200000 }, 10 | { "Static", "Jacobs", 250000 }, 11 | { "Robert", "Franklin", 170000 }, 12 | }, 13 | }; 14 | 15 | int main () 16 | { 17 | MR_PRINT ((organization_t, &firm, JSON)); 18 | return (EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /examples/decl_rarray.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (employee_t, 5 | (char *, firstname), 6 | (char *, lastname), 7 | int salary 8 | ) 9 | 10 | TYPEDEF_STRUCT (organization_t, 11 | (char *, name), 12 | (employee_t *, employees, /* suffix */ , /* meta */ , { "size" }, "string"), 13 | VOID (ssize_t, size), 14 | ) 15 | -------------------------------------------------------------------------------- /examples/deserialization_2_args.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | int 14 | main (int argc, char * argv[]) 15 | { 16 | char source[] = 17 | "" 18 | "" 19 | "John" 20 | "Doe" 21 | "123456" 22 | ""; 23 | 24 | employee_t employee = MR_LOAD_XML (employee_t, source); 25 | printf ("%11s: %s\n" 26 | "%11s: %s\n" 27 | "%11s: %u\n", 28 | "firstname", employee.firstname, 29 | "lastname", employee.lastname, 30 | "salary", employee.salary); 31 | 32 | return (EXIT_SUCCESS); 33 | } 34 | -------------------------------------------------------------------------------- /examples/deserialization_3_args.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | int 14 | main (int argc, char * argv[]) 15 | { 16 | char source[] = 17 | "" 18 | "" 19 | "John" 20 | "Doe" 21 | "123456" 22 | ""; 23 | 24 | employee_t employee; 25 | 26 | if (MR_SUCCESS != MR_LOAD_XML (employee_t, source, &employee)) 27 | fprintf (stderr, "De-serialization error has occurred.\n"); 28 | else 29 | { 30 | printf ("%11s: %s\n" 31 | "%11s: %s\n" 32 | "%11s: %u\n", 33 | "firstname", employee.firstname, 34 | "lastname", employee.lastname, 35 | "salary", employee.salary); 36 | } 37 | return (EXIT_SUCCESS); 38 | } 39 | -------------------------------------------------------------------------------- /examples/deserializing_xml.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | int 14 | main (int argc, char * argv[]) 15 | { 16 | char xml[] = 17 | "" 18 | "" 19 | "John" 20 | "Doe" 21 | "123456" 22 | ""; 23 | 24 | employee_t employee = MR_LOAD_XML (employee_t, xml); 25 | 26 | printf ( 27 | "First name: %s\nLast name: %s\nSalary: %u\n", 28 | employee.firstname, employee.lastname, employee.salary); 29 | 30 | return (EXIT_SUCCESS); 31 | } 32 | -------------------------------------------------------------------------------- /examples/double_pointer.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | TYPEDEF_STRUCT (int_dbl_pointer_t, 9 | (struct int_pointer_t *, ip_ptr), 10 | (int *, ptr) 11 | ) 12 | 13 | TYPEDEF_STRUCT (int_pointer_t, 14 | (int *, ptr) 15 | ) 16 | 17 | int main () 18 | { 19 | int x = 1234; 20 | int y = 4321; 21 | int_pointer_t x_ptr = { &x }; 22 | int_dbl_pointer_t idp = { &x_ptr, &y }; 23 | MR_PRINT ((int_dbl_pointer_t, &idp, XML)); 24 | return (EXIT_SUCCESS); 25 | } 26 | -------------------------------------------------------------------------------- /examples/dwarf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef struct tree_node_t { 5 | char * value; 6 | struct tree_node_t * left, * right; 7 | } tree_node_t; 8 | 9 | static tree_node_t root = { 10 | "root", 11 | (tree_node_t[]) { { "left" } }, 12 | (tree_node_t[]) { { "right" } }, 13 | }; 14 | 15 | int main (int argc, char * argv[]) 16 | { 17 | MR_PRINT ("root = ", (tree_node_t, &root)); 18 | return (EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /examples/dwarf_types.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static mr_dwarf_t mr_dwarf = 4 | #include "dwarf_types.h" 5 | ; 6 | 7 | static inline void __attribute__((constructor)) dwarf_types (void) { mr_add_dwarf (&mr_dwarf); } 8 | -------------------------------------------------------------------------------- /examples/emptystruct.c: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* This file is a part of Metaresc project */ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | int 11 | main (int argc, char * argv[]) 12 | { 13 | return (EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /examples/emptystruct.h: -------------------------------------------------------------------------------- 1 | #include 2 | // equivalent to the following: 3 | TYPEDEF_STRUCT (empty_t) // typedef struct { } empty_t; 4 | // and some METARESC meta-data magic 5 | -------------------------------------------------------------------------------- /examples/enums.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "enums.h" 6 | 7 | TYPEDEF_STRUCT (character_place_t, 8 | char c, 9 | (color_t, fg), 10 | (color_t, bg) 11 | ) 12 | 13 | int main () 14 | { 15 | mr_td_t * tdp = mr_get_td_by_name ("color_t"); 16 | MR_PRINT ("color_t enum desciptor\n", (mr_td_t, tdp)); 17 | MR_PRINT ("RED: ", RED, "\n", 18 | "ORANGE: ", ORANGE, "\n", 19 | "YELLOW: ", YELLOW, "\n", 20 | "GREEN: ", GREEN, "\n", 21 | "BLUE: ", BLUE, "\n", 22 | "PURPLE: ", PURPLE, "\n", 23 | "PINK: ", PINK, "\n", 24 | "BROWN: ", BROWN, "\n"); 25 | 26 | character_place_t place = { 'A', RED, BROWN }; 27 | MR_PRINT ("place = ", (character_place_t, &place)); 28 | 29 | return (EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /examples/enums.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_ENUM (color_t, ATTRIBUTES (__attribute__ ((packed))), 5 | RED, /* auto-enumerated and becomes 0 */ 6 | (ORANGE), /* auto-enumerated and becomes 1 */ 7 | 8 | (YELLOW, = 2), /* explicitly set to 2 */ 9 | (GREEN, = 3, "set to 3 - this is a textual meta info"), 10 | (BLUE, , "auto-enumerated", { "a void pointer for arbitrary resource" }), 11 | 12 | (PURPLE, 13 | /* value argument may be empty */, 14 | "becomes 5", 15 | { "next argument is a type of this poiner" }, 16 | "string" 17 | ), 18 | 19 | (PINK, 20 | /* auto-enumerated */, 21 | /* no meta */, 22 | { (color_t[]){ PINK } }, 23 | "color_t" /* type itself might be used for initialization of resource */ 24 | ), 25 | 26 | (BROWN, 27 | /* auto-enumerated */, 28 | /* no meta */, 29 | { (color_t[]){ RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE, PINK, BROWN } }, 30 | "color_t", 31 | 8 * sizeof (color_t) /* size of resource array */ 32 | ) /* trailing comma is optional */ 33 | ); 34 | -------------------------------------------------------------------------------- /examples/enums_metadata.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | TYPEDEF_ENUM (color_t, 9 | (BLACK, = 8), 10 | (RED), 11 | (GREEN, = 2), 12 | (YELLOW, = 3), 13 | (BLUE, = 4), 14 | MAGENTA, 15 | CYAN, 16 | WHITE 17 | ) 18 | 19 | int main () 20 | { 21 | mr_conf_init (); 22 | 23 | char * type_name = "color_t"; 24 | mr_td_t * tdp = mr_get_td_by_name (type_name); 25 | 26 | if (NULL == tdp) 27 | { 28 | fprintf (stderr, 29 | "error: can't obtain type information for '%s'\n", 30 | type_name); 31 | return (EXIT_FAILURE); 32 | } 33 | 34 | int i, count = tdp->param.enum_param.enums_size / sizeof (tdp->param.enum_param.enums[0]); 35 | for (i = 0; i < count; ++i) 36 | { 37 | mr_ed_t * edp = tdp->param.enum_param.enums[i]; 38 | printf ("%d: %s = %" PRIu64 "\n", i, edp->name.str, edp->value._unsigned); 39 | } 40 | return (EXIT_SUCCESS); 41 | } 42 | -------------------------------------------------------------------------------- /examples/field_types.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | TYPEDEF_STRUCT (employee_t, 9 | (char *, firstname), 10 | (char *, lastname), 11 | (int, salary), 12 | ) 13 | 14 | int main () 15 | { 16 | char name[] = "employee_t"; 17 | mr_td_t * tdp = mr_get_td_by_name(name); 18 | int i, count; 19 | 20 | if (NULL == tdp) 21 | { 22 | printf ("error: can't obtain type information for '%s'\n", name); 23 | return (EXIT_FAILURE); 24 | } 25 | 26 | count = tdp->param.struct_param.fields_size / sizeof (tdp->param.struct_param.fields[0]); 27 | for (i = 0; i < count; ++i) 28 | { 29 | mr_fd_t * fdp = tdp->param.struct_param.fields[i]; 30 | printf("\t%d: name = %s, type = %s, size = %u bytes\n", 31 | i, fdp->name.str, fdp->stype.type, fdp->stype.size); 32 | } 33 | 34 | return (EXIT_SUCCESS); 35 | } 36 | -------------------------------------------------------------------------------- /examples/function_pointer_metadata.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (ops, 8 | (double, add, (float, int)), 9 | (double, subtract, (float, int)), 10 | (double, multiply, (float, int)), 11 | (double, divide, (float, int)) 12 | ) 13 | 14 | int print_func_field_signature (mr_fd_t const * fdp) 15 | { 16 | int i; 17 | 18 | if (fdp->stype.mr_type != MR_TYPE_FUNC) 19 | { 20 | fprintf(stderr, 21 | "error: the field '%s' is not a pointer to function\n", 22 | fdp->name.str); 23 | return (EXIT_FAILURE); 24 | } 25 | 26 | size_t const num_args = fdp->func_param.size / sizeof (fdp->func_param.args[0]); 27 | 28 | printf ("%s (*) (", fdp->func_param.args[0]->type); 29 | 30 | for (i = 1; i < num_args; ++i) 31 | { 32 | if (i > 1) 33 | printf(", "); 34 | 35 | printf ("%s", fdp->func_param.args[i]->type); 36 | } 37 | 38 | printf (")\n"); 39 | return (EXIT_SUCCESS); 40 | } 41 | 42 | int main () 43 | { 44 | char type_name[] = "ops"; 45 | char field_name[] = "subtract"; 46 | 47 | mr_conf_init (); 48 | 49 | mr_td_t * td = mr_get_td_by_name (type_name); 50 | 51 | if (NULL == td) 52 | { 53 | fprintf (stderr, 54 | "error: can't obtain type information for '%s'\n", 55 | type_name); 56 | return (EXIT_FAILURE); 57 | } 58 | 59 | mr_fd_t const * fdp = mr_get_fd_by_name (td, field_name); 60 | 61 | if (NULL == fdp) 62 | { 63 | fprintf (stderr, 64 | "error: can't obtain type information for '%s' in '%s'\n", 65 | field_name, type_name); 66 | return (EXIT_FAILURE); 67 | } 68 | 69 | printf ("field '%s' has type name '%s'\n", field_name, fdp->stype.type); 70 | printf ("the actual type: "); 71 | return (print_func_field_signature (fdp)); 72 | } 73 | -------------------------------------------------------------------------------- /examples/function_pointers.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (with_f_pointers_t, 8 | (char *, pfunc, (int)) 9 | ) 10 | 11 | int main () 12 | { 13 | MR_PRINT ("with_f_pointers_t = ", (mr_td_t, mr_get_td_by_name ("with_f_pointers_t"))); 14 | return (EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /examples/function_type.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_FUNC (ATTRIBUTES (__attribute__ ((aligned (sizeof (int64_t)))) , "function type sample"), int, func_t, (char *, int, int *, double)) 8 | 9 | int main () 10 | { 11 | MR_PRINT ("func_t = ", (mr_td_t, mr_get_td_by_name ("func_t"))); 12 | return (EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /examples/get_set_field.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | TYPEDEF_STRUCT (employee_t, 7 | (char *, firstname), 8 | (char *, lastname), 9 | (int, salary), 10 | ) 11 | 12 | void print_employee_info (employee_t const * employee) 13 | { 14 | printf ("employee:\n" 15 | "\tfirst name: %s\n" 16 | "\tlast name: %s\n" 17 | "\tsalary: %u\n", 18 | employee->firstname, employee->lastname, employee->salary); 19 | } 20 | 21 | int main () 22 | { 23 | employee_t employee = { "John", "Smith", 7350 }; 24 | 25 | char type_name[] = "employee_t"; 26 | char field_name[] = "salary"; 27 | 28 | mr_td_t * td = mr_get_td_by_name (type_name); 29 | 30 | if (NULL == td) 31 | { 32 | printf("error: can't obtain type information for '%s'\n", type_name); 33 | return (EXIT_FAILURE); 34 | } 35 | 36 | mr_fd_t * fd = mr_get_fd_by_name (td, field_name); 37 | 38 | if (NULL == fd) 39 | { 40 | printf("error: can't obtain type information for field '%s' in '%s'\n", 41 | field_name, type_name); 42 | return (EXIT_FAILURE); 43 | } 44 | 45 | size_t const offset = fd->offset; 46 | 47 | printf ("the value of field '%s' in variable employee is: %i\n", 48 | field_name, *(int*)(((char*)&employee) + offset)); 49 | 50 | printf ("setting field '%s' in variable employee...\n", field_name); 51 | *(int*)(((char*)&employee) + offset) = 9170; 52 | 53 | puts ("printing variable employee..."); 54 | print_employee_info (&employee); 55 | 56 | return (EXIT_SUCCESS); 57 | } 58 | -------------------------------------------------------------------------------- /examples/gjobs.c: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | TYPEDEF_STRUCT (project_t, int ID) // typedef struct project_t { int ID } project_t; 12 | 13 | TYPEDEF_ENUM (status_t, 14 | Open, 15 | Close, 16 | ) 17 | 18 | TYPEDEF_STRUCT (update_t, 19 | (status_t, Status), 20 | string_t Modified, 21 | string_t Salary, 22 | ) 23 | 24 | TYPEDEF_STRUCT (person_t, 25 | string_t Person, 26 | string_t Email, 27 | string_t Company, 28 | string_t Organisation, 29 | string_t Webpage, 30 | string_t Snailmail, 31 | string_t Phone, 32 | ) 33 | 34 | TYPEDEF_STRUCT (job_t, 35 | (project_t, Project), 36 | string_t Application, 37 | string_t Category, 38 | (update_t, Update), 39 | (person_t *, Developers, /* suffix */, /* meta */, { .offset = offsetof (job_t, Developers_size) }, "offset"), 40 | VOID (ssize_t, Developers_size), 41 | (person_t, Contact), 42 | string_t Requirements, 43 | string_t Skills, 44 | string_t Details, 45 | ) 46 | 47 | TYPEDEF_STRUCT (helping_t, 48 | (job_t *, Jobs, /* suffix */ , /* meta */, { .offset = offsetof (helping_t, Jobs_size) }, "offset" ), 49 | VOID (ssize_t, Jobs_size), 50 | ) 51 | 52 | static void 53 | print_person (person_t * person) 54 | { 55 | if (person == NULL) return; 56 | printf ("------ Person\n"); 57 | if (person->Person) printf (" name: %s\n", person->Person); 58 | if (person->Email) printf (" email: %s\n", person->Email); 59 | if (person->Company) printf (" company: %s\n", person->Company); 60 | if (person->Organisation) printf (" organisation: %s\n", person->Organisation); 61 | if (person->Snailmail) printf (" smail: %s\n", person->Snailmail); 62 | if (person->Webpage) printf (" Web: %s\n", person->Webpage); 63 | if (person->Phone) printf (" phone: %s\n", person->Phone); 64 | printf ("------\n"); 65 | } 66 | 67 | static void 68 | print_job (job_t * job) 69 | { 70 | int i; 71 | int developers; 72 | 73 | if (job == NULL) return; 74 | printf ("======= Job\n"); 75 | printf ("projectID: %d\n", job->Project.ID); 76 | if (job->Application != NULL) printf ("application: %s\n", job->Application); 77 | if (job->Category != NULL) printf ("category: %s\n", job->Category); 78 | print_person (&job->Contact); 79 | developers = job->Developers_size / sizeof (job->Developers[0]); 80 | printf ("%d developers\n", developers); 81 | 82 | for (i = 0; i < developers; ++i) 83 | print_person (&job->Developers[i]); 84 | printf ("======= \n"); 85 | } 86 | 87 | static void 88 | print_helping (helping_t * helping) 89 | { 90 | int i; 91 | int jobs = helping->Jobs_size / sizeof (helping->Jobs[0]); 92 | printf ("%d Jobs registered\n", jobs); 93 | for (i = 0; i < jobs; ++i) 94 | print_job (&helping->Jobs[i]); 95 | } 96 | 97 | int 98 | main (int argc, char * argv[]) 99 | { 100 | helping_t helping; 101 | 102 | #ifdef HAVE_LIBXML2 103 | LIBXML_TEST_VERSION; 104 | #endif /* HAVE_LIBXML2 */ 105 | 106 | char * xml = mr_read_xml_doc (stdin); 107 | if (NULL == xml) 108 | printf ("mr_read_xml_doc failed\n"); 109 | else 110 | { 111 | memset (&helping, 0, sizeof (helping)); 112 | if (MR_SUCCESS != MR_LOAD_XML (helping_t, xml, &helping)) 113 | printf ("Load failed\n"); 114 | else 115 | print_helping (&helping); 116 | MR_FREE_RECURSIVELY (helping_t, &helping); 117 | MR_FREE (xml); 118 | } 119 | 120 | /* Clean up everything else before quitting. */ 121 | #ifdef HAVE_LIBXML2 122 | xmlCleanupParser(); 123 | #endif /* HAVE_LIBXML2 */ 124 | return (EXIT_SUCCESS); 125 | } 126 | -------------------------------------------------------------------------------- /examples/gjobs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 3 8 | 9 | GBackup 10 | Development 11 | 12 | 13 | Open 14 | Mon, 07 Jun 1999 20:27:45 -0400 MET DST 15 | USD 0.00 16 | 17 | 18 | 19 | 20 | Jason Venner 21 | jvener@mirantis.com 22 | Mirantis, Inc 23 | 24 | 25 | http://mirantis.com/ 26 | 615 National av., Mountain View, CA, 94043 27 | +1 (650) 465-8798 28 | 29 | 30 | 31 | 32 | Nathan Clemons 33 | nathan@windsofstorm.net 34 | FooBar Software 35 | 36 | 37 | web://foobarsoftware/ 38 | 321 Hillview Court, Somewhere-city, ZQ 54312, Zimbovia 39 | 011 4321 917 123 45 67 40 | 41 | 42 | 43 | The program should be released as free software, under the FreeBSD license. 44 | 45 | 46 | 47 | 48 | 49 | 50 | A GNOME based system that will allow a superuser to configure 51 | compressed and uncompressed files and/or file systems to be backed 52 | up with a supported media in the system. This should be able to 53 | perform via find commands generating a list of files that are passed 54 | to tar, dd, cpio, cp, gzip, etc., to be directed to the tape machine 55 | or via operations performed on the filesystem itself. Email 56 | notification and GUI status display very important. 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /examples/justabuiltin.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | int 8 | main (int argc, char * argv[]) 9 | { 10 | int x = 5; 11 | MR_PRINT (( , &x, XML)); 12 | return (EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /examples/load_cinit.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | void print_info (employee_t const * e) 14 | { 15 | printf ("First name: %s\nLast name: %s\nSalary: %u\n", 16 | e->firstname, e->lastname, e->salary); 17 | } 18 | 19 | int main (int argc, char * argv[]) 20 | { 21 | char serialized[] = 22 | "{" "\n" 23 | " .firstname = \"John\", " "\n" 24 | " .lastname = \"Doe\", " "\n" 25 | " .salary = 123456, " "\n" 26 | "}" "\n"; 27 | 28 | employee_t employee = MR_LOAD_CINIT (employee_t, serialized); 29 | 30 | print_info (&employee); 31 | MR_FREE_RECURSIVELY (employee_t, &employee); 32 | 33 | char corrupted[] = "this is not a Scheme language text"; 34 | 35 | if (MR_SUCCESS == MR_LOAD_CINIT (employee_t, corrupted, &employee)) 36 | printf ("Parsing successfull (unexpected behavior)\n"); 37 | else 38 | printf ("Parsing error (expected behavior)\n"); 39 | 40 | return (EXIT_SUCCESS); 41 | } 42 | -------------------------------------------------------------------------------- /examples/load_json.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | void print_info (employee_t const * e) 14 | { 15 | printf ("First name: %s\nLast name: %s\nSalary: %u\n", 16 | e->firstname, e->lastname, e->salary); 17 | } 18 | 19 | int main (int argc, char * argv[]) 20 | { 21 | char serialized[] = 22 | "{" "\n" 23 | " \"firstname\" : \"John\"," "\n" 24 | " \"lastname\" : \"Doe\"," "\n" 25 | " \"salary\" : 123456," "\n" 26 | "}" "\n"; 27 | 28 | employee_t employee = MR_LOAD_JSON (employee_t, serialized); 29 | 30 | print_info (&employee); 31 | MR_FREE_RECURSIVELY (employee_t, &employee); 32 | 33 | char corrupted[] = "this is not a Scheme language text"; 34 | 35 | if (MR_SUCCESS == MR_LOAD_JSON (employee_t, corrupted, &employee)) 36 | printf ("Parsing successfull (unexpected behavior)\n"); 37 | else 38 | printf ("Parsing error (expected behavior)\n"); 39 | 40 | return (EXIT_SUCCESS); 41 | } 42 | -------------------------------------------------------------------------------- /examples/load_scm.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | void print_info (employee_t const * e) 14 | { 15 | printf ("First name: %s\nLast name: %s\nSalary: %u\n", 16 | e->firstname, e->lastname, e->salary); 17 | } 18 | 19 | int main (int argc, char * argv[]) 20 | { 21 | char serialized[] = 22 | "( \n" 23 | " (\"John\" . firstname) \n" 24 | " (\"Doe\" . lastname) \n" 25 | " (123456 . salary)) \n" 26 | ; 27 | 28 | employee_t employee = MR_LOAD_SCM (employee_t, serialized); 29 | 30 | print_info (&employee); 31 | MR_FREE_RECURSIVELY (employee_t, &employee); 32 | 33 | char corrupted[] = "this is not a Scheme language text"; 34 | 35 | if (MR_SUCCESS == MR_LOAD_SCM (employee_t, corrupted, &employee)) 36 | printf ("Parsing successfull (unexpected behavior)\n"); 37 | else 38 | printf ("Parsing error (expected behavior)\n"); 39 | 40 | return (EXIT_SUCCESS); 41 | } 42 | -------------------------------------------------------------------------------- /examples/marshalling_arrays.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "marshalling_arrays.h" 6 | 7 | int main () 8 | { 9 | array_t a = { .a = { 11, 17, 23 } }; 10 | array2d_t a2d = { { {1, 2}, {3, 4} } }; 11 | MR_PRINT ((array_t, &a, XML), (array2d_t, &a2d, XML)); 12 | return (EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /examples/marshalling_arrays.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (array_t, 5 | (int, a, [3]) 6 | ) 7 | 8 | TYPEDEF_STRUCT (array2d_t, 9 | (int, a, [2][2]) 10 | ) 11 | -------------------------------------------------------------------------------- /examples/marshalling_enumerations.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "marshalling_enumerations.h" 6 | 7 | int main () 8 | { 9 | screen_t screen = { 10 | .width = 80, 11 | .height = 25, 12 | .bg = BLACK, 13 | .fg = WHITE 14 | }; 15 | 16 | MR_PRINT ((screen_t, &screen, XML)); 17 | return (EXIT_SUCCESS); 18 | } 19 | -------------------------------------------------------------------------------- /examples/marshalling_enumerations.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_ENUM (color_t, 5 | (BLACK), 6 | (RED, = 1), 7 | (GREEN, ), 8 | (YELLOW), 9 | (BLUE, = 4), 10 | (MAGENTA, = 5), 11 | (CYAN, = 6), 12 | (WHITE, = 7) 13 | ) 14 | 15 | TYPEDEF_STRUCT (screen_t, 16 | (int, width), 17 | (int, height), 18 | (color_t, bg), 19 | (color_t, fg) 20 | ) 21 | -------------------------------------------------------------------------------- /examples/marshalling_pointers.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "marshalling_pointers.h" 6 | 7 | int main () 8 | { 9 | back_end_server_t server1 = { 10 | .id = 3, 11 | .address = 0x12341234, 12 | .port = 80 13 | }; 14 | back_end_server_t server2 = { 15 | .id = 11, 16 | .address = 0x43214321, 17 | .port = 443 18 | }; 19 | 20 | filter_t filter1 = { 123 }; 21 | filter_t __attribute__ ((unused)) filter2 = { 321 }; 22 | 23 | policy_t policy = { 24 | .server_a = &server1, 25 | .server_b = &server2, 26 | .f = &filter1, 27 | .fallback = &server2 28 | }; 29 | 30 | MR_PRINT ((policy_t, &policy, XML)); 31 | return (EXIT_SUCCESS); 32 | } 33 | -------------------------------------------------------------------------------- /examples/marshalling_pointers.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (back_end_server_t, 5 | (int, id), 6 | (unsigned long int, address), 7 | (unsigned short int, port) 8 | ) 9 | 10 | typedef struct { 11 | int data; 12 | } filter_t; 13 | 14 | TYPEDEF_STRUCT (policy_t, 15 | (back_end_server_t *, server_a), 16 | (back_end_server_t *, server_b), 17 | (filter_t *, f), 18 | (back_end_server_t *, fallback) 19 | ) 20 | -------------------------------------------------------------------------------- /examples/marshalling_pointers_to_functions.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "marshalling_pointers_to_functions.h" 5 | 6 | int main () 7 | { 8 | with_functions_t with_functions = { 9 | .value = 7, 10 | .func = puts 11 | }; 12 | MR_PRINT ((with_functions_t, &with_functions, XML)); 13 | return (EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /examples/marshalling_pointers_to_functions.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (with_functions_t, 5 | (int, value), 6 | (int, func, (char const*)) 7 | ) 8 | -------------------------------------------------------------------------------- /examples/marshalling_structures_basic_types.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "marshalling_structures_basic_types.h" 4 | 5 | int main () 6 | { 7 | basics_t b = { 8 | .c = 'Z', 9 | .uli = 123, 10 | .fl = { 11 | .f = 0.3f, 12 | .ld = 3.14, 13 | .dc = 7.42 14 | } 15 | }; 16 | 17 | MR_PRINT ((basics_t, &b, XML)); 18 | return (EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /examples/marshalling_structures_basic_types.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (floatings_t, 5 | (float, f), 6 | (long double, ld), 7 | (double _Complex, dc) 8 | ) 9 | 10 | TYPEDEF_STRUCT (basics_t, 11 | (char, c), 12 | (unsigned long int, uli), 13 | (floatings_t, fl) 14 | ) 15 | -------------------------------------------------------------------------------- /examples/marshalling_unions.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | TYPEDEF_ENUM (union_discriminator_t, 9 | (UD_VOID_PTR, , "void_ptr"), 10 | (UD_UC_ARRAY, , "uc_array"), 11 | (UD_U32, , "u32"), 12 | (UD_FLOAT_VAL, , "float_val") 13 | ) 14 | 15 | TYPEDEF_UNION (union_t, 16 | (void *, void_ptr), 17 | (unsigned char, uc_array, [sizeof (float)]), 18 | (uint32_t, u32), 19 | (float, float_val) 20 | ) 21 | 22 | TYPEDEF_STRUCT (discriminated_union_t, 23 | (union_t, union_val, , "union_discriminator"), 24 | (union_discriminator_t, union_discriminator) 25 | ) 26 | 27 | int main () 28 | { 29 | discriminated_union_t u = { { .float_val = 3.1415926 }, UD_UC_ARRAY }; 30 | MR_PRINT ((discriminated_union_t, &u, XML)); 31 | return (EXIT_SUCCESS); 32 | } 33 | -------------------------------------------------------------------------------- /examples/multidimensional_arrays.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (box_t, 8 | (char *, name), 9 | (time_t, creation_time) 10 | ) 11 | 12 | TYPEDEF_STRUCT (voxel_t, 13 | (box_t *, pbox) 14 | ) 15 | 16 | TYPEDEF_STRUCT (plane_t, 17 | (voxel_t, points, [2][2]), 18 | ) 19 | 20 | TYPEDEF_STRUCT (space_t, 21 | (plane_t, planes, [2]), 22 | ) 23 | 24 | int main () 25 | { 26 | space_t space; 27 | box_t box = { .name = "some name", .creation_time = time (NULL) }; 28 | 29 | memset (&space, 0, sizeof(space)); 30 | 31 | space.planes[0].points[0][0].pbox = &box; 32 | 33 | // here we will serialize and print to console 34 | MR_PRINT ("space_t space = ", (space_t, &space)); 35 | 36 | return (EXIT_SUCCESS); 37 | } 38 | -------------------------------------------------------------------------------- /examples/named_union.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "named_union.h" 4 | 5 | int main () 6 | { 7 | return (EXIT_SUCCESS); 8 | } 9 | -------------------------------------------------------------------------------- /examples/named_union.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_UNION (named_union_t, 5 | (int, a), 6 | (char, c), 7 | (long double, ld) 8 | ) 9 | -------------------------------------------------------------------------------- /examples/save_cinit.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | int 14 | main (int argc, char * argv[]) 15 | { 16 | employee_t employee = { "John", "Doe", 123456 }; 17 | MR_PRINT ("employee = ", (employee_t, &employee)); 18 | return (EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /examples/save_json.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | int 14 | main (int argc, char * argv[]) 15 | { 16 | employee_t employee = { "John", "Doe", 123456 }; 17 | MR_PRINT ((employee_t, &employee, JSON)); 18 | return (EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /examples/save_scm.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (employee_t, 8 | (char *, firstname), 9 | (char *, lastname), 10 | (int, salary), 11 | ) 12 | 13 | int 14 | main (int argc, char * argv[]) 15 | { 16 | employee_t employee = { "John", "Doe", 123456 }; 17 | MR_PRINT ((employee_t, &employee, SCM), "\n"); 18 | return (EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /examples/separate.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "separate_employee.h" 6 | 7 | int 8 | main (int argc, char * argv[]) 9 | { 10 | employee_t employee = create_employee ("John", "Doe", 123456); 11 | MR_PRINT ((employee_t, &employee, XML)); 12 | return (EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /examples/separate_employee.c: -------------------------------------------------------------------------------- 1 | 2 | #include "separate_employee.h" 3 | 4 | #undef MR_MODE 5 | #define MR_MODE DESC 6 | #include "separate_employee_decl.h" 7 | 8 | employee_t create_employee ( 9 | char const * firstname, 10 | char const * lastname, 11 | int salary) 12 | { 13 | employee_t employee; 14 | 15 | employee.firstname = firstname; 16 | employee.lastname = lastname; 17 | employee.salary = salary; 18 | 19 | return (employee); 20 | } 21 | -------------------------------------------------------------------------------- /examples/separate_employee.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _METARESC_EXAMPLES_SEPARATE_EMPLOYEE_H_INCLUDED_ 3 | #define _METARESC_EXAMPLES_SEPARATE_EMPLOYEE_H_INCLUDED_ 4 | 5 | #define MR_MODE PROTO 6 | #include "separate_employee_decl.h" 7 | 8 | employee_t create_employee ( 9 | char const * firstname, 10 | char const * lastname, 11 | int salary); 12 | 13 | #endif /* _METARESC_EXAMPLES_SEPARATE_EMPLOYEE_H_INCLUDED_ */ 14 | -------------------------------------------------------------------------------- /examples/separate_employee_decl.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (employee_t, 5 | (char const *,firstname), 6 | (char const *, lastname), 7 | (int, salary), 8 | ) 9 | 10 | // no guardian here! 11 | -------------------------------------------------------------------------------- /examples/simple_structure.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "simple_structure.h" 4 | 5 | int main () 6 | { 7 | return (EXIT_SUCCESS); 8 | } 9 | -------------------------------------------------------------------------------- /examples/simple_structure.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (employee_t, 5 | (char *, firstname), 6 | (char *, lastname), 7 | (int, salary), 8 | ) 9 | -------------------------------------------------------------------------------- /examples/simplified_grammar.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "simplified_grammar.h" 6 | 7 | int main () 8 | { 9 | event_t ev = { .x = 11, .y = 17, .z = 31 }; 10 | MR_PRINT ("event_t ev = ", (event_t, &ev)); 11 | return (EXIT_SUCCESS); 12 | } 13 | -------------------------------------------------------------------------------- /examples/simplified_grammar.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (event_t, 5 | int x, 6 | int y, 7 | volatile unsigned long long int const z 8 | ) 9 | -------------------------------------------------------------------------------- /examples/specified_width.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "specified_width.h" 6 | 7 | int main () 8 | { 9 | specified_width_t b; 10 | memset (&b, 0, sizeof (b)); 11 | return (EXIT_SUCCESS); 12 | } 13 | -------------------------------------------------------------------------------- /examples/specified_width.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | TYPEDEF_STRUCT (specified_width_t, 6 | (int16_t, si16), 7 | (uint64_t, ui64), 8 | (int_least32_t, sil32), 9 | (int_fast32_t, sif32), 10 | (uintptr_t, uip), 11 | (intmax_t, sim) 12 | ) 13 | -------------------------------------------------------------------------------- /examples/suffixes_comments_userdata.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "suffixes_comments_userdata.h" 6 | 7 | int main () 8 | { 9 | char type[] = "example_t"; 10 | mr_td_t * td = mr_get_td_by_name (type); 11 | if (NULL == td) 12 | printf ("error: can't obtain type information for type '%s'\n", type); 13 | else 14 | MR_PRINT ("Type desciptor for type '", type, "' is\n", (mr_td_t, td)); 15 | return (EXIT_SUCCESS); 16 | } 17 | -------------------------------------------------------------------------------- /examples/suffixes_comments_userdata.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | TYPEDEF_STRUCT (example_t, 5 | /* optional argument with meta data for type itself */ 6 | ATTRIBUTES (__attribute__((packed)), "Comment on type", { "auxiliary void pointer" }, "char" /* type of aux ptr */), 7 | /* all 4 arguments of ATTRIBUTES are optional */ 8 | (int, x1), /* (type, name) */ 9 | (int, x2, [3]), /* (type, name, suffix) */ 10 | (double, x3, /* empty */, "Text comment for the field"), /* (type, name, suffix, meta) */ 11 | /* (type, name, suffix, meta, { void_ptr }, type_of_void_ptr_as_string) */ 12 | (float, x4, /* empty */, /* empty */, { "auxiliary void pointer" }, "char"), 13 | /* (type, name, suffix, meta, { void_ptr }, type_of_void_ptr_as_string, size_of_void_ptr) */ 14 | (long double, x5, /* empty */, /* empty */, 15 | { (example_t[]){ { .x1 = 1, .x3 = 1.1 }, { .x1 = 2, .x3 = 2.2 } } }, "example_t", 2 * sizeof (example_t)), 16 | int x6, 17 | volatile const unsigned long long int x7, 18 | string_t x8 19 | ) 20 | -------------------------------------------------------------------------------- /examples/type_descriptors.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | TYPEDEF_STRUCT (employee_t, 7 | (char *, firstname), 8 | (char *, lastname), 9 | (int, salary), 10 | ) 11 | 12 | int main () 13 | { 14 | char type[] = "employee_t"; 15 | mr_td_t const * td = mr_get_td_by_name (type); 16 | 17 | if (td) 18 | { 19 | printf ("information for '%s':\n", type); 20 | char const * type_class = NULL; 21 | 22 | switch (td->mr_type) 23 | { 24 | case MR_TYPE_STRUCT: 25 | type_class = "a struct"; 26 | break; 27 | case MR_TYPE_ENUM: 28 | type_class = "an enumeration"; 29 | break; 30 | case MR_TYPE_UNION: 31 | type_class = "a union"; 32 | break; 33 | default: 34 | type_class = "an unknown type"; 35 | } 36 | 37 | printf ("\t%s is %s\n", type, type_class); 38 | printf ("\tit's declared name is '%s'\n", td->type.str); 39 | printf ("\tvariables of this type occupy %u bytes of memory\n", td->size); 40 | } 41 | else 42 | { 43 | printf ("error: can't obtain type information for type '%s'\n", type); 44 | } 45 | 46 | return (EXIT_SUCCESS); 47 | } 48 | -------------------------------------------------------------------------------- /examples/type_prefixes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "type_prefixes.h" 3 | 4 | int main () 5 | { 6 | MR_PRINT ("mr_conf = ", (mr_conf_t, &mr_conf)); 7 | return (EXIT_SUCCESS); 8 | } 9 | -------------------------------------------------------------------------------- /examples/type_prefixes.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | typedef struct { 5 | int x, * p, a[2], a2d[2][2], (*f)(int); /* legal C declaration */ 6 | } s1_t; 7 | 8 | /* Metaresc equivalent */ 9 | TYPEDEF_STRUCT (s2_t, 10 | (int, x), 11 | (int *, p), 12 | (int, a, [2]), 13 | (int, a2d, [2][2]), 14 | (int, f, (int)), 15 | ) 16 | -------------------------------------------------------------------------------- /gcov/check_gcov.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | make -j check 4 | 5 | cd src 6 | 7 | gcov -b -o .libs ../../src/*.c | tee ../gcov.log -------------------------------------------------------------------------------- /gcov/configure_gcov.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | ../configure CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage" 3 | -------------------------------------------------------------------------------- /huge_enterprise_app/Makefile: -------------------------------------------------------------------------------- 1 | 2 | NUMFILES ?= 100 3 | 4 | BINARY = huge_enterprise_app 5 | 6 | CFLAGS += -Wall -I../src `xml2-config --cflags` 7 | LDADD += ../src/.libs/libmetaresc.a `xml2-config --libs` 8 | 9 | all: ${BINARY} 10 | 11 | SOURCES = $(shell seq -f file_%05g.c -s " " ${NUMFILES}) main.c 12 | 13 | ${BINARY}: $(patsubst %.c,%.o, ${SOURCES}) 14 | ${CC} -o $@ $? ${LDADD} 15 | 16 | main.c: main.h 17 | 18 | file_%.c: file_%.h main.h 19 | sed -e s/@FILENO@/$(patsubst file_%.c,%,$@)/ < file.c.in > $@ 20 | 21 | file_%.h: 22 | sed -e s/@FILENO@/$(patsubst file_%.h,%,$@)/ < file.h.in > $@ 23 | 24 | main.h: $(patsubst %.c, %.h, $(patsubst main.c, , ${SOURCES})) 25 | echo -e "#ifndef _MAIN_H_\n#define _MAIN_H_\n" $(patsubst %,"#include \"%\"\n", $?) "#endif\n" > main.h 26 | 27 | clean: 28 | @${RM} ${BINARY} *.o 29 | 30 | distclean: 31 | @${RM} ${BINARY} *.o file_*.[ch] main.h 32 | 33 | .PHONY: clean distclean all 34 | 35 | .PRECIOUS: file_%.[ch] -------------------------------------------------------------------------------- /huge_enterprise_app/file.c.in: -------------------------------------------------------------------------------- 1 | #include "file_@FILENO@.h" 2 | #include "main.h" 3 | 4 | void f@FILENO@(void) 5 | { 6 | struct_@FILENO@_t __attribute__((unused)) s; 7 | } 8 | -------------------------------------------------------------------------------- /huge_enterprise_app/file.h.in: -------------------------------------------------------------------------------- 1 | #ifndef _METARESC_HUGE_ENTERPRISE_APP_TEST_HEADER_@FILENO@_INCLUDED_ 2 | #define _METARESC_HUGE_ENTERPRISE_APP_TEST_HEADER_@FILENO@_INCLUDED_ 3 | #include 4 | 5 | TYPEDEF_STRUCT (struct_@FILENO@_t, 6 | (int, a), 7 | (long, b), 8 | (void*, c), 9 | ) 10 | void f@FILENO@(void); 11 | 12 | #endif // guardian 13 | -------------------------------------------------------------------------------- /huge_enterprise_app/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "main.h" 3 | 4 | int main() 5 | { 6 | puts("It has started!"); 7 | return (0); 8 | } 9 | -------------------------------------------------------------------------------- /huge_enterprise_app/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export LANG=C LC_MEASUREMENT=C LC_NUMERIC=C 4 | 5 | numpasses=3 6 | 7 | perform_test() 8 | { 9 | local numfiles=$1 10 | local variant=$2 11 | local optimize= 12 | local numcpus=`cat /proc/cpuinfo | grep processor | tail -n 1 | awk '{print $3 + 1}'` 13 | 14 | local buildtime='N/A' 15 | local filesize='N/A' 16 | local starttime='N/A' 17 | 18 | [ "$variant" = "optimized" ] && CFLAGS="-DMR_MODE=PROTO" || CFLAGS="" 19 | 20 | make distclean 21 | buildtime=$( (CFLAGS=${CFLAGS} time -p make -j ${numcpus} NUMFILES=${numfiles} > /dev/null) 2>&1 | grep real | awk '{print $NF;}') 22 | filesize=$( stat --format '%s' huge_enterprise_app ) 23 | starttime=$( (time -p ./huge_enterprise_app > /dev/null) 2>&1 | grep real | awk '{print $NF;}' ) 24 | 25 | echo "$numfiles files $variant build $buildtime start $starttime size $filesize" 26 | } 27 | 28 | test_all_sizes() 29 | { 30 | for numfiles in 1 2 4 8 16 32 64 128 256 31 | do 32 | echo -n "${numfiles}..." > /dev/stderr 33 | perform_test $numfiles simple 34 | perform_test $numfiles optimized 35 | done 36 | 37 | echo > /dev/stderr 38 | } 39 | 40 | calc_average() 41 | { 42 | local number=$1 43 | local variant=$2 44 | local fieldno=$3 45 | local numpasses=$4 46 | 47 | local formula=$( 48 | echo -n '('; 49 | grep -h "${number} files ${variant}" pass* | awk '{print $'"${fieldno}"';}' | tr '\n' '+'; 50 | echo "0)/${numpasses}"; 51 | ) 52 | 53 | echo $formula | bc -l 54 | } 55 | 56 | print_averages() 57 | { 58 | local number=$1 59 | local variant=$2 60 | local numpasses=$3 61 | 62 | local avg_build=$(calc_average $number $variant 5 $numpasses) 63 | local avg_start=$(calc_average $number $variant 7 $numpasses) 64 | local avg_size=$(calc_average $number $variant 9 $numpasses) 65 | 66 | local print_build=$(printf "%.2f" $avg_build) 67 | local print_start=$(printf "%.2f" $avg_start) 68 | local print_size=$(printf "%.1f" $( echo "$avg_size / 1024" | bc -l ) ) 69 | 70 | echo "$number files, $variant, build $print_build, start $print_start, size $print_size k" 71 | } 72 | 73 | for (( pass = 0; $pass < $numpasses; pass = $pass + 1 )); 74 | do 75 | echo "pass #${pass}" > /dev/stderr 76 | test_all_sizes > pass${pass} 77 | done 78 | 79 | make distclean 80 | 81 | tested_numbers=$(cat pass* | cut -d' ' -f1 | sort -n | uniq) 82 | 83 | for number in $tested_numbers 84 | do 85 | print_averages $number simple $numpasses 86 | print_averages $number optimized $numpasses 87 | done 88 | 89 | rm pass* 90 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | /Makefile 2 | /Makefile.in 3 | /mr_config.h 4 | /mr_config.h.in 5 | /mr_export.h 6 | /mr_pp.h 7 | /mr_dwarf 8 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- makefile -*- 2 | 3 | AM_CFLAGS = @AM_CFLAGS@ 4 | AM_CPPFLAGS = -I$(top_srcdir)/src 5 | 6 | DISTCLEANFILES = mr_pp.h 7 | MOSTLYCLEANFILES = *.tab.[ch] *.lex.[ch] 8 | 9 | SUFFIXES = .y .l .lex.h .tab.h .lex.c .tab.c 10 | 11 | .y.tab.h: 12 | $(YACC) -d $< 13 | 14 | .y.tab.c: 15 | $(YACC) $< 16 | 17 | .l.lex.h: 18 | $(LEX) --header-file=$@ -o $*.lex.c $< 19 | 20 | .l.lex.c: 21 | $(LEX) -o $@ $< 22 | 23 | pkgincludedir = $(includedir) 24 | 25 | lib_LTLIBRARIES = libmetaresc.la 26 | 27 | if HAVE_LIBDWARF 28 | SUBDIRS = ../libdwarf-code/ 29 | bin_PROGRAMS = mr_dwarf 30 | mr_dwarf_CPPFLAGS = -I$(top_srcdir)/libdwarf-code/src/lib/libdwarf/ 31 | mr_dwarf_LDADD = libmetaresc.la ../libdwarf-code/src/lib/libdwarf/.libs/libdwarf.la 32 | endif 33 | 34 | libmetaresc_la_SOURCES = metaresc.c mr_message.c mr_extra.c mr_print.c mr_stringify.c mr_save.c mr_load.c xml_save.c cinit_save.c json_save.c scm_save.c mr_ic.c mr_hsort.c mr_value.c mr_btree.c mr_udo_init.c 35 | 36 | if HAVE_BISON_FLEX 37 | libmetaresc_la_SOURCES += xml1_load.tab.c xml1_load.lex.c cinit_load.tab.c cinit_load.lex.c json_load.tab.c json_load.lex.c scm_load.tab.c scm_load.lex.c 38 | endif 39 | if HAVE_LIBXML2 40 | libmetaresc_la_SOURCES += xml2_load.c 41 | endif 42 | if HAVE_LIBYAML 43 | libmetaresc_la_SOURCES += yaml_save.c yaml_load.c 44 | endif 45 | if HAVE_XDR 46 | libmetaresc_la_SOURCES += xdr.c 47 | endif 48 | 49 | mr_value.lo: CFLAGS += -ffast-math 50 | 51 | pkginclude_HEADERS = metaresc.h mr_protos.h mr_export.h mr_pp.h 52 | 53 | xml1_load.tab.c: xml1_load.y xml1_load.lex.h 54 | xml1_load.lex.c: xml1_load.l xml1_load.tab.h 55 | cinit_load.tab.c: cinit_load.y cinit_load.lex.h 56 | cinit_load.lex.c: cinit_load.l cinit_load.tab.h 57 | json_load.tab.c: json_load.y json_load.lex.h 58 | json_load.lex.c: json_load.l json_load.tab.h 59 | scm_load.tab.c: scm_load.y scm_load.lex.h 60 | scm_load.lex.c: scm_load.l scm_load.tab.h 61 | $(libmetaresc_la_SOURCES) mr_dwarf.c: metaresc.h 62 | metaresc.h: mr_pp.h 63 | mr_pp.h: mr_pp.sh 64 | ./$? $(PP_DEPTH) > $@ 65 | 66 | valgrind: 67 | $(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT="$(LIBTOOL) --mode=execute $(VALGRIND)" 68 | -------------------------------------------------------------------------------- /src/cinit_load.l: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | %option 8bit reentrant bison-bridge bison-locations 6 | %option warn nounput never-interactive noyywrap 7 | %option extra-type="mr_load_t*" 8 | %option prefix="mr_cinit_" 9 | %{ 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #define MR_CINIT_LTYPE mr_token_lloc_t 18 | #include 19 | #define YYSTYPE MR_CINIT_STYPE 20 | #define YYLTYPE MR_CINIT_LTYPE 21 | 22 | static void 23 | get_type (mr_substr_t * substr, char * start) 24 | { 25 | while (isspace (*start)) 26 | ++start; 27 | 28 | substr->str = start; 29 | substr->length = strlen (start); 30 | 31 | char * stop = memchr (substr->str, ')', substr->length); 32 | if (stop) 33 | { 34 | while (--stop > start) 35 | if (!((isspace (*stop) || ('[' == *stop) || (']' == *stop) || ('*' == *stop)))) 36 | break; 37 | substr->length = stop - start + 1; 38 | } 39 | } 40 | 41 | %} 42 | 43 | %x in_comment 44 | 45 | WS [[:space:]]* 46 | ID [_[:alpha:]][_[:alnum:]]* 47 | INT_NUMBER [[:digit:]]+ 48 | HEX_NUMBER (0x|0X)[[:xdigit:]]+ 49 | OCT_NUMBER 0[[0-7]]+ 50 | NUMBER {INT_NUMBER}|{HEX_NUMBER}|{OCT_NUMBER} 51 | FLOAT_NAN [+-]?[Nn][Aa][Nn] 52 | FLOAT_INF [+-]?[Ii][Nn][Ff] 53 | FLOAT_NUMBER {FLOAT_NAN}|{FLOAT_INF}|{INT_NUMBER}("."[[:digit:]]*)?([eE][+-]?{INT_NUMBER})? 54 | IMAGENARY_NUMBER {INT_NUMBER}("."[[:digit:]]*)?([eE][+-]?{INT_NUMBER})?[Ii] 55 | %% 56 | 57 | {WS} { /* eat up whitespace */ } 58 | 59 | "NULL" { return (TOK_CINIT_NULL); } 60 | "false" { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = false; return (TOK_CINIT_NUMBER); } 61 | "FALSE" { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = false; return (TOK_CINIT_NUMBER); } 62 | "true" { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = true; return (TOK_CINIT_NUMBER); } 63 | "TRUE" { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = true; return (TOK_CINIT_NUMBER); } 64 | [Ii] { yylval->value.value_type = MR_VT_COMPLEX; yylval->value.vt_complex = I; return (TOK_CINIT_NUMBER); } 65 | 66 | {NUMBER} { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = mr_strtouintmax (yytext, NULL, 0); return (TOK_CINIT_NUMBER); } 67 | 68 | {FLOAT_NUMBER} { yylval->value.value_type = MR_VT_FLOAT; yylval->value.vt_float = strtold (yytext, NULL); return (TOK_CINIT_NUMBER); } 69 | 70 | {IMAGENARY_NUMBER} { 71 | yylval->value.value_type = MR_VT_COMPLEX; 72 | yylval->value.vt_complex = I * strtold (yytext, NULL); 73 | return (TOK_CINIT_NUMBER); 74 | } 75 | 76 | {ID} { 77 | yylval->string.str = yytext; 78 | yylval->string.length = strlen (yytext); 79 | return (TOK_CINIT_ID); 80 | } 81 | 82 | "\""([^\"\\]|\\.)*"\"" { 83 | yylval->string.str = &yytext[1]; 84 | yylval->string.length = strlen (yytext) - 2 * sizeof (yytext[0]); 85 | return (TOK_CINIT_STRING); 86 | } 87 | 88 | "\'"([^\'\\]|\\.)*"\'" { 89 | yylval->string.str = &yytext[1]; 90 | yylval->string.length = strlen (yytext) - 2 * sizeof (yytext[0]); 91 | return (TOK_CINIT_CHAR); 92 | } 93 | 94 | "("{WS}({ID}{WS})*{ID}{WS}\*?{WS}("["{WS}"]")?{WS}")" { get_type (&yylval->string, &yytext[1]); return (TOK_CINIT_FIELD_CAST); } 95 | 96 | "/*"{WS}{ID}{WS}"="{WS}[[:digit:]]+{WS}"*/" { 97 | mr_get_id (&yylval->id_ivalue.id, &yytext[2]); 98 | yylval->id_ivalue.ivalue = strtoull (strchr (yytext, '=') + 1, NULL, 0); 99 | return (TOK_CINIT_ID_IVALUE); 100 | } 101 | 102 | "/*" { BEGIN(in_comment); } 103 | [^*\n]* /* eat anything that's not a '*' */ 104 | "*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ 105 | \n 106 | "*"+"/" { BEGIN(INITIAL); } 107 | 108 | "+" { return (TOK_CINIT_PLUS); } 109 | "-" { return (TOK_CINIT_MINUS); } 110 | "*" { return (TOK_CINIT_MUL); } 111 | "/" { return (TOK_CINIT_DIV); } 112 | "%" { return (TOK_CINIT_MOD); } 113 | "|" { return (TOK_CINIT_BIT_OR); } 114 | "&" { return (TOK_CINIT_BIT_AND); } 115 | "^" { return (TOK_CINIT_BIT_XOR); } 116 | 117 | "{" { return (TOK_CINIT_LBRACE); } 118 | "}" { return (TOK_CINIT_RBRACE); } 119 | "(" { return (TOK_CINIT_LPAREN); } 120 | ")" { return (TOK_CINIT_RPAREN); } 121 | "," { return (TOK_CINIT_COMMA); } 122 | "." { return (TOK_CINIT_DOT); } 123 | "=" { return (TOK_CINIT_ASSIGN); } 124 | . { return (TOK_CINIT_ERROR); } 125 | %% 126 | 127 | 128 | -------------------------------------------------------------------------------- /src/json_load.l: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | %option 8bit reentrant bison-bridge bison-locations 6 | %option warn nounput never-interactive noyywrap 7 | %option extra-type="mr_load_t*" 8 | %option prefix="mr_json_" 9 | %{ 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #define MR_JSON_LTYPE mr_token_lloc_t 18 | #include 19 | #define YYSTYPE MR_JSON_STYPE 20 | #define YYLTYPE MR_JSON_LTYPE 21 | 22 | %} 23 | 24 | WS [[:space:]]+ 25 | ID [_[:alpha:]][_[:alnum:]]* 26 | INT_NUMBER [+-]?[[:digit:]]+ 27 | FLOAT_NAN [+-]?[Nn][Aa][Nn] 28 | FLOAT_INF [+-]?[Ii][Nn][Ff] 29 | FLOAT_NUMBER {FLOAT_NAN}|{FLOAT_INF}|{INT_NUMBER}("."[[:digit:]]*)?([eE]{INT_NUMBER})? 30 | %% 31 | 32 | "null" { return (TOK_JSON_NULL); } 33 | "false" { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = false; return (TOK_JSON_NUMBER); } 34 | "true" { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = true; return (TOK_JSON_NUMBER); } 35 | 36 | {INT_NUMBER} { yylval->value.value_type = MR_VT_INT; yylval->value.vt_int = mr_strtouintmax (yytext, NULL, 0); return (TOK_JSON_NUMBER); } 37 | {FLOAT_NUMBER} { yylval->value.value_type = MR_VT_FLOAT; yylval->value.vt_float = strtold (yytext, NULL); return (TOK_JSON_NUMBER); } 38 | 39 | "\""([^\"\\]|\\.)*"\"" { 40 | yylval->string.str = &yytext[1]; 41 | yylval->string.length = strlen (yytext) - 2 * sizeof (yytext[0]); 42 | return (TOK_JSON_STRING); 43 | } 44 | 45 | {WS} { /* eat up whitespace */ } 46 | ":" { return (TOK_JSON_SEMICOLON); } 47 | "{" { return (TOK_JSON_LBRACE); } 48 | "}" { return (TOK_JSON_RBRACE); } 49 | "[" { return (TOK_JSON_LBRACKET); } 50 | "]" { return (TOK_JSON_RBRACKET); } 51 | "," { return (TOK_JSON_COMMA); } 52 | . { return (TOK_JSON_ERROR); } 53 | %% 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/json_load.y: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | %code top { 6 | #include 7 | #include 8 | 9 | #define MR_JSON_DEBUG 0 10 | /* Pass the argument to yyparse through to yylex. */ 11 | #define MR_JSON_LTYPE mr_token_lloc_t 12 | #define MR_LOAD (mr_json_get_extra (scanner)) 13 | #define mr_json_error MR_PARSE_ERROR 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #define YYSTYPE MR_JSON_STYPE 21 | #define YYLTYPE MR_JSON_LTYPE 22 | #include 23 | 24 | } 25 | 26 | %code { 27 | 28 | static void 29 | json_unquote_str (mr_substr_t * substr, char * dst) 30 | { 31 | typeof (substr->length) i, length = 0; 32 | static bool initialized = false; 33 | static char map[MR_ESC_CHAR_MAP_SIZE]; 34 | 35 | if (!initialized) 36 | { 37 | memset (map, 0, sizeof (map)); 38 | for (i = 0; i < MR_ESC_CHAR_MAP_SIZE; ++i) 39 | if (mr_esc_char_map[i]) 40 | map[(unsigned char)mr_esc_char_map[i]] = i; 41 | initialized = true; 42 | } 43 | 44 | if (NULL == substr->str) 45 | return; 46 | 47 | for (i = 0; i < substr->length; ++i) 48 | { 49 | if ('\\' == substr->str[i]) 50 | { 51 | int c = map[(unsigned char)substr->str[++i]]; 52 | int size; 53 | if (c > 0) 54 | dst[length++] = c; 55 | else if (1 == sscanf (&substr->str[i], "u%04x%n", &c, &size)) 56 | { 57 | i += size - 1; 58 | dst[length++] = c; 59 | } 60 | else 61 | dst[length++] = substr->str[i]; 62 | } 63 | else 64 | dst[length++] = substr->str[i]; 65 | } 66 | dst[length] = 0; 67 | } 68 | 69 | } 70 | 71 | %define api.prefix {mr_json_} 72 | %define api.pure full 73 | %param {void * scanner} 74 | %locations 75 | /* generate include-file with symbols and types */ 76 | %defines 77 | 78 | /* a more advanced semantic type */ 79 | %union { 80 | mr_value_t value; 81 | mr_substr_t string; 82 | } 83 | 84 | /* Bison declarations. */ 85 | %token TOK_JSON_NUMBER 86 | %token TOK_JSON_STRING 87 | %token TOK_JSON_SEMICOLON TOK_JSON_LBRACE TOK_JSON_RBRACE TOK_JSON_LBRACKET TOK_JSON_RBRACKET TOK_JSON_COMMA TOK_JSON_NULL TOK_JSON_ERROR 88 | 89 | %start json 90 | 91 | %% /* The grammar follows. */ 92 | 93 | json: element 94 | 95 | element: push_node value pop_node 96 | 97 | pop_node: { 98 | mr_load_t * mr_load = MR_LOAD; 99 | mr_load->parent = mr_load->ptrs->ra[mr_load->parent].parent; 100 | (void)mr_json_nerrs; /* workaround compiler warning: variable 'mr_json_nerrs' set but not used */ 101 | } 102 | 103 | push_node: { 104 | mr_load_t * mr_load = MR_LOAD; 105 | mr_idx_t idx = mr_add_ptr_to_list (mr_load->ptrs); 106 | if (MR_NULL_IDX == idx) 107 | { YYERROR; } 108 | mr_add_child (mr_load->ptrs, mr_load->parent, idx); 109 | mr_load->parent = idx; 110 | mr_load->ptrs->ra[idx].idx = idx; 111 | } 112 | 113 | value: object | array 114 | | TOK_JSON_STRING { 115 | mr_load_t * mr_load = MR_LOAD; 116 | if (memchr ($1.str, '\\', $1.length)) 117 | { 118 | char * buf = MR_CALLOC (1, $1.length + sizeof (char)); 119 | if (NULL == buf) 120 | { 121 | MR_MESSAGE (MR_LL_FATAL, MR_MESSAGE_OUT_OF_MEMORY); 122 | YYERROR; 123 | } 124 | json_unquote_str (&$1, buf); 125 | mr_load->ptrs->ra[mr_load->parent].value_type = MR_VT_STRING; 126 | mr_load->ptrs->ra[mr_load->parent].load_params.vt_string = buf; 127 | } 128 | else 129 | { 130 | mr_load->ptrs->ra[mr_load->parent].value_type = MR_VT_SUBSTR; 131 | mr_load->ptrs->ra[mr_load->parent].load_params.vt_substr.str = &mr_load->str[$1.str - mr_load->buf]; 132 | mr_load->ptrs->ra[mr_load->parent].load_params.vt_substr.length = $1.length; 133 | } 134 | } 135 | | TOK_JSON_NUMBER { 136 | mr_load_t * mr_load = MR_LOAD; 137 | mr_status_t status = mr_value_to_mr_ptrdes (&mr_load->ptrs->ra[mr_load->parent], &$1); 138 | if (MR_SUCCESS != status) 139 | { YYERROR; } 140 | } 141 | | TOK_JSON_NULL { 142 | mr_load_t * mr_load = MR_LOAD; 143 | mr_load->ptrs->ra[mr_load->parent].flags |= MR_IS_NULL; 144 | mr_load->ptrs->ra[mr_load->parent].value_type = MR_VT_INT; 145 | memset (&mr_load->ptrs->ra[mr_load->parent].load_params.vt_int, 0, sizeof (mr_load->ptrs->ra[mr_load->parent].load_params.vt_int)); 146 | } 147 | 148 | object: TOK_JSON_LBRACE TOK_JSON_RBRACE 149 | | TOK_JSON_LBRACE members TOK_JSON_RBRACE 150 | 151 | members: member | member TOK_JSON_COMMA members 152 | 153 | member: TOK_JSON_STRING TOK_JSON_SEMICOLON element { 154 | mr_load_t * mr_load = MR_LOAD; 155 | mr_idx_t idx = mr_last_child_for_parent (mr_load->ptrs, mr_load->parent); 156 | if (MR_NULL_IDX == idx) 157 | { 158 | MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_INTERNAL_PARSER_ERROR); 159 | YYERROR; 160 | } 161 | 162 | $1.str[$1.length] = 0; 163 | mr_load->ptrs->ra[idx].fdp = mr_get_any_fd_by_name ($1.str, NULL); 164 | if (NULL == mr_load->ptrs->ra[idx].fdp) 165 | { 166 | MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_UNKNOWN_FIELD_NAME, $1.str); 167 | YYERROR; 168 | } 169 | } 170 | 171 | array: TOK_JSON_LBRACKET TOK_JSON_RBRACKET 172 | | TOK_JSON_LBRACKET elements TOK_JSON_RBRACKET 173 | 174 | elements: element | element TOK_JSON_COMMA elements 175 | 176 | %% 177 | 178 | MR_LOAD_FUNC (json); 179 | -------------------------------------------------------------------------------- /src/lexer.h: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | #ifndef _LEXER_H_ 6 | #define _LEXER_H_ 7 | 8 | #include 9 | 10 | TYPEDEF_STRUCT (mr_token_lloc_t, ATTRIBUTES ( , "token location"), 11 | (mr_lloc_t, start, , "start of the token"), 12 | (mr_lloc_t, end, , "end of the token"), 13 | ) 14 | 15 | #define MR_PARSE_ERROR(LLOCP, SCANNER, ERROR_MSG) \ 16 | MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_PARSE_ERROR, ERROR_MSG, \ 17 | (LLOCP)->start.lineno, (LLOCP)->start.column, (LLOCP)->end.lineno, (LLOCP)->end.column) 18 | 19 | static inline void mr_calc_lloc (mr_load_t * mr_load, char * ptr) 20 | { 21 | if (NULL == mr_load->buf) 22 | mr_load->buf = ptr; 23 | else 24 | for ( ; &mr_load->buf[mr_load->lloc.offset] < ptr; ++mr_load->lloc.offset) 25 | if ('\n' == mr_load->buf[mr_load->lloc.offset]) 26 | { 27 | ++mr_load->lloc.lineno; 28 | mr_load->lloc.column = 0; 29 | } 30 | else 31 | ++mr_load->lloc.column; 32 | } 33 | 34 | static inline int mr_substrcmp (char * str, mr_substr_t * substr) 35 | { 36 | typeof (substr->length) str_len = strlen (str); 37 | if (str_len != substr->length) 38 | return (str_len - substr->length); 39 | return (strncmp (str, substr->str, str_len)); 40 | } 41 | 42 | static inline void mr_get_id (mr_substr_t * substr, char * start) 43 | { 44 | char * stop; 45 | while (isspace (*start)) 46 | ++start; 47 | stop = start; 48 | while (isalnum (*stop) || ('_' == *stop)) 49 | ++stop; 50 | substr->str = start; 51 | substr->length = stop - start; 52 | } 53 | 54 | #define YY_USER_ACTION ({ \ 55 | mr_load_t * mr_load = yyextra; \ 56 | mr_calc_lloc (mr_load, yy_bp); \ 57 | yylloc->start = mr_load->lloc; \ 58 | mr_calc_lloc (mr_load, yy_cp); \ 59 | yylloc->end = mr_load->lloc; \ 60 | }); 61 | 62 | #define YYLLOC_DEFAULT(Current, Rhs, N) \ 63 | ({ \ 64 | if (N) \ 65 | { \ 66 | (Current).start.lineno = YYRHSLOC (Rhs, 1).start.lineno; \ 67 | (Current).start.column = YYRHSLOC (Rhs, 1).start.column; \ 68 | (Current).start.offset = YYRHSLOC (Rhs, 1).start.offset; \ 69 | (Current).end.lineno = YYRHSLOC (Rhs, N).end.lineno; \ 70 | (Current).end.column = YYRHSLOC (Rhs, N).end.column; \ 71 | (Current).end.offset = YYRHSLOC (Rhs, N).end.offset; \ 72 | } \ 73 | else \ 74 | { \ 75 | (Current).start.lineno = (Current).end.lineno = YYRHSLOC (Rhs, 0).end.lineno; \ 76 | (Current).start.column = (Current).end.column = YYRHSLOC (Rhs, 0).end.column; \ 77 | (Current).start.offset = (Current).end.offset = YYRHSLOC (Rhs, 0).end.offset; \ 78 | } \ 79 | }) 80 | 81 | #define YY_NO_INPUT 82 | #define YYINITDEPTH 256 83 | #define YYMAXDEPTH ((unsigned)-1) 84 | 85 | #define MR_LOAD_FUNC(METHOD) \ 86 | mr_status_t mr_ ## METHOD ## _load (char * str, mr_ra_ptrdes_t * ptrs) { \ 87 | mr_status_t status = MR_FAILURE; \ 88 | yyscan_t scanner; \ 89 | mr_load_t mr_load = { .lloc = { .lineno = 1, .column = 0, .offset = 0, }, .str = str, .buf = NULL, .parent = 0, .ptrs = ptrs }; \ 90 | if (NULL == str) \ 91 | { \ 92 | MR_MESSAGE (MR_LL_WARN, MR_MESSAGE_UNEXPECTED_NULL_POINTER); \ 93 | return (MR_FAILURE); \ 94 | } \ 95 | if (mr_ ## METHOD ## _lex_init_extra (&mr_load, &scanner)) \ 96 | return (MR_FAILURE); \ 97 | if (NULL != mr_ ## METHOD ## __scan_string (str, scanner)) \ 98 | if (0 == mr_ ## METHOD ## _parse (scanner)) \ 99 | status = MR_SUCCESS; \ 100 | if (status != MR_SUCCESS) \ 101 | mr_free_load_values (ptrs); \ 102 | mr_ ## METHOD ## _lex_destroy (scanner); \ 103 | return (status); \ 104 | } 105 | 106 | #endif /* _LEXER_H_ */ 107 | -------------------------------------------------------------------------------- /src/mr_btree.h: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | #ifndef _MR_BTREE_H_ 5 | #define _MR_BTREE_H_ 6 | 7 | #include 8 | 9 | extern void mr_tree_init (mr_tree_t * tree); 10 | extern void mr_tree_free (mr_tree_t * tree); 11 | extern mr_status_t mr_tree_reserve (mr_tree_t * tree, unsigned items_count, bool reset); 12 | extern mr_status_t mr_tree_walk (mr_tree_t * tree, mr_visit_fn_t visit_fn, void * context); 13 | extern void mr_tree_find (mr_ptr_t key, mr_tree_t * tree, mr_compar_fn_t compar_fn, void * context, mr_tree_traverse_t * traverse); 14 | extern void mr_tree_next (mr_tree_t * tree, mr_tree_traverse_t * traverse, mr_child_idx_t next); 15 | 16 | extern mr_ptr_t * mr_rbtree_add (mr_ptr_t key, mr_tree_t * tree, mr_compar_fn_t compar_fn, void * context); 17 | extern mr_status_t mr_rbtree_del (mr_ptr_t key, mr_tree_t * tree, mr_compar_fn_t compar_fn, void * context); 18 | extern bool mr_rbtree_is_valid (mr_tree_t * tree, mr_compar_fn_t cmp, void * context); 19 | 20 | extern mr_ptr_t * mr_avltree_add (mr_ptr_t key, mr_tree_t * tree, mr_compar_fn_t compar_fn, void * context); 21 | extern mr_status_t mr_avltree_del (mr_ptr_t key, mr_tree_t * tree, mr_compar_fn_t compar_fn, void * context); 22 | extern bool mr_avltree_is_valid (mr_tree_t * tree, mr_compar_fn_t cmp, void * context); 23 | 24 | #endif /* _MR_BTREE_H_ */ 25 | -------------------------------------------------------------------------------- /src/mr_export.h.in: -------------------------------------------------------------------------------- 1 | 2 | /* Bison & Flex found */ 3 | #undef HAVE_BISON_FLEX 4 | 5 | /* define if __builtin_dump_struct is present */ 6 | #undef HAVE_BUILTIN_DUMP_STRUCT 7 | 8 | /* define if __builtin_dump_struct supports extra args */ 9 | #undef HAVE_BUILTIN_DUMP_STRUCT_EXTRA_ARGS 10 | 11 | /* define if libxml2 is present */ 12 | #undef HAVE_LIBXML2 13 | 14 | /* define if libyaml is present */ 15 | #undef HAVE_LIBYAML 16 | 17 | /* Define to 1 if you have the header file. */ 18 | #undef HAVE_RPC_TYPES_H 19 | 20 | /* Preprocessor routines depth */ 21 | #undef MR_PP_DEPTH 22 | 23 | /* type of union discriminators indexes */ 24 | #undef MR_RA_UD_IDX_TYPE 25 | 26 | /* define if __int128 is supported */ 27 | #undef MR_HAVE_INT128 28 | 29 | /* long double significant bytes */ 30 | #undef MR_SIZEOF_LONG_DOUBLE 31 | 32 | /* sizeof char in bits */ 33 | #undef MR_SIZEOF_CHAR 34 | 35 | /* sizeof short in bits */ 36 | #undef MR_SIZEOF_SHORT 37 | 38 | /* sizeof int in bits */ 39 | #undef MR_SIZEOF_INT 40 | 41 | /* sizeof long in bits */ 42 | #undef MR_SIZEOF_LONG 43 | 44 | /* sizeof long long in bits */ 45 | #undef MR_SIZEOF_LONG_LONG 46 | -------------------------------------------------------------------------------- /src/mr_hsort.c: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | #include /* size_t */ 6 | #include /* memcpy */ 7 | 8 | #include 9 | #include 10 | 11 | static inline void 12 | sift (char * array, size_t count, size_t size, mr_compar_fn_t compar_fn, void * context, unsigned idx0) 13 | { 14 | unsigned idx1; 15 | char x[size]; 16 | memcpy (x, &array[idx0 * size], size); 17 | 18 | for (idx1 = (idx0 << 1) + 1; idx1 < count; idx1 = (idx1 << 1) + 1) 19 | { 20 | if (compar_fn (&array[idx1 * size], &array[(idx1 + 1) * size], context) <= 0) 21 | ++idx1; 22 | if (compar_fn (&array[idx1 * size], x, context) <= 0) 23 | break; 24 | memcpy (&array[idx0 * size], &array[idx1 * size], size); 25 | idx0 = idx1; 26 | } 27 | if (idx1 == count) 28 | if (compar_fn (&array[idx1 * size], x, context) > 0) 29 | { 30 | memcpy (&array[idx0 * size], &array[idx1 * size], size); 31 | idx0 = idx1; 32 | } 33 | memcpy (&array[idx0 * size], x, size); 34 | } 35 | 36 | void 37 | mr_hsort (void * array, size_t count, size_t size, mr_compar_fn_t compar_fn, void * context) 38 | { 39 | unsigned i; 40 | 41 | if (count-- <= 1) 42 | return; 43 | 44 | for (i = count >> 1; i > 0; --i) 45 | sift (array, count, size, compar_fn, context, i); 46 | 47 | for ( ; count > 0; --count) 48 | { 49 | char x[size]; 50 | void * last = &(((char*)array)[count * size]); 51 | sift (array, count, size, compar_fn, context, 0); 52 | memcpy (x, last, size); 53 | memcpy (last, array, size); 54 | memcpy (array, x, size); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/mr_hsort.h: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | #ifndef _MR_HSORT_H_ 5 | #define _MR_HSORT_H_ 6 | 7 | #include /* size_t */ 8 | #include 9 | 10 | extern void mr_hsort (void * array, size_t count, size_t size, mr_compar_fn_t compar_fn, void * context); 11 | 12 | #endif /* _MR_HSORT_H_ */ 13 | -------------------------------------------------------------------------------- /src/mr_load.h: -------------------------------------------------------------------------------- 1 | #ifndef _MR_LOAD_H_ 2 | #define _MR_LOAD_H_ 3 | 4 | #include 5 | 6 | extern mr_status_t mr_load_integer (mr_idx_t, mr_ra_ptrdes_t *); 7 | extern mr_status_t mr_load_func (mr_idx_t, mr_ra_ptrdes_t *); 8 | extern void mr_pointer_set_size (mr_idx_t, mr_ra_ptrdes_t *); 9 | 10 | #endif /* _MR_LOAD_H_ */ 11 | -------------------------------------------------------------------------------- /src/mr_message.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | # include 3 | #endif /* HAVE_CONFIG_H */ 4 | #ifdef HAVE_EXECINFO_H 5 | # include 6 | #endif /* HAVE_EXECINFO_H */ 7 | 8 | #include /* free () */ 9 | #include 10 | 11 | static int 12 | mr_vscprintf (const char * format, va_list args) 13 | { 14 | va_list _args; 15 | va_copy (_args, args); 16 | int retval = vsnprintf (NULL, 0, format, _args); 17 | va_end (_args); 18 | return (retval); 19 | } 20 | 21 | static int 22 | mr_vasprintf (char ** strp, const char * fmt, va_list args) 23 | { 24 | *strp = NULL; 25 | int len = mr_vscprintf (fmt, args); 26 | if (len <= 0) 27 | return (len); 28 | char * str = MR_CALLOC (len + 1, sizeof (*str)); 29 | if (NULL == str) 30 | return (-1); 31 | int _len = vsnprintf (str, len + 1, fmt, args); 32 | if (_len < 0) 33 | { 34 | MR_FREE (str); 35 | return (len); 36 | } 37 | *strp = str; 38 | return (_len); 39 | } 40 | 41 | /** 42 | * Format message. Allocates memory for message that need to be freed. 43 | * @param message_id message template string ID 44 | * @param args variadic agruments 45 | * @return message string allocated by standard malloc. Need to be freed outside. 46 | */ 47 | char * 48 | mr_message_format (mr_message_id_t message_id, va_list args) 49 | { 50 | static const char * messages[MR_MESSAGE_LAST + 1] = { [0 ... MR_MESSAGE_LAST] = NULL }; 51 | static bool messages_inited = false; 52 | const char * format = "Unknown MR_MESSAGE_ID."; 53 | char * message = NULL; 54 | 55 | if (!messages_inited) 56 | { 57 | mr_td_t * tdp = mr_get_td_by_name_internal ("mr_message_id_t"); 58 | if (tdp) 59 | { 60 | int i; 61 | for (i = 0; tdp->param.enum_param.enums[i] != NULL; ++i) 62 | messages[tdp->param.enum_param.enums[i]->value._unsigned] = tdp->param.enum_param.enums[i]->meta; 63 | messages_inited = true; 64 | } 65 | } 66 | 67 | if ((message_id <= sizeof (messages) / sizeof (messages[0])) && messages[message_id]) 68 | format = messages[message_id]; 69 | 70 | if (format) 71 | (void)mr_vasprintf (&message, format, args); 72 | 73 | return (message); 74 | } 75 | 76 | /** 77 | * Redirect message to user defined handler or output message to stderr. 78 | * @param file_name file name 79 | * @param func_name function name 80 | * @param line line number 81 | * @param log_level logging level of message 82 | * @param message_id message template string ID 83 | */ 84 | void 85 | mr_message (const char * file_name, const char * func_name, int line, mr_log_level_t log_level, mr_message_id_t message_id, ...) 86 | { 87 | char * message; 88 | va_list args; 89 | 90 | va_start (args, message_id); 91 | /* if we have user defined message handler then pass error to it */ 92 | if (mr_conf.msg_handler) 93 | mr_conf.msg_handler (file_name, func_name, line, log_level, message_id, args); 94 | else if (log_level >= mr_conf.log_level) 95 | { 96 | const char * log_level_str_ = "Unknown"; 97 | #define LL_INIT(LEVEL) [MR_LL_##LEVEL] = #LEVEL, 98 | static const char * log_level_str[] = 99 | { MR_FOREACH (LL_INIT, ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF) }; 100 | 101 | if (((int)log_level >= 0) 102 | && ((int)log_level <= sizeof (log_level_str) / sizeof (log_level_str[0]))) 103 | if (log_level_str[log_level]) 104 | log_level_str_ = log_level_str[log_level]; 105 | 106 | #ifdef HAVE_EXECINFO_H 107 | if (log_level <= MR_LL_DEBUG) 108 | { 109 | void * array[8]; 110 | size_t size; 111 | char ** strings; 112 | size_t i; 113 | 114 | size = backtrace (array, sizeof (array) / sizeof (array[0])); 115 | strings = backtrace_symbols (array, size); 116 | fprintf (stderr, "Obtained %zd stack frames.\n", size); 117 | if (strings) 118 | { 119 | for (i = 0; i < size; ++i) 120 | fprintf (stderr, "%s\n", strings[i]); 121 | free (strings); 122 | } 123 | } 124 | #endif /* HAVE_EXECINFO_H */ 125 | 126 | message = mr_message_format (message_id, args); 127 | if (NULL == message) 128 | fprintf (stderr, "%s: in %s %s() line %d: Out of memory formating error message #%d\n", log_level_str_, file_name, func_name, line, message_id); 129 | else 130 | { 131 | fprintf (stderr, "%s: in %s %s() line %d: %s\n", log_level_str_, file_name, func_name, line, message); 132 | MR_FREE (message); 133 | } 134 | } 135 | va_end (args); 136 | } 137 | 138 | /** 139 | * printf into resizable array 140 | * @param mr_ra_str a pointer on resizable array 141 | * @param format standard printf format string 142 | * @param ... arguments for printf 143 | * @return length of added content and -1 in case of memory allocation failure 144 | */ 145 | int 146 | mr_ra_printf (mr_rarray_t * mr_ra_str, const char * format, ...) 147 | { 148 | va_list args; 149 | typeof (mr_ra_str->MR_SIZE) length, _length; 150 | 151 | va_start (args, format); 152 | length = mr_vscprintf (format, args); 153 | 154 | if (length < 0) 155 | goto free_mr_ra; 156 | 157 | if ((0 == mr_ra_str->MR_SIZE) || (NULL == mr_ra_str->data.ptr)) 158 | goto free_mr_ra; 159 | 160 | typeof (mr_ra_str->MR_SIZE) size = mr_ra_str->MR_SIZE; 161 | char * tail = mr_rarray_append (mr_ra_str, length); 162 | 163 | if (NULL == tail) 164 | goto free_mr_ra; 165 | else 166 | _length = vsnprintf (tail - 1, length + 1, format, args); 167 | 168 | if (_length < 0) 169 | goto free_mr_ra; 170 | 171 | mr_ra_str->MR_SIZE = _length + size; 172 | 173 | va_end (args); 174 | return (_length); 175 | 176 | free_mr_ra: 177 | if (mr_ra_str->data.ptr) 178 | MR_FREE (mr_ra_str->data.ptr); 179 | mr_ra_str->data.ptr = NULL; 180 | mr_ra_str->MR_SIZE = mr_ra_str->alloc_size = 0; 181 | va_end (args); 182 | return (-1); 183 | } 184 | -------------------------------------------------------------------------------- /src/mr_pp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PP_DEPTH=$1 4 | 5 | if [ x${PP_DEPTH} = x ]; then 6 | PP_DEPTH=128 7 | fi 8 | 9 | echo "#ifndef _MR_PP_H_" 10 | echo "#define _MR_PP_H_" 11 | echo 12 | 13 | echo "#define MR_FOREACH0(...)" 14 | I=0 15 | while [ $I -lt $PP_DEPTH ] 16 | do 17 | NEXT=$(( I + 1 )) 18 | echo "#define MR_FOREACH$NEXT(X, _0, ...) X (_0) MR_FOREACH$I (X, __VA_ARGS__)" 19 | I=$NEXT 20 | done 21 | echo 22 | 23 | echo "#define MR_FOR0(NAME, OP, FUNC, X, ...) " 24 | echo "#define MR_FOR1(NAME, OP, FUNC, X, ...) FUNC (NAME, X, 1)" 25 | I=1 26 | while [ $I -lt $PP_DEPTH ] 27 | do 28 | NEXT=$((I + 1)) 29 | echo "#define MR_FOR$NEXT(NAME, OP, FUNC, X, ...) OP (NAME, $I, FUNC (NAME, X, $NEXT), MR_FOR$I (NAME, OP, FUNC, __VA_ARGS__))" 30 | I=$NEXT 31 | done 32 | echo 33 | 34 | printf "#define MR_ARG$PP_DEPTH(" 35 | I=1 36 | while [ $I -le $PP_DEPTH ] 37 | do 38 | printf "_$I, " 39 | I=$((I + 1)) 40 | done 41 | echo "...) _$PP_DEPTH" 42 | echo 43 | 44 | echo "#define MR_NARG(...) MR_NARG_ (0, ##__VA_ARGS__)" 45 | 46 | printf "#define MR_NARG_(...) MR_ARG$PP_DEPTH (__VA_ARGS__, " 47 | I=$(( PP_DEPTH - 2 )) 48 | while [ $I -ge 0 ] 49 | do 50 | printf "$I, " 51 | I=$((I - 1)) 52 | done 53 | echo ")" 54 | echo 55 | 56 | printf "#define MR_HAS_COMMA(...) MR_ARG$PP_DEPTH (__VA_ARGS__, " 57 | I=2 58 | while [ $I -lt $PP_DEPTH ] 59 | do 60 | printf "1, " 61 | I=$((I + 1)) 62 | done 63 | echo "0)" 64 | echo 65 | 66 | echo "#endif /* _MR_PP_H_ */" 67 | -------------------------------------------------------------------------------- /src/mr_save.h: -------------------------------------------------------------------------------- 1 | #ifndef _MR_SAVE_H_ 2 | #define _MR_SAVE_H_ 3 | 4 | #include 5 | 6 | #define MR_ONE_SHIFT(SHIFT) | (1ULL << (SHIFT)) 7 | #define MR_STRUCT_TYPES (0 MR_FOREACH (MR_ONE_SHIFT, MR_TYPE_STRUCT, MR_TYPE_UNION, MR_TYPE_ANON_UNION, MR_TYPE_NAMED_ANON_UNION)) 8 | #define MR_TYPED_TYPES (0 MR_FOREACH (MR_ONE_SHIFT, MR_TYPE_STRUCT, MR_TYPE_ENUM, MR_TYPE_UNION, MR_TYPE_ANON_UNION, MR_TYPE_NAMED_ANON_UNION)) 9 | 10 | extern void mr_assign_int (mr_ptrdes_t * dst, mr_ptrdes_t * src); 11 | extern void mr_pointer_get_size_ptrdes (mr_ptrdes_t * ptrdes, mr_idx_t idx, mr_ra_ptrdes_t * ptrs); 12 | 13 | #endif /* _MR_SAVE_H_ */ 14 | -------------------------------------------------------------------------------- /src/mr_stringify.h: -------------------------------------------------------------------------------- 1 | #ifndef _MR_STRINGIFY_H_ 2 | #define _MR_STRINGIFY_H_ 3 | 4 | #include 5 | 6 | #define TRY_CATCH_THROW(ADD) ({ \ 7 | int added = ADD; \ 8 | if (added < 0) \ 9 | return (added); \ 10 | added; \ 11 | }) 12 | 13 | extern int mr_ra_printf_void (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 14 | extern int mr_ra_printf_float (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 15 | extern int mr_ra_printf_bool (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 16 | extern int mr_ra_printf_double (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 17 | extern int mr_ra_printf_long_double_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 18 | extern int mr_ra_printf_complex_float (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes, char * delimiter); 19 | extern int mr_ra_printf_complex_double (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes, char * delimiter); 20 | extern int mr_ra_printf_complex_long_double_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes, char * delimiter); 21 | extern int mr_ra_printf_int8_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 22 | extern int mr_ra_printf_uint8_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 23 | extern int mr_ra_printf_int16_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 24 | extern int mr_ra_printf_uint16_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 25 | extern int mr_ra_printf_int32_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 26 | extern int mr_ra_printf_uint32_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 27 | extern int mr_ra_printf_int64_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 28 | extern int mr_ra_printf_uint64_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 29 | extern int mr_ra_printf_int128_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 30 | extern int mr_ra_printf_uint128_t (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 31 | extern int mr_ra_printf_enum (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes); 32 | extern int mr_ra_printf_bitfield (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes, char * delimiter); 33 | extern int mr_ra_printf_quote_string (mr_rarray_t * mr_ra_str, char * str, char * char_pattern); 34 | extern int mr_ra_printf_bitmask (mr_rarray_t * mr_ra_str, mr_ptrdes_t * ptrdes, char * delimiter); 35 | extern const char * mr_serialize_func (void * func); 36 | extern char * mr_uintmaxtostr (char * out, mr_uintmax_t value); 37 | extern int mr_ra_append_char (mr_rarray_t * mr_ra_str, char c); 38 | extern int mr_ra_append_string (mr_rarray_t * mr_ra_str, char * str); 39 | 40 | #define MR_ESC_CHAR_MAP_SIZE (1 << __CHAR_BIT__) 41 | extern char mr_esc_char_map[MR_ESC_CHAR_MAP_SIZE]; 42 | 43 | #endif /* _MR_STRINGIFY_H_ */ 44 | -------------------------------------------------------------------------------- /src/mr_udo_init.h: -------------------------------------------------------------------------------- 1 | #ifndef MR_UDO_INIT_H 2 | #define MR_UDO_INIT_H 3 | 4 | extern void mr_udo_init (); 5 | 6 | #endif /* MR_UDO_INIT_H */ 7 | -------------------------------------------------------------------------------- /src/mr_value.h: -------------------------------------------------------------------------------- 1 | #ifndef _MR_VALUE_H_ 2 | #define _MR_VALUE_H_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | extern mr_status_t mr_value_to_mr_ptrdes (mr_ptrdes_t * ptrdes, mr_value_t * mr_value); 9 | extern mr_status_t mr_ptrdes_to_mr_value (mr_value_t * mr_value, mr_ptrdes_t * ptrdes); 10 | 11 | extern mr_status_t mr_value_cast (mr_value_type_t value_type, mr_value_t * value); 12 | extern mr_status_t mr_value_neg (mr_value_t * value); 13 | extern bool mr_value_is_zero (mr_value_t * value); 14 | extern mr_status_t mr_value_add (mr_value_t * result, mr_value_t * left, mr_value_t * right); 15 | extern mr_status_t mr_value_sub (mr_value_t * result, mr_value_t * left, mr_value_t * right); 16 | extern mr_status_t mr_value_div (mr_value_t * result, mr_value_t * left, mr_value_t * right); 17 | extern mr_status_t mr_value_mul (mr_value_t * result, mr_value_t * left, mr_value_t * right); 18 | extern mr_status_t mr_value_mod (mr_value_t * result, mr_value_t * left, mr_value_t * right); 19 | extern mr_status_t mr_value_bit_or (mr_value_t * result, mr_value_t * left, mr_value_t * right); 20 | extern mr_status_t mr_value_bit_and (mr_value_t * result, mr_value_t * left, mr_value_t * right); 21 | extern mr_status_t mr_value_bit_xor (mr_value_t * result, mr_value_t * left, mr_value_t * right); 22 | 23 | #endif /* _MR_VALUE_H_ */ 24 | -------------------------------------------------------------------------------- /src/scm_load.l: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | %option 8bit reentrant bison-bridge bison-locations 6 | %option warn nounput never-interactive noyywrap 7 | %option yylineno 8 | %option extra-type="mr_load_t*" 9 | %option prefix="mr_scm_" 10 | %{ 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #define MR_SCM_LTYPE mr_token_lloc_t 17 | #include 18 | #define YYSTYPE MR_SCM_STYPE 19 | #define YYLTYPE MR_SCM_LTYPE 20 | 21 | %} 22 | 23 | WS [[:space:]]+ 24 | ID [_[:alpha:]][_[:alnum:]]* 25 | INT_NUMBER [+-]?[[:digit:]]+ 26 | HEX_NUMBER [+-]?#(x|X)[[:xdigit:]]+ 27 | OCT_NUMBER [+-]?#(o|O)[[0-7]]+ 28 | FLOAT_NAN [+-]?[Nn][Aa][Nn] 29 | FLOAT_INF [+-]?[Ii][Nn][Ff] 30 | FLOAT_NUMBER {FLOAT_NAN}|{FLOAT_INF}|{INT_NUMBER}("."[[:digit:]]*)?([eE][+-]?{INT_NUMBER})? 31 | %% 32 | 33 | {WS} { return (TOK_SCM_WS); } 34 | 35 | {INT_NUMBER} { 36 | yylval->value.value_type = MR_VT_INT; 37 | yylval->value.vt_int = mr_strtouintmax (yytext, NULL, 10); 38 | return (TOK_SCM_NUMBER); 39 | } 40 | 41 | {HEX_NUMBER} { 42 | char * hash = ('#' == *yytext) ? yytext : &yytext[1]; 43 | hash[0] = '0'; 44 | yylval->value.vt_int = mr_strtouintmax (yytext, NULL, 16); 45 | yylval->value.value_type = MR_VT_INT; 46 | return (TOK_SCM_NUMBER); 47 | } 48 | 49 | {OCT_NUMBER} { 50 | char * hash = ('#' == *yytext) ? yytext : &yytext[1]; 51 | hash[0] = '0'; 52 | hash[1] = '0'; 53 | yylval->value.vt_int = mr_strtouintmax (yytext, NULL, 8); 54 | yylval->value.value_type = MR_VT_INT; 55 | return (TOK_SCM_NUMBER); 56 | } 57 | 58 | {FLOAT_NUMBER} { 59 | yylval->value.value_type = MR_VT_FLOAT; 60 | yylval->value.vt_float = strtold (yytext, NULL); 61 | return (TOK_SCM_NUMBER); 62 | } 63 | 64 | "nil" { return (TOK_SCM_FALSE); } 65 | "t" { 66 | yylval->value.value_type = MR_VT_INT; 67 | yylval->value.vt_int = true; 68 | return (TOK_SCM_NUMBER); 69 | } 70 | 71 | "\""([^\"\\]|\\.)*"\"" { 72 | yylval->string.str = &yytext[1]; 73 | yylval->string.length = strlen (yytext) - 2 * sizeof (yytext[0]); 74 | return (TOK_SCM_STRING); 75 | } 76 | 77 | "#\\". { 78 | yylval->value.value_type = MR_VT_CHAR; 79 | yylval->value.vt_char = yytext[2]; 80 | return (TOK_SCM_CHAR); 81 | } 82 | 83 | "#\\x"[[:xdigit:]]{2} { 84 | int code; 85 | sscanf (yytext, "#\\x%x", &code); 86 | yylval->value.value_type = MR_VT_CHAR; 87 | yylval->value.vt_char = code; 88 | return (TOK_SCM_CHAR); 89 | } 90 | 91 | ";"+{WS}*"("{WS}*{ID}{WS}*\.{WS}*[[:digit:]]+{WS}*")"{WS}* { 92 | mr_get_id (&yylval->id_ivalue.id, strchr (yytext, '(') + 1); 93 | yylval->id_ivalue.ivalue = strtoull (strchr (yytext, '.') + 1, NULL, 0); 94 | return (TOK_SCM_ID_IVALUE); 95 | } 96 | 97 | ";"[^\n]*{WS}* { } 98 | 99 | "("{WS}* { return (TOK_SCM_LPARENTHESIS); } 100 | {WS}*")" { return (TOK_SCM_RPARENTHESIS); } 101 | 102 | {ID} { 103 | yylval->string.str = yytext; 104 | yylval->string.length = strlen (yytext); 105 | return (TOK_SCM_ID); 106 | } 107 | 108 | {WS}+"."{WS}+ { return (TOK_SCM_DOT); } 109 | 110 | . { return (TOK_SCM_ERROR); } 111 | 112 | %% 113 | -------------------------------------------------------------------------------- /src/scm_load.y: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | %code top { 6 | #include 7 | 8 | #define MR_SCM_DEBUG 0 9 | /* Pass the argument to yyparse through to yylex. */ 10 | #define MR_SCM_LTYPE mr_token_lloc_t 11 | #define MR_LOAD (mr_scm_get_extra (scanner)) 12 | #define mr_scm_error MR_PARSE_ERROR 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #define YYSTYPE MR_SCM_STYPE 20 | #define YYLTYPE MR_SCM_LTYPE 21 | #include 22 | 23 | #define SIZEOF_QUOTE_CHAR (sizeof ("\"") - sizeof ("")) 24 | 25 | #if MR_SCM_DEBUG 26 | __attribute__ ((constructor)) void init_scm_debug (void) { mr_scm_debug = 1; } 27 | #endif /* MR_SCM_DEBUG */ 28 | } 29 | 30 | %code { 31 | static void 32 | scm_unquote_str (mr_substr_t * substr, char * dst) 33 | { 34 | typeof (substr->length) i, length; 35 | static bool initialized = false; 36 | static char map[MR_ESC_CHAR_MAP_SIZE]; 37 | 38 | if (!initialized) 39 | { 40 | memset (map, 0, sizeof (map)); 41 | for (i = 0; i < MR_ESC_CHAR_MAP_SIZE; ++i) 42 | if (mr_esc_char_map[i]) 43 | map[(unsigned char)mr_esc_char_map[i]] = i; 44 | initialized = true; 45 | } 46 | 47 | if (NULL == substr->str) 48 | return; 49 | 50 | length = 0; 51 | for (i = 0; i < substr->length; ++i) 52 | { 53 | if ('\\' == substr->str[i]) 54 | { 55 | int c = map[(unsigned char)substr->str[++i]]; 56 | int size; 57 | if (c) 58 | dst[length++] = c; 59 | else if (1 == sscanf (&substr->str[i], "x%x%n;", &c, &size)) 60 | { 61 | i += size; 62 | dst[length++] = c; 63 | } 64 | else 65 | dst[length++] = substr->str[i]; 66 | } 67 | else 68 | dst[length++] = substr->str[i]; 69 | } 70 | dst[length] = 0; 71 | } 72 | 73 | } 74 | 75 | %define api.prefix {mr_scm_} 76 | %define api.pure full 77 | %param {void * scanner} 78 | %locations 79 | /* generate include-file with symbols and types */ 80 | %defines 81 | 82 | /* a more advanced semantic type */ 83 | %union { 84 | mr_value_t value; 85 | mr_substr_t string; 86 | struct { 87 | mr_substr_t id; 88 | mr_idx_t ivalue; 89 | } id_ivalue; 90 | } 91 | 92 | /* Bison declarations. */ 93 | %token TOK_SCM_VALUE TOK_SCM_ID TOK_SCM_STRING 94 | %token TOK_SCM_CHAR TOK_SCM_NUMBER 95 | %token TOK_SCM_ID_IVALUE 96 | %token TOK_SCM_FALSE TOK_SCM_WS TOK_SCM_LPARENTHESIS TOK_SCM_RPARENTHESIS TOK_SCM_LBRACKETS TOK_SCM_RBRACKETS TOK_SCM_DOT TOK_SCM_ERROR 97 | 98 | %start ws_scm_ws 99 | 100 | %% /* The grammar follows. */ 101 | 102 | ws_scm_ws: ws scm ws 103 | 104 | scm: start_node scm_stmt { 105 | mr_load_t * mr_load = MR_LOAD; 106 | mr_load->parent = mr_load->ptrs->ra[mr_load->parent].parent; 107 | (void)mr_scm_nerrs; /* workaround compiler warning: variable 'mr_scm_nerrs' set but not used */ 108 | } 109 | 110 | start_node: { 111 | mr_load_t * mr_load = MR_LOAD; 112 | mr_idx_t idx = mr_add_ptr_to_list (mr_load->ptrs); 113 | if (MR_NULL_IDX == idx) 114 | { YYERROR; } 115 | mr_add_child (mr_load->ptrs, mr_load->parent, idx); 116 | mr_load->parent = idx; 117 | } 118 | 119 | scm_stmt: 120 | value 121 | | TOK_SCM_ID_IVALUE scm_stmt { 122 | mr_load_t * mr_load = MR_LOAD; 123 | if ($1.id.str && $1.id.length) 124 | { 125 | if (0 == mr_substrcmp (MR_REF, &$1.id)) 126 | { 127 | mr_load->ptrs->ra[mr_load->parent].first_child = $1.ivalue; 128 | mr_load->ptrs->ra[mr_load->parent].flags |= MR_IS_REFERENCE; 129 | } 130 | else if (0 == mr_substrcmp (MR_REF_CONTENT, &$1.id)) 131 | { 132 | mr_load->ptrs->ra[mr_load->parent].first_child = $1.ivalue; 133 | mr_load->ptrs->ra[mr_load->parent].flags |= MR_IS_CONTENT_REFERENCE; 134 | } 135 | else if (0 == mr_substrcmp (MR_REF_IDX, &$1.id)) 136 | { 137 | mr_load->ptrs->ra[mr_load->parent].idx = $1.ivalue; 138 | mr_load->ptrs->ra[mr_load->parent].flags |= MR_IS_REFERENCED; 139 | } 140 | } 141 | } 142 | 143 | value: 144 | compaund 145 | | named_node 146 | | TOK_SCM_CHAR { 147 | mr_load_t * mr_load = MR_LOAD; 148 | mr_status_t status = mr_value_to_mr_ptrdes (&mr_load->ptrs->ra[mr_load->parent], &$1); 149 | if (MR_SUCCESS != status) 150 | { YYERROR; } 151 | } 152 | | TOK_SCM_NUMBER { 153 | mr_load_t * mr_load = MR_LOAD; 154 | mr_status_t status = mr_value_to_mr_ptrdes (&mr_load->ptrs->ra[mr_load->parent], &$1); 155 | if (MR_SUCCESS != status) 156 | { YYERROR; } 157 | } 158 | | TOK_SCM_STRING { 159 | mr_load_t * mr_load = MR_LOAD; 160 | if (memchr ($1.str, '\\', $1.length)) 161 | { 162 | char * buf = MR_CALLOC (1, $1.length + sizeof (char)); 163 | if (NULL == buf) 164 | { 165 | MR_MESSAGE (MR_LL_FATAL, MR_MESSAGE_OUT_OF_MEMORY); 166 | YYERROR; 167 | } 168 | scm_unquote_str (&$1, buf); 169 | mr_load->ptrs->ra[mr_load->parent].value_type = MR_VT_STRING; 170 | mr_load->ptrs->ra[mr_load->parent].load_params.vt_string = buf; 171 | } 172 | else 173 | { 174 | mr_load->ptrs->ra[mr_load->parent].value_type = MR_VT_SUBSTR; 175 | mr_load->ptrs->ra[mr_load->parent].load_params.vt_substr.str = &mr_load->str[$1.str - mr_load->buf]; 176 | mr_load->ptrs->ra[mr_load->parent].load_params.vt_substr.length = $1.length; 177 | } 178 | } 179 | | TOK_SCM_FALSE { 180 | mr_load_t * mr_load = MR_LOAD; 181 | mr_load->ptrs->ra[mr_load->parent].flags |= MR_IS_NULL; 182 | mr_load->ptrs->ra[mr_load->parent].value_type = MR_VT_INT; 183 | memset (&mr_load->ptrs->ra[mr_load->parent].load_params.vt_int, 0, sizeof (mr_load->ptrs->ra[mr_load->parent].load_params.vt_int)); 184 | } 185 | 186 | compaund: TOK_SCM_LPARENTHESIS list TOK_SCM_RPARENTHESIS 187 | 188 | list: | scm ws list 189 | 190 | named_node: TOK_SCM_LPARENTHESIS TOK_SCM_ID TOK_SCM_DOT value TOK_SCM_RPARENTHESIS { 191 | mr_load_t * mr_load = MR_LOAD; 192 | $2.str[$2.length] = 0; 193 | mr_load->ptrs->ra[mr_load->parent].fdp = mr_get_any_fd_by_name ($2.str, NULL); 194 | if (NULL == mr_load->ptrs->ra[mr_load->parent].fdp) 195 | { 196 | MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_UNKNOWN_FIELD_NAME, $2.str); 197 | YYERROR; 198 | } 199 | } 200 | 201 | ws: | TOK_SCM_WS 202 | 203 | %% 204 | 205 | MR_LOAD_FUNC (scm); 206 | -------------------------------------------------------------------------------- /src/xml1_load.l: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | %option 8bit reentrant bison-bridge bison-locations 6 | %option warn nounput never-interactive noyywrap 7 | %option extra-type="mr_load_t*" 8 | %option prefix="mr_xml1_" 9 | %{ 10 | #define __USE_GNU 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #define MR_XML1_LTYPE mr_token_lloc_t 17 | #include 18 | #define YYSTYPE MR_XML1_STYPE 19 | #define YYLTYPE MR_XML1_LTYPE 20 | 21 | %} 22 | 23 | ID [_[:alpha:]][_[:alnum:]]*(:[_[:alpha:]][_[:alnum:]]*)? 24 | %% 25 | 26 | [[:space:]]+ { return (TOK_XML_WS); } 27 | 28 | {ID} { 29 | yylval->string.str = yytext; 30 | yylval->string.length = strlen (yytext); 31 | return (TOK_XML_ID); 32 | } 33 | 34 | [[:space:]]*"="[[:space:]]* { return (TOK_XML_ASSIGN); } 35 | 36 | "\""[^\"]*"\"" { 37 | yylval->string.str = &yytext[1]; 38 | yylval->string.length = strlen (yytext) - 2; 39 | return (TOK_XML_PROP_VALUE); 40 | } 41 | 42 | ""[^<]* { return (TOK_XML_DOC_CLOSE_TAG); } 44 | 45 | "<"{ID} { 46 | yylval->string.str = &yytext[1]; 47 | yylval->string.length = strlen (&yytext[1]); 48 | return (TOK_XML_OPEN_TAG); 49 | } 50 | 51 | "string.str = &yytext[2]; 53 | 54 | yylval->string.length = strlen (&yytext[2]); 55 | return (TOK_XML_CLOSE_TAG); 56 | } 57 | 58 | [[:space:]]*"/>"[^<]* { 59 | yylval->string.str = strchr (yytext, '>') + 1; 60 | yylval->string.length = strlen (yylval->string.str); 61 | return (TOK_XML_CLOSE_EMPTY_TAG); 62 | } 63 | 64 | [[:space:]]*">"[^<]* { 65 | yylval->string.str = strchr (yytext, '>') + 1; 66 | yylval->string.length = strlen (yylval->string.str); 67 | return (TOK_XML_CONTENT); 68 | } 69 | 70 | . { return (TOK_XML_ERROR); } 71 | %% 72 | 73 | -------------------------------------------------------------------------------- /src/xml2_load.c: -------------------------------------------------------------------------------- 1 | /* -*- C -*- */ 2 | /* I hate this bloody country. Smash. */ 3 | /* This file is a part of Metaresc project */ 4 | 5 | #include 6 | 7 | static mr_status_t 8 | mr_load_xml_property (xmlNodePtr node, char * property_name, mr_idx_t * idx, mr_ptrdes_flags_t * flags, mr_ptrdes_flags_t flag) 9 | { 10 | char * property = (char*)xmlGetProp (node, (unsigned char*)property_name); 11 | if (property) 12 | { 13 | char * tail = NULL; 14 | *idx = mr_strtouintmax (property, &tail, 0); 15 | if (tail) 16 | while (isspace (*tail)) 17 | ++tail; 18 | bool fail = (NULL == tail) || *tail; 19 | if (fail) 20 | MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_READ_REF, property); 21 | xmlFree (property); 22 | if (fail) 23 | return (MR_FAILURE); 24 | *flags |= flag; 25 | } 26 | return (MR_SUCCESS); 27 | } 28 | 29 | mr_idx_t 30 | mr_xml2_load (xmlNodePtr node, mr_ra_ptrdes_t * ptrs) 31 | { 32 | xmlNodePtr node_; 33 | char * content = NULL; 34 | char * property = NULL; 35 | mr_idx_t idx = mr_add_ptr_to_list (ptrs); 36 | if (MR_NULL_IDX == idx) 37 | goto failure; 38 | 39 | /* handle REF_IDX property */ 40 | if (mr_load_xml_property (node, MR_REF_IDX, &ptrs->ra[idx].idx, &ptrs->ra[idx].flags, MR_IS_REFERENCED) != MR_SUCCESS) 41 | goto failure; 42 | /* handle REF property */ 43 | if (mr_load_xml_property (node, MR_REF, &ptrs->ra[idx].first_child, &ptrs->ra[idx].flags, MR_IS_REFERENCE) != MR_SUCCESS) 44 | goto failure; 45 | /* handle REF_CONTENT property */ 46 | if (mr_load_xml_property (node, MR_REF_CONTENT, &ptrs->ra[idx].first_child, &ptrs->ra[idx].flags, MR_IS_CONTENT_REFERENCE) != MR_SUCCESS) 47 | goto failure; 48 | 49 | property = (char*)xmlGetProp (node, (unsigned char*)MR_ISNULL); 50 | if (property) 51 | { 52 | ptrs->ra[idx].flags |= MR_IS_NULL; 53 | xmlFree (property); 54 | } 55 | 56 | for (node_ = node->xmlChildrenNode; node_ && !content; node_ = node_->next) 57 | content = (char*)XML_GET_CONTENT (node_); 58 | 59 | if (NULL == content) 60 | content = ""; 61 | 62 | ptrs->ra[idx].fdp = mr_get_any_fd_by_name ((char*)node->name, NULL); 63 | if (NULL == ptrs->ra[idx].fdp) 64 | { 65 | MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_UNKNOWN_FIELD_NAME, (char*)node->name); 66 | goto failure; 67 | } 68 | 69 | ptrs->ra[idx].value_type = MR_VT_SUBSTR; 70 | ptrs->ra[idx].load_params.vt_substr.str = content; 71 | ptrs->ra[idx].load_params.vt_substr.length = strlen (content); 72 | 73 | /* loop on subnodes */ 74 | for (node_ = node->xmlChildrenNode; node_; node_ = node_->next) 75 | if (XML_ELEMENT_NODE == node_->type) 76 | { 77 | if (ptrs->ra[idx].flags & (MR_IS_REFERENCE | MR_IS_CONTENT_REFERENCE)) 78 | { 79 | MR_MESSAGE (MR_LL_ERROR, MR_MESSAGE_UNEXPECTED_SUBNODES); 80 | goto failure; 81 | } 82 | mr_idx_t child = mr_xml2_load (node_, ptrs); 83 | if (MR_NULL_IDX == child) 84 | goto failure; 85 | mr_add_child (ptrs, idx, child); 86 | } 87 | 88 | return (idx); 89 | 90 | failure: 91 | if (ptrs->ra) 92 | MR_FREE (ptrs->ra); 93 | ptrs->ra = NULL; 94 | return (0); 95 | } 96 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | /*.log 2 | /*.trs 3 | /Makefile 4 | /Makefile.in 5 | /array 6 | /bitfield 7 | /bool 8 | /char 9 | /complex_double 10 | /complex_float 11 | /complex_long_double 12 | /double 13 | /dw_export 14 | /dw_export.h 15 | /dw_types 16 | /dw_types.h 17 | /dw_types.o.dSYM/ 18 | /enum 19 | /expr 20 | /float 21 | /function 22 | /ic 23 | /int16 24 | /int32 25 | /int64 26 | /int8 27 | /long_double 28 | /mem_allocations 29 | /mf_cinit_load 30 | /mf_cinit_save 31 | /mf_json_load 32 | /mf_json_save 33 | /mf_mr_copy 34 | /mf_mr_save 35 | /mf_scm_load 36 | /mf_scm_save 37 | /mf_xdr_load 38 | /mf_xdr_save 39 | /mf_xml1_load 40 | /mf_xml1_save 41 | /mf_xml2_load 42 | /mf_xml2_save 43 | /mr_copy 44 | /mr_hash_cmp 45 | /mr_ptr 46 | /mr_types 47 | /pointer_int 48 | /pointer_other 49 | /resizable_pointer 50 | /smoke_cinit 51 | /smoke_json 52 | /smoke_scm 53 | /smoke_xdr 54 | /smoke_xml1 55 | /smoke_xml2 56 | /string 57 | /union 58 | 59 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- makefile -*- 2 | 3 | AUTOMAKE_OPTIONS = parallel-tests 4 | AM_CFLAGS = @AM_CFLAGS@ $(CHECK_CFLAGS) 5 | AM_LDFLAGS = @AM_LDFLAGS@ 6 | AM_CPPFLAGS = -I$(top_srcdir)/src 7 | LIBS += ../src/libmetaresc.la $(CHECK_LIBS) 8 | VALGRIND = valgrind --leak-check=full --error-exitcode=1 --trace-children=yes 9 | CALLGRIND = valgrind --tool=callgrind --collect-jumps=yes --quiet 10 | 11 | if HAVE_CHECK 12 | 13 | check_PROGRAMS = long_double double float string int8 int16 int32 int64 enum char array union mr_ptr bitfield pointer_int pointer_other resizable_pointer bool complex_float complex_double complex_long_double function ic btree generic_ic mr_types mem_allocations mr_copy mr_hash_cmp 14 | 15 | if HAVE_INT128 16 | check_PROGRAMS += int128 17 | endif 18 | 19 | if HAVE_PERFTEST 20 | check_PROGRAMS += union_resolution_complexity perf_save 21 | endif 22 | 23 | if HAVE_EXECINFO 24 | check_PROGRAMS += mf_mr_save mf_mr_copy 25 | endif 26 | 27 | if HAVE_XDR 28 | check_PROGRAMS += smoke_xdr 29 | if HAVE_EXECINFO 30 | check_PROGRAMS += mf_xdr_save mf_xdr_load 31 | endif 32 | endif 33 | 34 | if HAVE_BISON_FLEX 35 | check_PROGRAMS += smoke_cinit smoke_json smoke_scm smoke_xml1 expr 36 | 37 | expr.$(OBJEXT): CFLAGS += -ffast-math 38 | 39 | if HAVE_PERFTEST 40 | check_PROGRAMS += perf_cinit perf_json perf_scm perf_xml1 41 | endif 42 | if HAVE_EXECINFO 43 | check_PROGRAMS += mf_cinit_save mf_cinit_load mf_json_save mf_json_load mf_scm_save mf_scm_load mf_xml1_save mf_xml1_load 44 | endif 45 | endif 46 | 47 | if HAVE_LIBXML2 48 | check_PROGRAMS += smoke_xml2 49 | if HAVE_EXECINFO 50 | check_PROGRAMS += mf_xml2_save mf_xml2_load 51 | endif 52 | endif 53 | 54 | if HAVE_LIBYAML 55 | check_PROGRAMS += smoke_yaml 56 | if HAVE_EXECINFO 57 | check_PROGRAMS += mf_yaml_save mf_yaml_load 58 | endif 59 | endif 60 | 61 | if HAVE_LIBDWARF 62 | check_PROGRAMS += dw_export dw_types dw_types_full 63 | CLEANFILES = dw_export.h dw_types.h 64 | endif 65 | 66 | endif 67 | 68 | dw_export.$(OBJEXT): dw_export.h dw_types.h 69 | dw_types_init.$(OBJEXT): dw_types.h 70 | dw_export.h: ../src/libmetaresc.la 71 | type dsymutil && dsymutil ../src/.libs/`$(SED) -ne "/^dlname='/{s/^dlname='\(.*\)'/\1/;p;}" $?` || echo "dsymutil not found" 72 | ../src/mr_dwarf ../src/.libs/`$(SED) -ne "/^dlname='/{s/^dlname='\(.*\)'/\1/;p;}" $?` > $@ 73 | 74 | dw_types.h: dw_types$(EXEEXT) 75 | type dsymutil && dsymutil .libs/$? || echo "dsymutil not found" 76 | ../src/mr_dwarf .libs/$? > $@ 77 | 78 | dw_types_full_SOURCES = dw_types.c 79 | dw_types_full_LDADD = dw_types_init.$(OBJEXT) 80 | mf_mr_save_LDADD = mem_failures.$(OBJEXT) 81 | mf_mr_copy_LDADD = mem_failures.$(OBJEXT) 82 | mf_xdr_save_LDADD = mem_failures.$(OBJEXT) 83 | mf_xdr_load_LDADD = mem_failures.$(OBJEXT) 84 | mf_cinit_save_LDADD = mem_failures.$(OBJEXT) 85 | mf_cinit_load_LDADD = mem_failures.$(OBJEXT) 86 | mf_json_save_LDADD = mem_failures.$(OBJEXT) 87 | mf_json_load_LDADD = mem_failures.$(OBJEXT) 88 | mf_scm_save_LDADD = mem_failures.$(OBJEXT) 89 | mf_scm_load_LDADD = mem_failures.$(OBJEXT) 90 | mf_xml1_save_LDADD = mem_failures.$(OBJEXT) 91 | mf_xml1_load_LDADD = mem_failures.$(OBJEXT) 92 | mf_xml2_save_LDADD = mem_failures.$(OBJEXT) 93 | mf_xml2_load_LDADD = mem_failures.$(OBJEXT) 94 | mf_yaml_save_LDADD = mem_failures.$(OBJEXT) 95 | mf_yaml_load_LDADD = mem_failures.$(OBJEXT) 96 | 97 | TESTS=$(check_PROGRAMS) 98 | 99 | valgrind: ../src/libmetaresc.la 100 | if HAVE_LIBDWARF 101 | LD_LIBRARY_PATH="../src/.libs; $(LD_LIBRARY_PATH)" $(VALGRIND) ../src/.libs/mr_dwarf ../src/.libs/`$(SED) -ne "/^dlname='/{s/^dlname='\(.*\)'/\1/;p;}" $?` > /dev/null 102 | endif 103 | $(MAKE) $(AM_MAKEFLAGS) check LOG_COMPILER="$(LOG_COMPILER) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute $(VALGRIND)" 104 | 105 | callgrind: 106 | $(MAKE) $(AM_MAKEFLAGS) check LOG_COMPILER="$(LOG_COMPILER) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute $(CALLGRIND)" CK_FORK=no 107 | -------------------------------------------------------------------------------- /tests/bitfield.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TYPEDEF_ENUM (_enum_t, (MINUS_ONE, = -1), ZERO, ONE, (TWO, = 2), (THREE, = 3)); 6 | 7 | TYPEDEF_STRUCT (struct_bitfield_int8_t, (int8_t, x, : sizeof (int8_t) * __CHAR_BIT__ - 1)); 8 | TYPEDEF_STRUCT (struct_bitfield_uint8_t, (uint8_t, x, : sizeof (uint8_t) * __CHAR_BIT__ - 1)); 9 | TYPEDEF_STRUCT (struct_bitfield_int16_t, (int16_t, x, : sizeof (int16_t) * __CHAR_BIT__ - 1)); 10 | TYPEDEF_STRUCT (struct_bitfield_uint16_t, (uint16_t, x, : sizeof (uint16_t) * __CHAR_BIT__ - 1)); 11 | TYPEDEF_STRUCT (struct_bitfield_int32_t, (int32_t, x, : sizeof (int32_t) * __CHAR_BIT__ - 1)); 12 | TYPEDEF_STRUCT (struct_bitfield_uint32_t, (uint32_t, x, : sizeof (uint32_t) * __CHAR_BIT__ - 1)); 13 | TYPEDEF_STRUCT (struct_bitfield_int64_t, (int64_t, x, : sizeof (int64_t) * __CHAR_BIT__ - 1)); 14 | TYPEDEF_STRUCT (struct_bitfield_uint64_t, (uint64_t, x, : sizeof (uint64_t) * __CHAR_BIT__ - 1)); 15 | TYPEDEF_STRUCT (struct_bitfield_intmax_t, (mr_intmax_t, x, : sizeof (mr_intmax_t) * __CHAR_BIT__ - 1)); 16 | TYPEDEF_STRUCT (struct_bitfield_uintmax_t, (mr_uintmax_t, x, : sizeof (mr_uintmax_t) * __CHAR_BIT__ - 1)); 17 | 18 | TYPEDEF_STRUCT (struct_bitfield_enum_t, (_enum_t, x, : sizeof (_enum_t) * __CHAR_BIT__ - 1)); 19 | 20 | #define CMP_SCALAR(TYPE, X, Y, ...) ((X)->x != (Y)->x) 21 | 22 | #define ASSERT_SAVE_LOAD_BITFIELD(METHOD, VALUE) ({ \ 23 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_int8_t, VALUE, CMP_SCALAR); \ 24 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_int16_t, VALUE, CMP_SCALAR); \ 25 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_int32_t, VALUE, CMP_SCALAR); \ 26 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_int64_t, VALUE, CMP_SCALAR); \ 27 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_intmax_t, VALUE, CMP_SCALAR); \ 28 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_uint8_t, VALUE, CMP_SCALAR); \ 29 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_uint16_t, VALUE, CMP_SCALAR); \ 30 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_uint32_t, VALUE, CMP_SCALAR); \ 31 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_uint64_t, VALUE, CMP_SCALAR); \ 32 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_bitfield_uintmax_t, VALUE, CMP_SCALAR); \ 33 | }); 34 | 35 | START_TEST (bitfield_enum_zero) { ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bitfield_enum_t, ZERO); } END_TEST 36 | START_TEST (bitfield_enum_three) { ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bitfield_enum_t, THREE); } END_TEST 37 | 38 | static int warnings; 39 | 40 | static void 41 | msg_handler (const char * file_name, const char * func_name, int line, mr_log_level_t log_level, mr_message_id_t message_id, va_list args) 42 | { 43 | if (MR_MESSAGE_SAVE_ENUM == message_id) 44 | ++warnings; 45 | } 46 | 47 | #define SKIP_METHOD_XDR 0 48 | 49 | START_TEST (invalid_bitfield_enum_t) { 50 | int checked = 0; 51 | mr_msg_handler_t save_msg_handler = mr_conf.msg_handler; 52 | 53 | #define CMP_SCALAR_CNT(...) ({ ++checked; CMP_SCALAR (__VA_ARGS__);}) 54 | 55 | warnings = 0; 56 | mr_conf.msg_handler = msg_handler; 57 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bitfield_enum_t, -2, CMP_SCALAR_CNT); 58 | mr_conf.msg_handler = save_msg_handler; 59 | 60 | ck_assert_msg ((checked == warnings), "Save/load of ivnalid enum value didn't produced mathced number of warnings (%d != %d)", checked, warnings); 61 | } END_TEST 62 | 63 | #undef SKIP_METHOD_XDR 64 | 65 | START_TEST (bitfield_int_0) { 66 | ALL_METHODS (ASSERT_SAVE_LOAD_BITFIELD, 0); 67 | } END_TEST 68 | 69 | START_TEST (bitfield_int_3) { 70 | ALL_METHODS (ASSERT_SAVE_LOAD_BITFIELD, 3); 71 | } END_TEST 72 | 73 | START_TEST (bitfield_int_m1) { 74 | ALL_METHODS (ASSERT_SAVE_LOAD_BITFIELD, -1); 75 | } END_TEST 76 | 77 | START_TEST (bitfield_negative_enum) { 78 | mr_msg_handler_t save_msg_handler = mr_conf.msg_handler; 79 | 80 | warnings = 0; 81 | mr_conf.msg_handler = msg_handler; 82 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bitfield_enum_t, MINUS_ONE, CMP_SCALAR); 83 | mr_conf.msg_handler = save_msg_handler; 84 | 85 | ck_assert_msg ((0 == warnings), "Save/load of negative enum value produced %d warnings", warnings); 86 | } END_TEST 87 | 88 | MAIN_TEST_SUITE ((bitfield_enum_zero, "bitfield as enum"), 89 | (bitfield_enum_three, "bitfield as enum"), 90 | (invalid_bitfield_enum_t, "invalid enum"), 91 | (bitfield_int_0, "bitfield as integer for value 0"), 92 | (bitfield_int_3, "bitfield as integer for value 3"), 93 | (bitfield_int_m1, "bitfield as integer for value -1"), 94 | (bitfield_negative_enum, "-1 should serialize as enum value, but not integer") 95 | ); 96 | -------------------------------------------------------------------------------- /tests/bool.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | TYPEDEF_STRUCT (struct_bool_t, bool x) 8 | 9 | START_TEST (bool_false) { 10 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, bool, false); 11 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bool_t, false); 12 | } END_TEST 13 | 14 | START_TEST (bool_true) { 15 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, bool, true); 16 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bool_t, true); 17 | } END_TEST 18 | 19 | START_TEST (bool_zero) { 20 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, bool, 0); 21 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bool_t, 0); 22 | } END_TEST 23 | 24 | START_TEST (bool_nonzero) { 25 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, bool, 2); 26 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_bool_t, 2); 27 | } END_TEST 28 | 29 | MAIN_TEST_SUITE ((bool_false, "boolean false"), 30 | (bool_true, "boolean true"), 31 | (bool_zero, "boolean zero"), 32 | (bool_nonzero, "boolean non-zero") 33 | ); 34 | -------------------------------------------------------------------------------- /tests/btree.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static int 9 | uintptr_t_cmp (mr_ptr_t x, mr_ptr_t y, const void * context) 10 | { 11 | return (x.uintptr > y.uintptr) - (x.uintptr < y.uintptr); 12 | } 13 | 14 | START_TEST (ic_rbtree) { 15 | mr_tree_t rbtree; 16 | mr_tree_init (&rbtree); 17 | 18 | mr_ptr_t x = { .uintptr = 0 }; 19 | mr_ptr_t * rv0 = mr_rbtree_add (x, &rbtree, uintptr_t_cmp, NULL); 20 | ck_assert_msg (NULL != rv0, "Failed to add value to binary tree"); 21 | ck_assert_msg (rv0->uintptr == x.uintptr, "Mismatched key"); 22 | ck_assert_msg (mr_rbtree_is_valid (&rbtree, uintptr_t_cmp, NULL), "Invalid tree"); 23 | 24 | mr_ptr_t * rv = mr_rbtree_add (x, &rbtree, uintptr_t_cmp, NULL); 25 | ck_assert_msg (NULL != rv, "Failed to add value to binary tree"); 26 | ck_assert_msg (rv->uintptr == x.uintptr, "Mismatched key"); 27 | ck_assert_msg (rv == rv0, "Wrong key found"); 28 | ck_assert_msg (mr_rbtree_is_valid (&rbtree, uintptr_t_cmp, NULL), "Invalid tree"); 29 | 30 | int i; 31 | for (i = 1; i < (1 << 10); ++i) 32 | { 33 | mr_ptr_t value = { .uintptr = i }; 34 | mr_ptr_t * rv1 = mr_rbtree_add (value, &rbtree, uintptr_t_cmp, NULL); 35 | ck_assert_msg (NULL != rv1, "Failed to add value to binary tree"); 36 | ck_assert_msg (rv1->uintptr == value.uintptr, "Mismatched key"); 37 | ck_assert_msg (mr_rbtree_is_valid (&rbtree, uintptr_t_cmp, NULL), "Invalid tree"); 38 | } 39 | 40 | for (i = rbtree.size / sizeof (rbtree.pool[0]) - 1; i > 0; --i) 41 | { 42 | mr_ptr_t value = rbtree.pool[1].key; 43 | mr_status_t status = mr_rbtree_del (value, &rbtree, uintptr_t_cmp, NULL); 44 | ck_assert_msg (MR_SUCCESS == status, "Deletion rerurned failed status"); 45 | ck_assert_msg (i == rbtree.size / sizeof (rbtree.pool[0]), "Failed to del value from binary tree"); 46 | ck_assert_msg (mr_rbtree_is_valid (&rbtree, uintptr_t_cmp, NULL), "Invalid tree"); 47 | } 48 | 49 | mr_tree_free (&rbtree); 50 | } END_TEST 51 | 52 | START_TEST (ic_avltree) { 53 | mr_tree_t tree; 54 | mr_tree_init (&tree); 55 | 56 | mr_ptr_t x = { .uintptr = 0 }; 57 | mr_ptr_t * rv0 = mr_avltree_add (x, &tree, uintptr_t_cmp, NULL); 58 | ck_assert_msg (NULL != rv0, "Failed to add value to binary tree"); 59 | ck_assert_msg (rv0->uintptr == x.uintptr, "Mismatched key"); 60 | ck_assert_msg (mr_avltree_is_valid (&tree, uintptr_t_cmp, NULL), "Invalid tree"); 61 | 62 | mr_ptr_t * rv = mr_avltree_add (x, &tree, uintptr_t_cmp, NULL); 63 | ck_assert_msg (NULL != rv, "Failed to add value to binary tree"); 64 | ck_assert_msg (rv->uintptr == x.uintptr, "Mismatched key"); 65 | ck_assert_msg (rv == rv0, "Wrong key found"); 66 | ck_assert_msg (mr_avltree_is_valid (&tree, uintptr_t_cmp, NULL), "Invalid tree"); 67 | 68 | int i; 69 | for (i = 1; i < 1 << 10; ++i) 70 | { 71 | mr_ptr_t value = { .uintptr = i }; 72 | mr_ptr_t * rv1 = mr_avltree_add (value, &tree, uintptr_t_cmp, NULL); 73 | ck_assert_msg (NULL != rv1, "Failed to add value to binary tree"); 74 | ck_assert_msg (rv1->uintptr == value.uintptr, "Mismatched key"); 75 | ck_assert_msg (mr_avltree_is_valid (&tree, uintptr_t_cmp, NULL), "Invalid tree"); 76 | } 77 | 78 | for (i = tree.size / sizeof (tree.pool[0]) - 1; i > 0; --i) 79 | { 80 | mr_ptr_t value = tree.pool[1].key; 81 | mr_status_t status = mr_avltree_del (value, &tree, uintptr_t_cmp, NULL); 82 | ck_assert_msg (MR_SUCCESS == status, "Deletion rerurned failed status"); 83 | ck_assert_msg (i == tree.size / sizeof (tree.pool[0]), "Failed to del value from binary tree"); 84 | ck_assert_msg (mr_avltree_is_valid (&tree, uintptr_t_cmp, NULL), "Invalid tree"); 85 | } 86 | 87 | mr_tree_free (&tree); 88 | } END_TEST 89 | 90 | MAIN_TEST_SUITE ( 91 | (ic_rbtree, "Check red/black tree implementation"), 92 | (ic_avltree, "Check AVL tree implementation") 93 | ); 94 | -------------------------------------------------------------------------------- /tests/char.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TYPEDEF_STRUCT (struct_char_t, char x) 6 | 7 | #define SKIP_METHOD_XML2 0 8 | 9 | START_TEST (all_chars) { 10 | int i; 11 | for (i = 0; i < (1 << __CHAR_BIT__); ++i) 12 | { 13 | char c = i; 14 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, char, c); 15 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_char_t, c); 16 | } 17 | } END_TEST 18 | 19 | #undef SKIP_METHOD_XML2 20 | 21 | START_TEST (print_chars) { 22 | #ifdef HAVE_LIBXML2 23 | #undef TEST_METHODS 24 | #define TEST_METHODS XML2 25 | int i; 26 | for (i = 0; i < (1 << __CHAR_BIT__); ++i) 27 | { 28 | char c = i; 29 | if (isprint (c)) 30 | { 31 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, char, c); 32 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, struct_char_t, c); 33 | } 34 | } 35 | #endif 36 | } END_TEST 37 | 38 | MAIN_TEST_SUITE ((all_chars, "run whole charset"), 39 | (print_chars, "run printable charset for libxml2") 40 | ); 41 | -------------------------------------------------------------------------------- /tests/complex_double.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define ASSERT_SAVE_LOAD_COMPLEX_DOUBLE(METHOD, VALUE) ({ \ 8 | ASSERT_SAVE_LOAD_TYPE (METHOD, complex double, VALUE); \ 9 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_complex_double_t, VALUE); \ 10 | }) 11 | 12 | TYPEDEF_STRUCT (struct_complex_double_t, complex double x) 13 | 14 | START_TEST (zero_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, 0); } END_TEST 15 | START_TEST (nan1_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, NAN); } END_TEST 16 | START_TEST (nan2_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, NAN * I); } END_TEST 17 | START_TEST (nan3_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, NAN + NAN * I); } END_TEST 18 | START_TEST (inf_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, INFINITY); } END_TEST 19 | START_TEST (huge_val_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, HUGE_VAL - HUGE_VAL * I); } END_TEST 20 | START_TEST (dbl_max_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, DBL_MAX - DBL_MAX * I); } END_TEST 21 | START_TEST (dbl_min_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, DBL_MIN - DBL_MIN * I); } END_TEST 22 | START_TEST (dbl_epsilon_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, DBL_EPSILON - DBL_EPSILON * I); } END_TEST 23 | START_TEST (pi_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, MR_PI + MR_E * I); } END_TEST 24 | START_TEST (one1_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, 1); } END_TEST 25 | START_TEST (one2_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, I); } END_TEST 26 | START_TEST (two_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_DOUBLE, 2I); } END_TEST 27 | 28 | MAIN_TEST_SUITE ((zero_double, "zero double"), 29 | (nan1_double, "NAN double"), 30 | (nan2_double, "NAN double"), 31 | (nan3_double, "NAN double"), 32 | (inf_double, "INFINITY double"), 33 | (huge_val_double, "HUGE_VAL double"), 34 | (dbl_max_double, "DBL_MAX double"), 35 | (dbl_min_double, "DBL_MIN double"), 36 | (dbl_epsilon_double, "DBL_EPSILON double"), 37 | (pi_double, "pi + e*i long_double"), 38 | (one1_double, "1"), 39 | (one2_double, "I"), 40 | (two_double, "2I") 41 | ); 42 | -------------------------------------------------------------------------------- /tests/complex_float.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define ASSERT_SAVE_LOAD_COMPLEX_FLOAT(METHOD, VALUE) ({ \ 8 | ASSERT_SAVE_LOAD_TYPE (METHOD, complex float, VALUE); \ 9 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_complex_float_t, VALUE); \ 10 | }) 11 | 12 | TYPEDEF_STRUCT (struct_complex_float_t, complex float x) 13 | 14 | START_TEST (zero_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, 0); } END_TEST 15 | START_TEST (nan1_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, NAN); } END_TEST 16 | START_TEST (nan2_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, NAN * I); } END_TEST 17 | START_TEST (nan3_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, NAN + NAN * I); } END_TEST 18 | START_TEST (inf_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, INFINITY); } END_TEST 19 | START_TEST (huge_valf_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, HUGE_VALF - HUGE_VALF * I); } END_TEST 20 | START_TEST (flt_max_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, FLT_MAX - FLT_MAX * I); } END_TEST 21 | START_TEST (flt_min_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, FLT_MIN - FLT_MIN * I); } END_TEST 22 | START_TEST (flt_epsilon_float) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, FLT_EPSILON - FLT_EPSILON * I); } END_TEST 23 | START_TEST (pi_float_complex) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, MR_PI + MR_E * I); } END_TEST 24 | START_TEST (one1_float_complex) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, 1); } END_TEST 25 | START_TEST (one2_float_complex) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, I); } END_TEST 26 | START_TEST (two_float_complex) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_FLOAT, 2I); } END_TEST 27 | 28 | MAIN_TEST_SUITE ((zero_float, "zero float"), 29 | (nan1_float, "NAN float"), 30 | (nan2_float, "NAN float"), 31 | (nan3_float, "NAN float"), 32 | (inf_float, "INFINITY float"), 33 | (huge_valf_float, "HUGE_VALF float"), 34 | (flt_max_float, "FLT_MAX float"), 35 | (flt_min_float, "FLT_MIN float"), 36 | (flt_epsilon_float, "FLT_EPSILON float"), 37 | (pi_float_complex, "pi + e*i"), 38 | (one1_float_complex, "1"), 39 | (one2_float_complex, "I"), 40 | (two_float_complex, "2I") 41 | ); 42 | -------------------------------------------------------------------------------- /tests/complex_long_double.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE(METHOD, VALUE) ({ \ 8 | ASSERT_SAVE_LOAD_TYPE (METHOD, complex long double, VALUE); \ 9 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_complex_long_double_t, VALUE); \ 10 | }) 11 | 12 | 13 | TYPEDEF_STRUCT (struct_complex_long_double_t, complex long double x) 14 | 15 | START_TEST (zero_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, 0); } END_TEST 16 | START_TEST (nan1_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, LD_NAN); } END_TEST 17 | START_TEST (nan2_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, LD_NAN * I); } END_TEST 18 | START_TEST (nan3_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, LD_NAN + LD_NAN * I); } END_TEST 19 | START_TEST (inf_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, INFINITY); } END_TEST 20 | START_TEST (huge_val_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, HUGE_VAL - HUGE_VAL * I); } END_TEST 21 | START_TEST (ldbl_max_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, LD_LDBL_MAX - LD_LDBL_MAX * I); } END_TEST 22 | START_TEST (ldbl_min_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, LD_LDBL_MIN - LD_LDBL_MIN * I); } END_TEST 23 | START_TEST (ldbl_epsilon_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, LDBL_EPSILON - LDBL_EPSILON * I); } END_TEST 24 | START_TEST (pi_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, MR_PI + MR_E * I); } END_TEST 25 | START_TEST (one1_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, 1); } END_TEST 26 | START_TEST (one2_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, I); } END_TEST 27 | START_TEST (two_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_COMPLEX_LONG_DOUBLE, 2I); } END_TEST 28 | 29 | MAIN_TEST_SUITE ((zero_long_double, "zero long_double"), 30 | (nan1_long_double, "NAN long_double"), 31 | (nan2_long_double, "NAN long_double"), 32 | (nan3_long_double, "NAN long_double"), 33 | (inf_long_double, "INFINITY long_double"), 34 | (huge_val_long_double, "HUGE_VAL long_double"), 35 | (ldbl_max_long_double, "LDBL_MAX long_double"), 36 | (ldbl_min_long_double, "LDBL_MIN long_double"), 37 | (ldbl_epsilon_long_double, "LDBL_EPSILON long_double"), 38 | (pi_long_double, "pi + e*i long_double"), 39 | (one1_long_double, "1"), 40 | (one2_long_double, "I"), 41 | (two_long_double, "2I") 42 | ); 43 | -------------------------------------------------------------------------------- /tests/double.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define ASSERT_SAVE_LOAD_DOUBLE(METHOD, VALUE) ({ \ 7 | ASSERT_SAVE_LOAD_TYPE (METHOD, double, VALUE); \ 8 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_double_t, VALUE); \ 9 | }) 10 | 11 | TYPEDEF_STRUCT (struct_double_t, double x) 12 | 13 | START_TEST (zero_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, 0); } END_TEST 14 | START_TEST (nan_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, NAN); } END_TEST 15 | START_TEST (inf_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, INFINITY); } END_TEST 16 | START_TEST (neg_inf_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, -INFINITY); } END_TEST 17 | START_TEST (huge_val_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, HUGE_VAL); } END_TEST 18 | START_TEST (neg_huge_val_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, -HUGE_VAL); } END_TEST 19 | START_TEST (dbl_max_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, DBL_MAX); } END_TEST 20 | START_TEST (neg_dbl_max_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, -DBL_MAX); } END_TEST 21 | START_TEST (dbl_min_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, DBL_MIN); } END_TEST 22 | START_TEST (neg_dbl_min_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, -DBL_MIN); } END_TEST 23 | START_TEST (dbl_epsilon_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, DBL_EPSILON); } END_TEST 24 | START_TEST (neg_dbl_epsilon_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, -DBL_EPSILON); } END_TEST 25 | START_TEST (random_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, 1.23456789012345678909L); } END_TEST 26 | START_TEST (pi_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, MR_PI); } END_TEST 27 | START_TEST (e_double) { ALL_METHODS (ASSERT_SAVE_LOAD_DOUBLE, MR_E); } END_TEST 28 | 29 | MAIN_TEST_SUITE ((zero_double, "zero double"), 30 | (nan_double, "NAN double"), 31 | (inf_double, "INFINITY double"), 32 | (neg_inf_double, "negative INFINITY double"), 33 | (huge_val_double, "HUGE_VAL double"), 34 | (neg_huge_val_double, "negative HUGE_VAL double"), 35 | (dbl_max_double, "DBL_MAX double"), 36 | (neg_dbl_max_double, "negative DBL_MAX double"), 37 | (dbl_min_double, "DBL_MIN double"), 38 | (neg_dbl_min_double, "negative DBL_MIN double"), 39 | (dbl_epsilon_double, "DBL_EPSILON double"), 40 | (neg_dbl_epsilon_double, "negative DBL_EPSILON double"), 41 | (random_double, "random double"), 42 | (pi_double, "pi long_double"), 43 | (e_double, "e long_double") 44 | ); 45 | -------------------------------------------------------------------------------- /tests/dw_mr_types.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TYPEDEF_STRUCT (mr_pointer_t, 4 | (signed int **, int_dptr), 5 | (signed int * *, int_dptr_), 6 | (mr_type_t **, enum_dptr), 7 | (mr_type_t * *, enum_dptr_), 8 | ); 9 | 10 | #define MAKE_FIELD(TYPE) (TYPE, MR_PASTE2 (_, __COUNTER__)), (TYPE *, MR_PASTE2 (_, __COUNTER__)), 11 | 12 | TYPEDEF_STRUCT (mr_builtin_types_t, 13 | MR_FOREACH (MAKE_FIELD, MR_BUILTIN_TYPES) 14 | ); 15 | 16 | typedef char * my_string_t; 17 | 18 | TYPEDEF_STRUCT (mr_array_t, 19 | (signed int *, int_ptr_array, [2]), 20 | (mr_type_t *, enum_ptr_array, [2]), 21 | (my_string_t, my_string_array, [2]), 22 | (my_string_t *, my_string_ptrs_array, [2]), 23 | (char *, string_array, [2]), 24 | (char * *, string_ptrs_array, [2]), 25 | (int, array1d, [2]), 26 | (int, array2d, [2][3]), 27 | (int, array3d, [2][3][4]), 28 | (int, array4d, [2][3][4][1]), 29 | (int, array5d, [2][3][4][5][6]), 30 | ); 31 | 32 | TYPEDEF_STRUCT (mr_void_fields_t, 33 | VOID (mr_ptr_t, void_union), 34 | VOID (mr_array_t, void_struct), 35 | ); 36 | 37 | typedef struct mr_inline_enum_t { 38 | enum {_0} inline_enum; 39 | } mr_inline_enum_t; 40 | 41 | TYPEDEF_STRUCT (mr_anon_union_t, 42 | /* three embeded anonymous unions */ 43 | ANON_UNION (), 44 | int _0, 45 | ANON_UNION (), 46 | int _1, 47 | ANON_UNION (), 48 | int _2, 49 | END_ANON_UNION (), 50 | END_ANON_UNION (), 51 | END_ANON_UNION (), 52 | int _3, 53 | /* one more anonymous union - should be named identically by MACRO and DWARF */ 54 | ANON_UNION (), 55 | int _4, 56 | END_ANON_UNION (), 57 | /* named anonymous union. adds one more field and indexing of fields in MACRO and DWARF after this field mismatching */ 58 | ANON_UNION (name), 59 | int _5, 60 | END_ANON_UNION (), 61 | int _6, 62 | /* one more anonymous union to check that test skip anonymous unions after named anonymous unions */ 63 | ANON_UNION (), 64 | int _7, 65 | END_ANON_UNION (), 66 | ); 67 | 68 | TYPEDEF_STRUCT (mr_bitfields_t, 69 | (int, _8bits, : __CHAR_BIT__), 70 | (int, _7bits, : __CHAR_BIT__ - 1), 71 | ); 72 | -------------------------------------------------------------------------------- /tests/dw_types.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | mr_pointer_t mr_pointer; 6 | mr_builtin_types_t mr_builtin_types; 7 | mr_array_t mr_array; 8 | mr_anon_union_t mr_anon_union; 9 | mr_void_fields_t mr_void_fields; 10 | mr_inline_enum_t mr_inline_enum; 11 | mr_bitfields_t mr_bitfields; 12 | 13 | #define POSITIVE_TYPE_DETECTION(TYPE, PREFIX, SUFFIX) ({ \ 14 | TYPE PREFIX var SUFFIX; \ 15 | char * type = MR_OBJ_TYPE_DWARF (var); \ 16 | ck_assert_msg (type && (0 == strcmp (type, #TYPE)), \ 17 | "DWARF type detection mismatched for type " #TYPE #PREFIX #SUFFIX ", but got %s", type); \ 18 | }) 19 | 20 | #define NEGATIVE_TYPE_DETECTION(TYPE, PREFIX, SUFFIX) ({ \ 21 | TYPE PREFIX var SUFFIX; \ 22 | char * type = MR_OBJ_TYPE_DWARF (var); \ 23 | ck_assert_msg (type == NULL, \ 24 | "DWARF type detection mismatched for type " #TYPE #PREFIX #SUFFIX ". Expected NULL, but got %s", type); \ 25 | }) 26 | 27 | START_TEST (dw_var_type_detection) 28 | { 29 | if (NULL == mr_conf.dwarf_list) 30 | return; 31 | 32 | POSITIVE_TYPE_DETECTION (mr_type_t, , ); 33 | POSITIVE_TYPE_DETECTION (mr_type_t, *, ); 34 | POSITIVE_TYPE_DETECTION (mr_type_t, , [1]); 35 | POSITIVE_TYPE_DETECTION (mr_type_t, , [1][2]); 36 | NEGATIVE_TYPE_DETECTION (mr_type_t, *, [1]); 37 | 38 | NEGATIVE_TYPE_DETECTION (int, , ); 39 | NEGATIVE_TYPE_DETECTION (int, *, ); 40 | NEGATIVE_TYPE_DETECTION (int, , [1]); 41 | NEGATIVE_TYPE_DETECTION (int, *, [1]); 42 | NEGATIVE_TYPE_DETECTION (void, *, ); 43 | NEGATIVE_TYPE_DETECTION (void, **, ); 44 | } END_TEST 45 | 46 | MAIN_TEST_SUITE ((dw_var_type_detection, "Check variables types detection with DWARF")); 47 | -------------------------------------------------------------------------------- /tests/dw_types_init.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static mr_dwarf_t mr_dwarf[] = { 4 | #include 5 | }; 6 | 7 | static void __attribute__ ((constructor)) dw_types_init () 8 | { 9 | int i, count = sizeof (mr_dwarf) / sizeof (mr_dwarf[0]); 10 | for (i = 0; i < count; ++i) 11 | mr_add_dwarf (&mr_dwarf[i]); 12 | } 13 | -------------------------------------------------------------------------------- /tests/enum.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | TYPEDEF_ENUM (mr_enum_t, 7 | ZERO, 8 | (ONE), 9 | (TWO, = 2 /* set value explicitly */), 10 | (THREE, = 3, "comment on enum value"), 11 | (FOUR, /* value */, /* comment */, { "metadata as a void pointer" }), 12 | (FIVE, /* value */, /* comment */, { "metadata as a void pointer" }, "string" /* type of metadata void pointer as string */), 13 | (SIX, /* value */, /* comment */, { (mr_enum_t[]){ 2 } }, "mr_enum_t" /* even enum itself */), 14 | SEVEN /* trailing comma is optional */ 15 | ); 16 | 17 | TYPEDEF_ENUM (mr_signed_bitmask_t, ATTRIBUTES (__attribute__ ((packed))), 18 | (SIGNED_ZERO, = 0), 19 | (SIGNED_ONE, = 1 << 0), 20 | (SIGNED_TWO, = 1 << 1), 21 | (SIGNED_FOUR, = 1 << 2), 22 | (SIGNED_MAX, = - (1 << (__CHAR_BIT__ - 1))), 23 | ); 24 | 25 | TYPEDEF_ENUM (mr_bitmask_t, 26 | (NONE, = 0), 27 | (FIRST, = 1 << 0), 28 | (SECOND, = 1 << 1), 29 | (THIRD, = 1 << 2), 30 | (FORTH, = 1 << 3), 31 | ); 32 | 33 | TYPEDEF_ENUM (mr_enum_uint8_t, ATTRIBUTES (__attribute__ ((packed))), 34 | UINT8_ZERO, UINT8_ONE, (UINT8_TWO, = 2), (UINT8_THREE, = 3)); 35 | TYPEDEF_ENUM (mr_enum_uint16_t, ATTRIBUTES (__attribute__ ((packed))), 36 | UINT16_ZERO, UINT16_ONE, (UINT16_TWO, = 2), (UINT16_THREE, = 3), (UINT16_LAST, = 1ULL << (__CHAR_BIT__ * sizeof (uint16_t) - 1))); 37 | TYPEDEF_ENUM (mr_enum_uint32_t, ATTRIBUTES (__attribute__ ((packed))), 38 | UINT32_ZERO, UINT32_ONE, (UINT32_TWO, = 2), (UINT32_THREE, = 3), (UINT32_LAST, = 1ULL << (__CHAR_BIT__ * sizeof (uint32_t) - 1))); 39 | TYPEDEF_ENUM (mr_enum_uint64_t, ATTRIBUTES (__attribute__ ((packed))), 40 | UINT64_ZERO, UINT64_ONE, (UINT64_TWO, = 2), (UINT64_THREE, = 3), (UINT64_LAST, = 1ULL << (__CHAR_BIT__ * sizeof (uint64_t) - 1))); 41 | TYPEDEF_ENUM (mr_enum_int64_t, ATTRIBUTES (__attribute__ ((packed))), 42 | (INT64_FIRST, = -1), 43 | (INT64_LAST, = (1ULL << (__CHAR_BIT__ * sizeof (uint64_t) - 1)) - 1)); 44 | 45 | TYPEDEF_STRUCT (struct_mr_enum_t, (mr_enum_t, x)); 46 | TYPEDEF_STRUCT (struct_mr_enum_uint8_t, (mr_enum_uint8_t, x)); 47 | TYPEDEF_STRUCT (struct_mr_enum_uint16_t, (mr_enum_uint16_t, x)); 48 | TYPEDEF_STRUCT (struct_mr_enum_uint32_t, (mr_enum_uint32_t, x)); 49 | TYPEDEF_STRUCT (struct_mr_enum_uint64_t, (mr_enum_uint64_t, x)); 50 | TYPEDEF_STRUCT (struct_mr_bitmask_t, (mr_bitmask_t, x)); 51 | TYPEDEF_STRUCT (struct_mr_signed_bitmask_t, (mr_signed_bitmask_t, x)); 52 | 53 | #define ASSERT_SAVE_LOAD_ENUM(METHOD, VALUE, ...) ({ \ 54 | ASSERT_SAVE_LOAD_TYPE (METHOD, mr_enum_t, VALUE, __VA_ARGS__); \ 55 | ASSERT_SAVE_LOAD_TYPE (METHOD, mr_enum_uint8_t, VALUE, __VA_ARGS__); \ 56 | ASSERT_SAVE_LOAD_TYPE (METHOD, mr_enum_uint16_t, VALUE, __VA_ARGS__); \ 57 | ASSERT_SAVE_LOAD_TYPE (METHOD, mr_enum_uint32_t, VALUE, __VA_ARGS__); \ 58 | ASSERT_SAVE_LOAD_TYPE (METHOD, mr_enum_uint64_t, VALUE, __VA_ARGS__); \ 59 | }) 60 | 61 | #define ASSERT_SAVE_LOAD_STRUCT_ENUM(METHOD, VALUE, ...) ({ \ 62 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_mr_enum_t, VALUE, __VA_ARGS__); \ 63 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_mr_enum_uint8_t, VALUE, __VA_ARGS__); \ 64 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_mr_enum_uint16_t, VALUE, __VA_ARGS__); \ 65 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_mr_enum_uint32_t, VALUE, __VA_ARGS__); \ 66 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_mr_enum_uint64_t, VALUE, __VA_ARGS__); \ 67 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_mr_bitmask_t, VALUE, __VA_ARGS__); \ 68 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_mr_signed_bitmask_t, VALUE, __VA_ARGS__); \ 69 | }) 70 | 71 | START_TEST (zero_mr_enum_t) { ALL_METHODS (ASSERT_SAVE_LOAD_ENUM, 0); } END_TEST 72 | START_TEST (zero_mr_struct_enum_t) { ALL_METHODS (ASSERT_SAVE_LOAD_STRUCT_ENUM, 0); } END_TEST 73 | 74 | START_TEST (three_mr_enum_t) { ALL_METHODS (ASSERT_SAVE_LOAD_ENUM, (int)THREE); } END_TEST 75 | START_TEST (three_mr_struct_enum_t) { ALL_METHODS (ASSERT_SAVE_LOAD_STRUCT_ENUM, (int)THREE); } END_TEST 76 | 77 | START_TEST (seven_mr_enum_t) { ALL_METHODS (ASSERT_SAVE_LOAD_ENUM, (int)SEVEN); } END_TEST 78 | START_TEST (seven_mr_struct_enum_t) { ALL_METHODS (ASSERT_SAVE_LOAD_STRUCT_ENUM, (int)SEVEN); } END_TEST 79 | 80 | START_TEST (mr_intmax_signed_max_value) { 81 | mr_intmax_t x = INT64_FIRST; 82 | mr_intmax_t parsed_x = MR_LOAD_CINIT (mr_intmax_t, "INT64_FIRST"); 83 | ck_assert_msg ((x == parsed_x), "Parsed unsigned value mismatches static initialization"); 84 | } END_TEST 85 | 86 | START_TEST (mr_intmax_unsigned_max_value) { 87 | mr_intmax_t x = UINT64_LAST; 88 | mr_intmax_t parsed_x = MR_LOAD_CINIT (mr_intmax_t, "UINT64_LAST"); 89 | ck_assert_msg ((x == parsed_x), "Parsed unsigned value mismatches static initialization"); 90 | } END_TEST 91 | 92 | static int warnings = 0; 93 | 94 | static void 95 | msg_handler (const char * file_name, const char * func_name, int line, mr_log_level_t log_level, mr_message_id_t message_id, va_list args) 96 | { 97 | if (MR_MESSAGE_SAVE_ENUM == message_id) 98 | ++warnings; 99 | } 100 | 101 | #define SKIP_METHOD_XDR 0 102 | 103 | START_TEST (invalid_mr_enum_t) { 104 | int checked = 0; 105 | mr_msg_handler_t save_msg_handler = mr_conf.msg_handler; 106 | 107 | #define CMP_ENUMS(...) ({ ++checked; CMP_SERIALIAZED (__VA_ARGS__);}) 108 | #define CMP_STRUCT_ENUMS(...) ({ ++checked; CMP_SERIALIAZED (__VA_ARGS__);}) 109 | 110 | mr_conf.msg_handler = msg_handler; 111 | ALL_METHODS (ASSERT_SAVE_LOAD_ENUM, -1, CMP_ENUMS); 112 | ALL_METHODS (ASSERT_SAVE_LOAD_STRUCT_ENUM, -1, CMP_STRUCT_ENUMS); 113 | mr_conf.msg_handler = save_msg_handler; 114 | 115 | ck_assert_msg ((checked == warnings), "Save/load of ivnalid enum value didn't produced mathced number of warnings (%d != %d)", checked, warnings); 116 | } END_TEST 117 | 118 | #undef SKIP_METHOD_XDR 119 | 120 | MAIN_TEST_SUITE ((zero_mr_enum_t, "zero as number enum"), 121 | (zero_mr_struct_enum_t, "zero as number enum in struct"), 122 | (three_mr_enum_t, "three as enum"), 123 | (three_mr_struct_enum_t, "three as enum in struct"), 124 | (seven_mr_enum_t, "seven as enum"), 125 | (seven_mr_struct_enum_t, "seven as enum in struct"), 126 | (mr_intmax_signed_max_value, "Signed enum parsing"), 127 | (mr_intmax_unsigned_max_value, "Unsigned enum parsing"), 128 | (invalid_mr_enum_t, "invalid enum") 129 | ); 130 | -------------------------------------------------------------------------------- /tests/expr.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define ASSERT_LOAD_EXPR(TYPE, VALUE) \ 8 | ck_assert_msg (((TYPE)(VALUE) == MR_LOAD_CINIT (TYPE, #VALUE)), \ 9 | "restored value mismatched original for method CINIT on expression %s", #VALUE); \ 10 | 11 | START_TEST (parse_bool_true) { ASSERT_LOAD_EXPR (bool, true); } END_TEST 12 | START_TEST (parse_int_zero) { ASSERT_LOAD_EXPR (int, 1); } END_TEST 13 | START_TEST (parse_int_paren) { ASSERT_LOAD_EXPR (int, (1)); } END_TEST 14 | START_TEST (parse_unary_minus) { ASSERT_LOAD_EXPR (int, (1 + -1)); } END_TEST 15 | START_TEST (parse_int_sum) { ASSERT_LOAD_EXPR (int, 1 + 1); } END_TEST 16 | START_TEST (parse_complex_sum) { ASSERT_LOAD_EXPR (complex float, 1 + 1i); } END_TEST 17 | START_TEST (parse_float_op1) { ASSERT_LOAD_EXPR (float, (1. + 1i) / 2); } END_TEST 18 | START_TEST (parse_float_op2) { ASSERT_LOAD_EXPR (float, 3.14159265358979323846 + 2 * 2.7182818284590452354); } END_TEST 19 | START_TEST (parse_bits_op1) { ASSERT_LOAD_EXPR (int, 7 ^ 5 * 8); } END_TEST 20 | START_TEST (parse_bits_op2) { ASSERT_LOAD_EXPR (int, 2 | 5 * 8); } END_TEST 21 | 22 | MAIN_TEST_SUITE ((parse_bool_true, "parse bool true = (0)"), 23 | (parse_int_zero, "parse int 1"), 24 | (parse_int_paren, "parse int x = (1)"), 25 | (parse_unary_minus, "parse int x = (1 + -1)"), 26 | (parse_int_sum, "parse int x = 1 + 1"), 27 | (parse_complex_sum, "parse float complex x = 1 + 1i"), 28 | (parse_float_op1, "parse float x = (1. + 1i) / 2"), 29 | (parse_float_op2, "parse float x = MR_PI + 2 * MR_E"), 30 | (parse_bits_op1, "parse int x = 7 ^ 5 * 8"), 31 | (parse_bits_op2, "parse int x = 2 | 5 * 8") 32 | ); 33 | -------------------------------------------------------------------------------- /tests/float.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | #define ASSERT_SAVE_LOAD_FLOAT(METHOD, VALUE) ({ \ 8 | ASSERT_SAVE_LOAD_TYPE (METHOD, float, VALUE); \ 9 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_float_t, VALUE); \ 10 | }) 11 | 12 | TYPEDEF_STRUCT (struct_float_t, float x) 13 | 14 | START_TEST (zero_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, 0); } END_TEST 15 | START_TEST (nan_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, NAN); } END_TEST 16 | START_TEST (inf_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, INFINITY); } END_TEST 17 | START_TEST (neg_inf_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, -INFINITY); } END_TEST 18 | START_TEST (huge_valf_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, HUGE_VALF); } END_TEST 19 | START_TEST (neg_huge_valf_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, -HUGE_VALF); } END_TEST 20 | START_TEST (flt_max_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, FLT_MAX); } END_TEST 21 | START_TEST (neg_flt_max_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, -FLT_MAX); } END_TEST 22 | START_TEST (flt_min_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, FLT_MIN); } END_TEST 23 | START_TEST (neg_flt_min_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, -FLT_MIN); } END_TEST 24 | START_TEST (flt_epsilon_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, FLT_EPSILON); } END_TEST 25 | START_TEST (neg_flt_epsilon_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, -FLT_EPSILON); } END_TEST 26 | START_TEST (random_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, 1.23456789012345678909L); } END_TEST 27 | START_TEST (pi_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, MR_PI); } END_TEST 28 | START_TEST (e_float) { ALL_METHODS (ASSERT_SAVE_LOAD_FLOAT, MR_E); } END_TEST 29 | 30 | MAIN_TEST_SUITE ((zero_float, "zero float"), 31 | (nan_float, "NAN float"), 32 | (inf_float, "INFINITY float"), 33 | (neg_inf_float, "negtive INFINITY float"), 34 | (huge_valf_float, "HUGE_VALF float"), 35 | (neg_huge_valf_float, "negtive HUGE_VALF float"), 36 | (flt_max_float, "FLT_MAX float"), 37 | (neg_flt_max_float, "negtive FLT_MAX float"), 38 | (flt_min_float, "FLT_MIN float"), 39 | (neg_flt_min_float, "negtive FLT_MIN float"), 40 | (flt_epsilon_float, "FLT_EPSILON float"), 41 | (neg_flt_epsilon_float, "negtive FLT_EPSILON float"), 42 | (random_float, "random float"), 43 | (pi_float, "pi float"), 44 | (e_float, "e float") 45 | ); 46 | 47 | -------------------------------------------------------------------------------- /tests/function.c: -------------------------------------------------------------------------------- 1 | #define __USE_GNU 2 | #include 3 | #include 4 | #include 5 | 6 | #define PTR_CMP(TYPE, X, Y, ...) (*(void**)(X) != *(void**)(Y)) 7 | 8 | #define ASSERT_SAVE_LOAD_FUNC(METHOD, VALUE) ({ \ 9 | ASSERT_SAVE_LOAD_TYPE (METHOD, int_int_func_t, VALUE, PTR_CMP); \ 10 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_func_inline_t, VALUE, PTR_CMP); \ 11 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_func_type_t, VALUE, PTR_CMP); \ 12 | }) 13 | 14 | TYPEDEF_FUNC (int, int_int_func_t, (int)) 15 | TYPEDEF_STRUCT (struct_func_inline_t, (int, func, (int))) 16 | TYPEDEF_STRUCT (struct_func_type_t, (int_int_func_t, func)) 17 | 18 | int public_int_int_func (int x) { return (x); } 19 | static int private_int_int_func (int x) { return (x); } 20 | 21 | START_TEST (public_func) { ALL_METHODS (ASSERT_SAVE_LOAD_FUNC, public_int_int_func); } END_TEST 22 | START_TEST (private_func) { ALL_METHODS (ASSERT_SAVE_LOAD_FUNC, private_int_int_func); } END_TEST 23 | 24 | MAIN_TEST_SUITE ((public_func, "public function"), 25 | (private_func, "private function") 26 | ); 27 | 28 | -------------------------------------------------------------------------------- /tests/int.h: -------------------------------------------------------------------------------- 1 | #ifndef _INT_H_ 2 | #define _INT_H_ 3 | 4 | #define ASSERT_SAVE_LOAD_INT(METHOD, BITS, VALUE, ...) ({ \ 5 | ASSERT_SAVE_LOAD_TYPE (METHOD, uint ## BITS ## _t, VALUE, __VA_ARGS__); \ 6 | ASSERT_SAVE_LOAD_TYPE (METHOD, int ## BITS ## _t, VALUE, __VA_ARGS__); \ 7 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_uint ## BITS ## _t, VALUE, __VA_ARGS__); \ 8 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_int ## BITS ## _t, VALUE, __VA_ARGS__); \ 9 | }) 10 | 11 | #endif /* _INT_H_ */ 12 | -------------------------------------------------------------------------------- /tests/int128.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #define int128_t mr_int128_t 8 | #define uint128_t mr_uint128_t 9 | 10 | TYPEDEF_STRUCT (struct_uint128_t, (uint128_t, x)); 11 | TYPEDEF_STRUCT (struct_int128_t, (int128_t, x)); 12 | 13 | START_TEST (zero_u_int128_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 128, 0); } END_TEST 14 | START_TEST (all_bits_u_int128_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 128, -1); } END_TEST 15 | START_TEST (max_signed_u_int128_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 128, (((uint128_t)1) << (128 - 1)) - 1); } END_TEST 16 | START_TEST (min_signed_u_int128_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 128, (((uint128_t)1) << (128 - 1))); } END_TEST 17 | START_TEST (random_u_int128_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 128, 0x123456789abcdef0LL); } END_TEST 18 | 19 | MAIN_TEST_SUITE ((zero_u_int128_t, "zero [u]int128_t"), 20 | (all_bits_u_int128_t, "all bits set [u]int128_t"), 21 | (max_signed_u_int128_t, "max signed [u]int128_t"), 22 | (min_signed_u_int128_t, "min signed [u]int128_t"), 23 | (random_u_int128_t, "random [u]int128_t") 24 | ); 25 | -------------------------------------------------------------------------------- /tests/int16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (struct_uint16_t, uint16_t x) 8 | TYPEDEF_STRUCT (struct_int16_t, int16_t x) 9 | 10 | START_TEST (zero_u_int16_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 16, 0); } END_TEST 11 | START_TEST (all_bits_u_int16_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 16, -1); } END_TEST 12 | START_TEST (max_signed_u_int16_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 16, (1ULL << (16 - 1)) - 1); } END_TEST 13 | START_TEST (min_signed_u_int16_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 16, (1ULL << (16 - 1))); } END_TEST 14 | START_TEST (random_u_int16_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 16, 0x1234); } END_TEST 15 | 16 | MAIN_TEST_SUITE ((zero_u_int16_t, "zero [u]int16_t"), 17 | (all_bits_u_int16_t, "all bits set [u]int16_t"), 18 | (max_signed_u_int16_t, "max signed [u]int16_t"), 19 | (min_signed_u_int16_t, "min signed [u]int16_t"), 20 | (random_u_int16_t, "random [u]int16_t") 21 | ); 22 | -------------------------------------------------------------------------------- /tests/int32.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (struct_uint32_t, uint32_t x) 8 | TYPEDEF_STRUCT (struct_int32_t, int32_t x) 9 | 10 | START_TEST (zero_u_int32_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 32, 0); } END_TEST 11 | START_TEST (all_bits_u_int32_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 32, -1); } END_TEST 12 | START_TEST (max_signed_u_int32_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 32, (1ULL << (32 - 1)) - 1); } END_TEST 13 | START_TEST (min_signed_u_int32_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 32, (1ULL << (32 - 1))); } END_TEST 14 | START_TEST (random_u_int32_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 32, 0x12345678); } END_TEST 15 | 16 | MAIN_TEST_SUITE ((zero_u_int32_t, "zero [u]int32_t"), 17 | (all_bits_u_int32_t, "all bits set [u]int32_t"), 18 | (max_signed_u_int32_t, "max signed [u]int32_t"), 19 | (min_signed_u_int32_t, "min signed [u]int32_t"), 20 | (random_u_int32_t, "random [u]int32_t") 21 | ); 22 | -------------------------------------------------------------------------------- /tests/int64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (struct_uint64_t, uint64_t x) 8 | TYPEDEF_STRUCT (struct_int64_t, int64_t x) 9 | 10 | START_TEST (zero_u_int64_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 64, 0); } END_TEST 11 | START_TEST (all_bits_u_int64_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 64, -1); } END_TEST 12 | START_TEST (max_signed_u_int64_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 64, (1ULL << (64 - 1)) - 1); } END_TEST 13 | START_TEST (min_signed_u_int64_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 64, (1ULL << (64 - 1))); } END_TEST 14 | START_TEST (random_u_int64_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 64, 0x123456789abcdef0LL); } END_TEST 15 | 16 | MAIN_TEST_SUITE ((zero_u_int64_t, "zero [u]int64_t"), 17 | (all_bits_u_int64_t, "all bits set [u]int64_t"), 18 | (max_signed_u_int64_t, "max signed [u]int64_t"), 19 | (min_signed_u_int64_t, "min signed [u]int64_t"), 20 | (random_u_int64_t, "random [u]int64_t") 21 | ); 22 | -------------------------------------------------------------------------------- /tests/int8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | TYPEDEF_STRUCT (struct_uint8_t, uint8_t x) 8 | TYPEDEF_STRUCT (struct_int8_t, int8_t x) 9 | 10 | START_TEST (zero_u_int8_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 8, 0); } END_TEST 11 | START_TEST (all_bits_u_int8_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 8, -1); } END_TEST 12 | START_TEST (max_signed_u_int8_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 8, (1ULL << (8 - 1)) - 1); } END_TEST 13 | START_TEST (min_signed_u_int8_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 8, (1ULL << (8 - 1))); } END_TEST 14 | START_TEST (random_u_int8_t) { ALL_METHODS (ASSERT_SAVE_LOAD_INT, 8, 0x12); } END_TEST 15 | 16 | MAIN_TEST_SUITE ((zero_u_int8_t, "zero [u]int8_t"), 17 | (all_bits_u_int8_t, "all bits set [u]int8_t"), 18 | (max_signed_u_int8_t, "max signed [u]int8_t"), 19 | (min_signed_u_int8_t, "min signed [u]int8_t"), 20 | (random_u_int8_t, "random [u]int8_t") 21 | ); 22 | -------------------------------------------------------------------------------- /tests/long_double.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define SCALAR_DOUBLE(TYPE, X, Y, ...) ({ \ 7 | long_double_t _x = *(long_double_t*)(X); \ 8 | long_double_t _y = *(long_double_t*)(Y); \ 9 | bool x_non_nan = !__builtin_isnan (_x); \ 10 | bool y_non_nan = !__builtin_isnan (_y); \ 11 | bool cmp = (x_non_nan != y_non_nan); \ 12 | if (x_non_nan && y_non_nan) \ 13 | cmp = (_x != _y); \ 14 | cmp; \ 15 | }) 16 | 17 | #define ASSERT_SAVE_LOAD_LONG_DOUBLE(METHOD, VALUE) ({ \ 18 | ASSERT_SAVE_LOAD_TYPE (METHOD, long double, VALUE, SCALAR_DOUBLE); \ 19 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_long_double_t, VALUE, SCALAR_DOUBLE); \ 20 | }) 21 | 22 | TYPEDEF_STRUCT (struct_long_double_t, long_double_t x) 23 | 24 | START_TEST (zero_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, 0); } END_TEST 25 | START_TEST (nan_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, LD_NAN); } END_TEST 26 | START_TEST (inf_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, INFINITY); } END_TEST 27 | START_TEST (neg_inf_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, -INFINITY); } END_TEST 28 | START_TEST (huge_val_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, HUGE_VAL); } END_TEST 29 | START_TEST (neg_huge_val_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, -HUGE_VAL); } END_TEST 30 | START_TEST (ldbl_max_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, LD_LDBL_MAX); } END_TEST 31 | START_TEST (neg_ldbl_max_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, -LD_LDBL_MAX); } END_TEST 32 | START_TEST (ldbl_min_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, LD_LDBL_MIN); } END_TEST 33 | START_TEST (neg_ldbl_min_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, -LD_LDBL_MIN); } END_TEST 34 | START_TEST (ldbl_epsilon_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, LDBL_EPSILON); } END_TEST 35 | START_TEST (neg_ldbl_epsilon_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, -LDBL_EPSILON); } END_TEST 36 | START_TEST (random_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, 1.2345678901234566904L); } END_TEST 37 | START_TEST (pi_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, MR_PI); } END_TEST 38 | START_TEST (e_long_double) { ALL_METHODS (ASSERT_SAVE_LOAD_LONG_DOUBLE, MR_E); } END_TEST 39 | 40 | MAIN_TEST_SUITE ((zero_long_double, "zero long_double"), 41 | (nan_long_double, "NAN long_double"), 42 | (inf_long_double, "INFINITY long_double"), 43 | (neg_inf_long_double, "negative INFINITY long_double"), 44 | (huge_val_long_double, "HUGE_VAL long_double"), 45 | (neg_huge_val_long_double, "negative HUGE_VAL long_double"), 46 | (ldbl_max_long_double, "LDBL_MAX long_double"), 47 | (neg_ldbl_max_long_double, "negative LDBL_MAX long_double"), 48 | (ldbl_min_long_double, "LDBL_MIN long_double"), 49 | (neg_ldbl_min_long_double, "negative LDBL_MIN long_double"), 50 | (ldbl_epsilon_long_double, "LDBL_EPSILON long_double"), 51 | (neg_ldbl_epsilon_long_double, "negative LDBL_EPSILON long_double"), 52 | (random_long_double, "random long_double"), 53 | (pi_long_double, "pi long_double"), 54 | (e_long_double, "e long_double") 55 | ); 56 | -------------------------------------------------------------------------------- /tests/mem_allocations.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #define REFERENCE_SIZE (1 << 10) 7 | #define REFERENCE_TYPE int32_t 8 | 9 | mr_mem_t mr_mem; 10 | static int mr_malloc_cnt = 0; 11 | static int mr_realloc_cnt = 0; 12 | static int mr_free_cnt = 0; 13 | 14 | static void * _calloc (const char * filename, const char * function, int line, size_t count, size_t size) 15 | { 16 | ++mr_malloc_cnt; 17 | return (mr_mem.calloc (filename, function, line, count, size)); 18 | } 19 | 20 | static void * _realloc (const char * filename, const char * function, int line, void * ptr, size_t size) 21 | { 22 | ++mr_realloc_cnt; 23 | return (mr_mem.realloc (filename, function, line, ptr, size)); 24 | } 25 | 26 | static void _free (const char * filename, const char * function, int line, void * ptr) 27 | { 28 | ++mr_free_cnt; 29 | mr_mem.free (filename, function, line, ptr); 30 | } 31 | 32 | static int 33 | get_number_of_memory_ops (int n, void callback (mr_res_t * res)) 34 | { 35 | int i; 36 | mr_res_t res; 37 | REFERENCE_TYPE * array; 38 | 39 | res.type = MR_STRINGIFY_READONLY (REFERENCE_TYPE); 40 | res.MR_SIZE = n * sizeof (REFERENCE_TYPE); 41 | res.data.ptr = array = MR_CALLOC (n, sizeof (REFERENCE_TYPE)); 42 | 43 | ck_assert_msg (array != NULL, "Failed to allocate reference array"); 44 | 45 | for (i = 0; i < n; ++i) 46 | array[i] = i; 47 | 48 | mr_malloc_cnt = mr_realloc_cnt = mr_free_cnt = 0; 49 | callback (&res); 50 | int count = mr_malloc_cnt + mr_realloc_cnt + mr_free_cnt; 51 | 52 | MR_FREE (res.data.ptr); 53 | return (count); 54 | } 55 | 56 | static void 57 | check_mem_ops_complexity (void callback (mr_res_t * res), char * method) 58 | { 59 | mr_conf_init (); 60 | mr_mem = mr_conf.mr_mem; 61 | mr_conf.mr_mem.calloc = _calloc; 62 | mr_conf.mr_mem.realloc = _realloc; 63 | mr_conf.mr_mem.free = _free; 64 | 65 | int mem_ops_for_doubled_size = 66 | get_number_of_memory_ops (REFERENCE_SIZE << 1, callback) - get_number_of_memory_ops (REFERENCE_SIZE, callback); 67 | 68 | mr_conf.mr_mem = mr_mem; 69 | 70 | ck_assert_msg (mem_ops_for_doubled_size < 12, 71 | "Number of memory operations (%d) grows higher than logarithmically for method %s", 72 | mem_ops_for_doubled_size, method); 73 | } 74 | 75 | static void 76 | mr_save_callback (mr_res_t * res) 77 | { 78 | mr_ra_ptrdes_t ptrs = MR_SAVE (mr_res_t, res); 79 | if (ptrs.ra) 80 | MR_FREE (ptrs.ra); 81 | } 82 | 83 | START_TEST (mem_allocation_complexity_mr_save) { 84 | check_mem_ops_complexity (mr_save_callback, "MR_SAVE"); 85 | } END_TEST 86 | 87 | #define CHECK_MEM_OPS_COMPLEXITY(METHOD, ...) \ 88 | static void MR_SAVE_ ## METHOD ## _CALLBACK (mr_res_t * res) \ 89 | { \ 90 | mr_rarray_t ra = MR_SAVE_ ## METHOD ## _RA (mr_res_t, res); \ 91 | if (ra.data.ptr) \ 92 | MR_FREE (ra.data.ptr); \ 93 | } \ 94 | START_TEST (mem_allocation_complexity_ ## METHOD) { \ 95 | check_mem_ops_complexity (MR_SAVE_ ## METHOD ## _CALLBACK, #METHOD); \ 96 | } END_TEST 97 | 98 | ALL_METHODS (CHECK_MEM_OPS_COMPLEXITY); 99 | 100 | #define MEM_OPS_COMPLEXITY(METHOD) MR_IF_ELSE (MR_IS_EMPTY (METHOD)) () \ 101 | ((mem_allocation_complexity_ ## METHOD, \ 102 | "test number of memory allocations for " #METHOD),) 103 | 104 | MAIN_TEST_SUITE ( 105 | MR_FOREACH (MEM_OPS_COMPLEXITY, TEST_METHODS) 106 | (mem_allocation_complexity_mr_save, "test number of memory allocations for MR_SAVE") 107 | ); 108 | -------------------------------------------------------------------------------- /tests/mem_failures.h: -------------------------------------------------------------------------------- 1 | #ifndef _MEM_FAILURES_H_ 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | extern void tweak_types (void); 9 | extern void mem_failures_method (mr_status_t (*method) (void * arg), void * arg, bool once_per_allocation); 10 | extern mr_mem_t _mr_mem, mr_mem; 11 | 12 | #undef MR_SAVE 13 | #define MR_SAVE(MR_TYPE, PTR) ({ \ 14 | mr_ra_ptrdes_t __ptrs = MR_SAVE_TYPED (MR_TYPE, PTR); \ 15 | mr_reorder_strings (&__ptrs); \ 16 | __ptrs; \ 17 | }) 18 | 19 | #define TEST_MF_SAVE_METHOD(METHOD) \ 20 | static mr_status_t \ 21 | METHOD ## _save_method (void * arg) \ 22 | { \ 23 | mr_rarray_t ra = MR_SAVE_ ## METHOD ## _RA (mr_conf_t, &mr_conf); \ 24 | if (ra.data.ptr) \ 25 | { \ 26 | MR_FREE (ra.data.ptr); \ 27 | return (MR_SUCCESS); \ 28 | } \ 29 | return (MR_FAILURE); \ 30 | } \ 31 | START_TEST (mem_save_failures_one_per_allocation_ ## METHOD) \ 32 | { mem_failures_method (METHOD ## _save_method, NULL, true); } END_TEST \ 33 | START_TEST (mem_save_failures_on_every_allocation_ ## METHOD) \ 34 | { mem_failures_method (METHOD ## _save_method, NULL, false); } END_TEST \ 35 | MAIN_TEST_SUITE ((mem_save_failures_one_per_allocation_ ## METHOD, \ 36 | "test failure of memory allocation (once per allocation point) for " #METHOD), \ 37 | (mem_save_failures_on_every_allocation_ ## METHOD, \ 38 | "test failure of memory allocation (after N allocations) for " #METHOD) \ 39 | ); 40 | 41 | #define TEST_MF_LOAD_METHOD(METHOD) \ 42 | static mr_status_t \ 43 | METHOD ## _load_method (void * arg) \ 44 | { \ 45 | mr_conf_t _mr_conf; \ 46 | mr_status_t status; \ 47 | mr_rarray_t * ra = arg; \ 48 | memset (&_mr_conf, 0, sizeof (_mr_conf)); \ 49 | status = MR_LOAD_## METHOD ## _RA (mr_conf_t, ra, &_mr_conf); \ 50 | mr_conf.mr_mem = mr_mem; \ 51 | mr_ra_ptrdes_t ptrs = MR_SAVE (mr_conf_t, &_mr_conf); \ 52 | mr_conf.mr_mem = _mr_mem; \ 53 | if (ptrs.ra != NULL) \ 54 | { \ 55 | mr_free_recursively (&ptrs); \ 56 | mr_mem.free (NULL, NULL, 0, ptrs.ra); \ 57 | } \ 58 | return (status); \ 59 | } \ 60 | void mem_load_failures (bool once_per_allocation) \ 61 | { \ 62 | mr_conf_init (); \ 63 | tweak_types (); \ 64 | mr_rarray_t ra = MR_SAVE_ ## METHOD ## _RA (mr_conf_t, &mr_conf); \ 65 | ck_assert_msg (ra.data.ptr != NULL, "Failed to save mr_conf for tests of load methods"); \ 66 | mem_failures_method (METHOD ## _load_method, &ra, once_per_allocation); \ 67 | MR_FREE (ra.data.ptr); \ 68 | } \ 69 | START_TEST (mem_load_failures_one_per_allocation_ ## METHOD) \ 70 | { mem_load_failures (true); } END_TEST \ 71 | START_TEST (mem_load_failures_on_every_allocation_ ## METHOD) \ 72 | { mem_load_failures (false); } END_TEST \ 73 | MAIN_TEST_SUITE ((mem_load_failures_one_per_allocation_ ## METHOD, "test load memory operations failures for " #METHOD), \ 74 | (mem_load_failures_on_every_allocation_ ## METHOD, "test load memory operations failures for " #METHOD)); 75 | 76 | #endif /* _MEM_FAILURES_H_ */ 77 | -------------------------------------------------------------------------------- /tests/mf_cinit_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_LOAD_METHOD (CINIT) 4 | -------------------------------------------------------------------------------- /tests/mf_cinit_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_SAVE_METHOD (CINIT) 4 | -------------------------------------------------------------------------------- /tests/mf_json_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_LOAD_METHOD (JSON) 4 | -------------------------------------------------------------------------------- /tests/mf_json_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_SAVE_METHOD (JSON) 4 | -------------------------------------------------------------------------------- /tests/mf_mr_copy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | mr_status_t 9 | mr_copy_method (void * arg) 10 | { 11 | mr_ra_ptrdes_t * ptrs = arg; 12 | mr_conf_t _mr_conf; 13 | mr_status_t status = mr_copy_recursively (ptrs, &_mr_conf); 14 | if (MR_SUCCESS == status) 15 | { 16 | mr_conf.mr_mem = mr_mem; 17 | mr_ra_ptrdes_t alloc_ptrs = MR_SAVE (mr_conf_t, &_mr_conf); 18 | mr_conf.mr_mem = _mr_mem; 19 | if (alloc_ptrs.ra != NULL) 20 | { 21 | mr_free_recursively (&alloc_ptrs); 22 | mr_mem.free (__FILE__, __FUNCTION__, __LINE__, alloc_ptrs.ra); 23 | } 24 | return (MR_SUCCESS); 25 | } 26 | return (MR_FAILURE); 27 | } 28 | 29 | START_TEST (mem_failures_mr_copy_once_per_allocation) { 30 | mr_conf_init (); 31 | mr_ra_ptrdes_t ptrs = MR_SAVE (mr_conf_t, &mr_conf); 32 | ck_assert_msg (ptrs.ra != NULL, "Failed to save mr_conf for tests of MR_COPY_RECURSIVELY"); 33 | mem_failures_method (mr_copy_method, &ptrs, true); 34 | MR_FREE (ptrs.ra); 35 | } END_TEST 36 | 37 | MAIN_TEST_SUITE ((mem_failures_mr_copy_once_per_allocation, "test memory operations failures for MR_COPY_RECURSIVELY")); 38 | -------------------------------------------------------------------------------- /tests/mf_mr_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | mr_status_t 9 | mr_save_method (void * arg) 10 | { 11 | mr_ra_ptrdes_t ptrs = MR_SAVE (mr_conf_t, &mr_conf); 12 | if (ptrs.ra) 13 | { 14 | MR_FREE (ptrs.ra); 15 | return (MR_SUCCESS); 16 | } 17 | return (MR_FAILURE); 18 | } 19 | 20 | START_TEST (mem_failures_mr_save_once_per_allocation) { mem_failures_method (mr_save_method, NULL, true); } END_TEST 21 | START_TEST (mem_failures_mr_save_on_every_allocation) { mem_failures_method (mr_save_method, NULL, false); } END_TEST 22 | 23 | MAIN_TEST_SUITE ((mem_failures_mr_save_once_per_allocation, "test memory operations failures for MR_SAVE (fail once per allocation)"), 24 | (mem_failures_mr_save_on_every_allocation, "test memory operations failures for MR_SAVE (fail after N allocations)") 25 | ); 26 | -------------------------------------------------------------------------------- /tests/mf_scm_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_LOAD_METHOD (SCM) 4 | -------------------------------------------------------------------------------- /tests/mf_scm_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_SAVE_METHOD (SCM) 4 | -------------------------------------------------------------------------------- /tests/mf_xdr_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_LOAD_METHOD (XDR) 4 | -------------------------------------------------------------------------------- /tests/mf_xdr_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_SAVE_METHOD (XDR) 4 | -------------------------------------------------------------------------------- /tests/mf_xml1_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_LOAD_METHOD (XML1) 4 | -------------------------------------------------------------------------------- /tests/mf_xml1_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_SAVE_METHOD (XML1) 4 | -------------------------------------------------------------------------------- /tests/mf_xml2_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | static mr_status_t 8 | xml2_load_method (void * arg) 9 | { 10 | mr_conf_t _mr_conf; 11 | mr_status_t status; 12 | xmlNodePtr node = arg; 13 | memset (&_mr_conf, 0, sizeof (_mr_conf)); 14 | status = MR_LOAD_XML2_NODE_ARGS3 (mr_conf_t, node, &_mr_conf); 15 | mr_conf.mr_mem = mr_mem; 16 | mr_ra_ptrdes_t ptrs = MR_SAVE (mr_conf_t, &_mr_conf); 17 | mr_conf.mr_mem = _mr_mem; 18 | if (ptrs.ra != NULL) 19 | { 20 | mr_free_recursively (&ptrs); 21 | mr_mem.free (__FILE__, __FUNCTION__, __LINE__, ptrs.ra); 22 | } 23 | return (status); 24 | } 25 | 26 | START_TEST (mem_load_failures_xml2) 27 | { 28 | char * xml2 = MR_SAVE_XML2 (mr_conf_t, &mr_conf); 29 | ck_assert_msg (xml2 != NULL, "Failed to save mr_conf for tests of load methods"); 30 | xmlDocPtr doc = xmlParseMemory (xml2, strlen (xml2)); 31 | MR_FREE (xml2); 32 | ck_assert_msg (doc != NULL, "Failed to parse xml"); 33 | xmlNodePtr node = xmlDocGetRootElement (doc); 34 | ck_assert_msg (node != NULL, "Failed to get root element from xml document"); 35 | mem_failures_method (xml2_load_method, node, true); 36 | xmlFreeDoc (doc); 37 | } END_TEST 38 | 39 | MAIN_TEST_SUITE ((mem_load_failures_xml2, "test load memory operations failures for XML2")); 40 | -------------------------------------------------------------------------------- /tests/mf_xml2_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_SAVE_METHOD (XML2) 4 | -------------------------------------------------------------------------------- /tests/mf_yaml_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_LOAD_METHOD (YAML) 4 | -------------------------------------------------------------------------------- /tests/mf_yaml_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_MF_SAVE_METHOD (YAML) 4 | -------------------------------------------------------------------------------- /tests/mr_copy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TYPEDEF_STRUCT (ll_t, 6 | (void *, ptr)); 7 | 8 | START_TEST (mr_copy_self_void_ptr) { 9 | ll_t x, y; 10 | ll_t * _x = &x; 11 | ll_t * _y = &y; 12 | x.ptr = &x; 13 | 14 | mr_status_t status = MR_COPY_RECURSIVELY (ll_t, _x++, _y++); /* validate that post increment will happen only once */ 15 | ck_assert_msg ((MR_SUCCESS == status), "MR_COPY_RECURSIVELY failed"); 16 | ck_assert_msg ((_x - &x == 1), "multiple post increments of source"); 17 | ck_assert_msg ((_y - &y == 1), "multiple post increments of destination"); 18 | 19 | ck_assert_msg (MR_CMP_STRUCTS (ll_t, &x, &y) == 0, "MR_COPY_RECURSIVELY mismatched original"); 20 | } END_TEST 21 | 22 | #ifdef HAVE_BUILTIN_DUMP_STRUCT 23 | TYPEDEF_STRUCT (tree_t, 24 | int value, 25 | (tree_t *, children, [2]), 26 | ); 27 | 28 | START_TEST (mr_copy_single_arg) { 29 | tree_t r = {0, {(tree_t[]){{1}}, (tree_t[]){{2}}}}; 30 | tree_t c = MR_COPY_RECURSIVELY (&r); 31 | 32 | ck_assert_msg ((MR_HASH_STRUCT (tree_t, &r) == MR_HASH_STRUCT (&c)), "hash of copy mismatched original"); 33 | ck_assert_msg (MR_CMP_STRUCTS (&r, &c) == 0, "MR_COPY_RECURSIVELY mismatched original"); 34 | 35 | MR_FREE_RECURSIVELY (&c); 36 | } END_TEST 37 | #endif /* HAVE_BUILTIN_DUMP_STRUCT */ 38 | 39 | TYPEDEF_STRUCT (const_field_t, const int x); 40 | 41 | START_TEST (mr_copy_const_field) { 42 | const_field_t x = { 123 }; 43 | const_field_t y = MR_COPY_RECURSIVELY (const_field_t, &x); 44 | int orig_eq_restored = (0 == CMP_SERIALIAZED (const_field_t, &x, &y)); 45 | ck_assert_msg (orig_eq_restored, "dump of MR_COPY_RECURSIVELY mismatched dump of original const_field_t"); 46 | } END_TEST 47 | 48 | START_TEST (mr_copy_args2) { 49 | mr_conf_t mr_conf_copy = MR_COPY_RECURSIVELY (mr_conf_t, &mr_conf); 50 | int orig_eq_restored = (0 == CMP_SERIALIAZED (mr_conf_t, &mr_conf, &mr_conf_copy)); 51 | ck_assert_msg (orig_eq_restored, "dump of MR_COPY_RECURSIVELY mismatched dump of original mr_conf"); 52 | MR_FREE_RECURSIVELY (mr_conf_t, &mr_conf_copy); 53 | } END_TEST 54 | 55 | START_TEST (mr_copy_arg3) { 56 | mr_conf_t mr_conf_copy; 57 | int orig_eq_restored; 58 | mr_status_t status = MR_COPY_RECURSIVELY (mr_conf_t, &mr_conf, &mr_conf_copy); 59 | ck_assert_msg ((MR_SUCCESS == status), "MR_COPY_RECURSIVELY failed"); 60 | orig_eq_restored = (0 == CMP_SERIALIAZED (mr_conf_t, &mr_conf, &mr_conf_copy)); 61 | ck_assert_msg (orig_eq_restored, "dump of MR_COPY_RECURSIVELY mismatched dump of original mr_conf"); 62 | MR_FREE_RECURSIVELY (mr_conf_t, &mr_conf_copy); 63 | } END_TEST 64 | 65 | MAIN_TEST_SUITE ((mr_copy_self_void_ptr, "test MR_COPY_RECURSIVELY works for self-refereed void pointers"), 66 | #ifdef HAVE_BUILTIN_DUMP_STRUCT 67 | (mr_copy_single_arg, "test single argumets MR_COPY_RECURSIVELY, MR_HASH_STRUCT, MR_CMP_STRUCTS, MR_FREE_RECURSIVELY"), 68 | #endif /* HAVE_BUILTIN_DUMP_STRUCT */ 69 | (mr_copy_const_field, "test that MR_COPY_RECURSIVELY works for struct with const field"), 70 | (mr_copy_args2, "test that dump of mr_conf matches with dump of MR_COPY_RECURSIVELY (mr_conf_t, &mr_conf)"), 71 | (mr_copy_arg3, "test that dump of mr_conf matches with dump of MR_COPY_RECURSIVELY (mr_conf_t, &mr_conf, &mr_conf_copy)") 72 | ); 73 | -------------------------------------------------------------------------------- /tests/mr_ptr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | MR_TYPEDEF_DESC_BI (ca2_t); 9 | 10 | #define ASSERT_SAVE_LOAD_MR_PTR(METHOD, TYPE, VALUE, ...) ({ \ 11 | struct_mr_ptr_t x = { .dummy = 0, { (TYPE[]){ { .dummy = 0, { MR_PI }, VALUE } } }, #TYPE }; \ 12 | ASSERT_SAVE_LOAD (METHOD, struct_mr_ptr_t, &x, __VA_ARGS__); \ 13 | }) 14 | 15 | START_TEST (union_mr_ptr_int) { 16 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_int8_t, 1); 17 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_int16_t, 1); 18 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_int32_t, 1); 19 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_int64_t, 1); 20 | } END_TEST 21 | 22 | START_TEST (union_mr_ptr_enum) { 23 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_enum8_t, U8D_INT32); 24 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_enum16_t, U16D_INT32); 25 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_enum32_t, U32D_INT32); 26 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_enum64_t, U64D_INT32); 27 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_enum_t, UD_INT32); 28 | } END_TEST 29 | 30 | START_TEST (union_mr_ptr_enum_ptr) { 31 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_enum_ptr_t, (enum_discriminator_t[]){ UD_INT32 }); 32 | } END_TEST 33 | 34 | START_TEST (union_mr_ptr_string_y) { 35 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_string_t, "y"); 36 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_ca_t, "y"); 37 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_string_ptr_t, (string_t[]){ "y" }); 38 | ALL_METHODS (ASSERT_SAVE_LOAD_MR_PTR, struct_union_ca_ptr_t, (ca2_t[]){ "y" }); 39 | } END_TEST 40 | 41 | START_TEST (union_mr_ptr_string) { 42 | struct_mr_ptr_t x = { .dummy = 0, { "string_t" }, "string" }; 43 | ALL_METHODS (ASSERT_SAVE_LOAD, struct_mr_ptr_t, &x); 44 | x.ptr.ptr = "string longer then sizeof (char)"; 45 | ALL_METHODS (ASSERT_SAVE_LOAD, struct_mr_ptr_t, &x); 46 | } END_TEST 47 | 48 | MAIN_TEST_SUITE ((union_mr_ptr_int, "mr_ptr_t is a pointer on any Metaresc type"), 49 | (union_mr_ptr_enum, "mr_ptr_t is a pointer on any Metaresc type"), 50 | (union_mr_ptr_enum_ptr, "mr_ptr_t is a pointer on any Metaresc type"), 51 | (union_mr_ptr_string_y, "mr_ptr_t is a pointer on any Metaresc type"), 52 | (union_mr_ptr_string, "mr_ptr_t is a pointer on any Metaresc type") 53 | ); 54 | -------------------------------------------------------------------------------- /tests/perf.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #define TEST_PERFORMANCE(METHOD, ...) \ 10 | TYPEDEF_STRUCT (list_t, (mr_ptr_t, mr_ptr, , "ptr_type"), (list_t *, next)); \ 11 | TYPEDEF_STRUCT (typed_list_t, (char *, ptr_type), (list_t *, root)); \ 12 | TYPEDEF_STRUCT (array_t, (list_t *, ra, , , { "size" }, "string"), (ssize_t, size), (char *, ptr_type)); \ 13 | \ 14 | int test_run (int count) \ 15 | { \ 16 | int i; \ 17 | array_t array, array_; \ 18 | mr_rarray_t ra; \ 19 | typed_list_t list_, typed_list = { .ptr_type = "string", }; \ 20 | memset (&array, 0, sizeof (array)); \ 21 | array.size = count * sizeof (array.ra[0]); \ 22 | array.ptr_type = "string"; \ 23 | array.ra = MR_CALLOC (count, sizeof (array.ra[0])); \ 24 | ck_assert_msg (NULL != array.ra, "Memory allocation failed."); \ 25 | for (i = 1; i < count; ++i) \ 26 | { \ 27 | array.ra[i - 1].next = &array.ra[i]; \ 28 | array.ra[i - 1].mr_ptr.ptr = "string"; \ 29 | } \ 30 | array.ra[count - 1].next = &array.ra[0]; \ 31 | array.ra[count - 1].mr_ptr.ptr = "string"; \ 32 | typed_list.root = &array.ra[0]; \ 33 | clock_t _start = clock (); \ 34 | ra = MR_SAVE_ ## METHOD ## _RA (typed_list_t, &typed_list); \ 35 | ck_assert_msg ((ra.MR_SIZE > 0) && (ra.data.ptr != NULL), \ 36 | "Serialization for method " #METHOD " failed."); \ 37 | ck_assert_msg (MR_SUCCESS == \ 38 | MR_LOAD_ ## METHOD ## _RA (typed_list_t, &ra, &list_), \ 39 | "Deserialization for method " #METHOD " failed."); \ 40 | MR_FREE_RECURSIVELY (typed_list_t, &list_); \ 41 | MR_FREE (ra.data.ptr); \ 42 | ra = MR_SAVE_ ## METHOD ## _RA (array_t, &array); \ 43 | ck_assert_msg ((ra.MR_SIZE > 0) && (ra.data.ptr != NULL), \ 44 | "Serialization for method " #METHOD " failed."); \ 45 | ck_assert_msg (MR_SUCCESS == \ 46 | MR_LOAD_ ## METHOD ## _RA (array_t, &ra, &array_), \ 47 | "Deserialization for method " #METHOD " failed."); \ 48 | MR_FREE_RECURSIVELY (array_t, &array_); \ 49 | MR_FREE (ra.data.ptr); \ 50 | MR_FREE (array.ra); \ 51 | clock_t _finish = clock (); \ 52 | return (_finish - _start); \ 53 | } \ 54 | \ 55 | START_TEST (test_performance) { \ 56 | mr_conf_init (); \ 57 | int i, size = 1 << 8; \ 58 | int base_time, double_time = test_run (size); \ 59 | do { \ 60 | size <<= 1; \ 61 | base_time = double_time; \ 62 | double_time = test_run (size); \ 63 | } while (double_time < CLOCKS_PER_SEC / 8); \ 64 | for (i = 0; i < 3; ++i) \ 65 | { \ 66 | int another_try = test_run (size); \ 67 | double_time = MR_MIN (double_time, another_try); \ 68 | } \ 69 | ck_assert_msg (double_time < (5 * base_time) / 2, "performance issue for method " #METHOD " %d / %d = %.02g", double_time, base_time, (double)double_time / base_time); \ 70 | } END_TEST \ 71 | int main (int argc, char * argv[]) \ 72 | { \ 73 | int number_failed; \ 74 | Suite * suite = suite_create ("main"); \ 75 | if (NULL == suite) \ 76 | return (EXIT_FAILURE); \ 77 | SRunner * srunner = srunner_create (suite); \ 78 | if (NULL == srunner) \ 79 | return (EXIT_FAILURE); \ 80 | TCase * tcase = tcase_create ("performance test"); \ 81 | if (NULL == tcase) \ 82 | return (EXIT_FAILURE); \ 83 | tcase_set_timeout (tcase, 0); \ 84 | tcase_add_test (tcase, test_performance); \ 85 | suite_add_tcase (suite, tcase); \ 86 | srunner_run_all (srunner, CK_ENV); \ 87 | number_failed = srunner_ntests_failed (srunner); \ 88 | srunner_free (srunner); \ 89 | return ((number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE); \ 90 | } 91 | -------------------------------------------------------------------------------- /tests/perf_cinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_PERFORMANCE (CINIT) 4 | -------------------------------------------------------------------------------- /tests/perf_json.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_PERFORMANCE (JSON) 4 | -------------------------------------------------------------------------------- /tests/perf_save.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MR_SAVE_NONE_RA(...) ({ \ 4 | mr_ra_ptrdes_t ptrs = MR_SAVE (__VA_ARGS__); \ 5 | mr_rarray_t _ra_; \ 6 | _ra_.data.ptr = ptrs.ra; \ 7 | _ra_.MR_SIZE = ptrs.size; \ 8 | _ra_.type = "mr_ptrdes_t"; \ 9 | _ra_; \ 10 | }) 11 | #define MR_LOAD_NONE_RA(TYPE, RA, PTR) ({ \ 12 | memset (PTR, 0, sizeof (*PTR)); \ 13 | MR_SUCCESS; \ 14 | }) 15 | 16 | TEST_PERFORMANCE (NONE) 17 | -------------------------------------------------------------------------------- /tests/perf_scm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_PERFORMANCE (SCM) 4 | -------------------------------------------------------------------------------- /tests/perf_xml1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | TEST_PERFORMANCE (XML1) 4 | -------------------------------------------------------------------------------- /tests/pointer_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | TYPEDEF_STRUCT (int32_dptr_t, (int32_t **, x)); 6 | 7 | TYPEDEF_STRUCT (int8_ptr_t, (int8_t *, x)); 8 | TYPEDEF_STRUCT (uint8_ptr_t, (uint8_t *, x)); 9 | TYPEDEF_STRUCT (int16_ptr_t, (int16_t *, x)); 10 | TYPEDEF_STRUCT (uint16_ptr_t, (uint16_t *, x)); 11 | TYPEDEF_STRUCT (int32_ptr_t, (int32_t *, x)); 12 | TYPEDEF_STRUCT (uint32_ptr_t, (uint32_t *, x)); 13 | TYPEDEF_STRUCT (int64_ptr_t, (int64_t *, x)); 14 | TYPEDEF_STRUCT (uint64_ptr_t, (uint64_t *, x)); 15 | 16 | START_TEST (int32_dptr) { 17 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_dptr_t, NULL); 18 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_dptr_t, (int32_t*[]){ NULL }); 19 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_dptr_t, (int32_t*[]){ (int32_t[]){ 0 } }); 20 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_dptr_t, (int32_t*[]){ (int32_t[]){ -1 } }); 21 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_dptr_t, (int32_t*[]){ (int32_t[]){ 1 } }); 22 | } END_TEST 23 | 24 | START_TEST (int8_ptr) { 25 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int8_ptr_t, NULL); 26 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int8_ptr_t, (int8_t[]){ 0 }); 27 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int8_ptr_t, (int8_t[]){ -1 }); 28 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int8_ptr_t, (int8_t[]){ 1 }); 29 | } END_TEST 30 | 31 | START_TEST (uint8_ptr) { 32 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint8_ptr_t, NULL); 33 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint8_ptr_t, (uint8_t[]){ 0 }); 34 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint8_ptr_t, (uint8_t[]){ -1 }); 35 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint8_ptr_t, (uint8_t[]){ 1 }); 36 | } END_TEST 37 | 38 | START_TEST (int16_ptr) { 39 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int16_ptr_t, NULL); 40 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int16_ptr_t, (int16_t[]){ 0 }); 41 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int16_ptr_t, (int16_t[]){ -1 }); 42 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int16_ptr_t, (int16_t[]){ 1 }); 43 | } END_TEST 44 | 45 | START_TEST (uint16_ptr) { 46 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint16_ptr_t, NULL); 47 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint16_ptr_t, (uint16_t[]){ 0 }); 48 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint16_ptr_t, (uint16_t[]){ -1 }); 49 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint16_ptr_t, (uint16_t[]){ 1 }); 50 | } END_TEST 51 | 52 | START_TEST (int32_ptr) { 53 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_ptr_t, NULL); 54 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_ptr_t, (int32_t[]){ 0 }); 55 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_ptr_t, (int32_t[]){ -1 }); 56 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int32_ptr_t, (int32_t[]){ 1 }); 57 | } END_TEST 58 | 59 | START_TEST (uint32_ptr) { 60 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint32_ptr_t, NULL); 61 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint32_ptr_t, (uint32_t[]){ 0 }); 62 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint32_ptr_t, (uint32_t[]){ -1 }); 63 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint32_ptr_t, (uint32_t[]){ 1 }); 64 | } END_TEST 65 | 66 | START_TEST (int64_ptr) { 67 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int64_ptr_t, NULL); 68 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int64_ptr_t, (int64_t[]){ 0 }); 69 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int64_ptr_t, (int64_t[]){ -1 }); 70 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, int64_ptr_t, (int64_t[]){ 1 }); 71 | } END_TEST 72 | 73 | START_TEST (uint64_ptr) { 74 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint64_ptr_t, NULL); 75 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint64_ptr_t, (uint64_t[]){ 0 }); 76 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint64_ptr_t, (uint64_t[]){ -1 }); 77 | ALL_METHODS (ASSERT_SAVE_LOAD_TYPE, uint64_ptr_t, (uint64_t[]){ 1 }); 78 | } END_TEST 79 | 80 | MAIN_TEST_SUITE ((int32_dptr, "double pointer on int"), 81 | (int8_ptr, "pointer on int"), 82 | (uint8_ptr, "pointer on uint"), 83 | (int16_ptr, "pointer on int"), 84 | (uint16_ptr, "pointer on uint"), 85 | (int32_ptr, "pointer on int"), 86 | (uint32_ptr, "pointer on uint"), 87 | (int64_ptr, "pointer on int"), 88 | (uint64_ptr, "pointer on uint") 89 | ); 90 | -------------------------------------------------------------------------------- /tests/regression.h: -------------------------------------------------------------------------------- 1 | #ifndef _REGRESSION_H_ 2 | #define _REGRESSION_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include /* MR_TYPED_TYPES */ 10 | 11 | #ifdef HAVE_BISON_FLEX 12 | #define BISON_FLEX_METHODS XML1, SCM, CINIT, JSON, 13 | #else /* HAVE_BISON_FLEX */ 14 | #define BISON_FLEX_METHODS 15 | #endif /* HAVE_BISON_FLEX */ 16 | 17 | #ifdef HAVE_LIBXML2 18 | #define LIBXML2_METHODS XML2, 19 | #else /* HAVE_LIBXML2 */ 20 | #define LIBXML2_METHODS 21 | #endif /* HAVE_LIBXML2 */ 22 | 23 | #ifdef HAVE_LIBYAML 24 | #define LIBYAML_METHODS YAML, 25 | #else /* HAVE_LIBYAML */ 26 | #define LIBYAML_METHODS 27 | #endif /* HAVE_LIBYAML */ 28 | 29 | #ifdef HAVE_RPC_TYPES_H 30 | #define XDR_METHODS XDR 31 | #else /* HAVE_RPC_TYPES_H */ 32 | #define XDR_METHODS 33 | #endif /* HAVE_RPC_TYPES_H */ 34 | 35 | #define TEST_METHODS LIBXML2_METHODS LIBYAML_METHODS BISON_FLEX_METHODS XDR_METHODS 36 | 37 | #define CMP_SERIALIAZED(TYPE, X, Y, ...) MR_CMP_STRUCTS(TYPE, X, Y) 38 | 39 | #define SKIP_METHOD_ 0 40 | 41 | #define MR_IS__EQ__ 0 42 | 43 | #define ASSERT_SAVE_LOAD(METHOD, TYPE, X, ...) \ 44 | MR_IF_ELSE (MR_PASTE2 (SKIP_METHOD_, METHOD)) \ 45 | (ASSERT_SAVE_LOAD_(METHOD, TYPE, X, __VA_ARGS__)) (0) 46 | 47 | #define ASSERT_SAVE_LOAD_(METHOD, TYPE, X, TYPE_CMP, ...) \ 48 | MR_IF_ELSE (MR_PASTE3 (MR_IS__EQ_, TYPE_CMP, _)) \ 49 | (ASSERT_SAVE_LOAD__ (METHOD, TYPE, X, TYPE_CMP, __VA_ARGS__)) \ 50 | (ASSERT_SAVE_LOAD__ (METHOD, TYPE, X, CMP_SERIALIAZED, __VA_ARGS__)) 51 | 52 | #define ASSERT_SAVE_LOAD__(METHOD, TYPE, X, TYPE_CMP, ...) ({ \ 53 | mr_rarray_t serialized = MR_SAVE_ ## METHOD ## _RA (TYPE, X); \ 54 | int orig_eq_restored, load_success; \ 55 | TYPE METHOD ## _restored; \ 56 | memset (&METHOD ## _restored, 0, sizeof (TYPE)); \ 57 | load_success = (MR_SUCCESS == MR_LOAD_ ## METHOD ## _RA (TYPE, &serialized, &METHOD ## _restored)); \ 58 | ck_assert_msg (load_success, \ 59 | "load for method " #METHOD " on type " #TYPE " failed"); \ 60 | if (serialized.data.ptr) \ 61 | MR_FREE (serialized.data.ptr); \ 62 | orig_eq_restored = (0 == TYPE_CMP (TYPE, X, &METHOD ## _restored, __VA_ARGS__)); \ 63 | ck_assert_msg (orig_eq_restored, \ 64 | "restored value mismatched original for method " #METHOD " on type " #TYPE); \ 65 | MR_FREE_RECURSIVELY (TYPE, &METHOD ## _restored); \ 66 | }) 67 | 68 | #define ASSERT_SAVE_LOAD_TYPE(METHOD, TYPE, VALUE, ...) ({ \ 69 | TYPE x = { VALUE }; \ 70 | ASSERT_SAVE_LOAD (METHOD, TYPE, &x, __VA_ARGS__); \ 71 | }) 72 | 73 | #define ASSERT_GET_TEST(TEST, ...) TEST 74 | #define ASSERT_GET_ARGS(TEST, ...) __VA_ARGS__ 75 | #define ASSERT_ITERATOR(ARGS, METHOD, I) MR_IF_ELSE (MR_IS_EMPTY (METHOD)) () (ASSERT_ITERATOR_ (ASSERT_GET_TEST ARGS, METHOD, ASSERT_GET_ARGS ARGS)) 76 | #define ASSERT_ITERATOR_(TEST, METHOD, ...) MR_IF_ELSE (SKIP_METHOD_ ## METHOD) (TEST (METHOD, __VA_ARGS__)) () 77 | #define SERIAL(NAME, I, REC, X) REC; X 78 | #define ALL_METHODS(...) MR_FOR ((__VA_ARGS__), MR_NARG (TEST_METHODS), SERIAL, ASSERT_ITERATOR, TEST_METHODS) 79 | 80 | #define ADD_TCASE(NAME_DESCRIPTION) { \ 81 | TCase * tcase = tcase_create ("" P00_GET_SECOND NAME_DESCRIPTION); \ 82 | if (tcase) \ 83 | { \ 84 | tcase_set_timeout (tcase, 120); \ 85 | tcase_add_test (tcase, P00_GET_FIRST NAME_DESCRIPTION); \ 86 | suite_add_tcase (suite, tcase); \ 87 | } \ 88 | } 89 | 90 | #define MAIN_TEST_SUITE(...) \ 91 | int main (int argc, char * argv[]) \ 92 | { \ 93 | int number_failed; \ 94 | Suite * suite = suite_create (__FILE__); \ 95 | if (NULL == suite) \ 96 | return (EXIT_FAILURE); \ 97 | MR_FOREACH (ADD_TCASE, __VA_ARGS__); \ 98 | SRunner * srunner = srunner_create (suite); \ 99 | srunner_run_all (srunner, CK_ENV); \ 100 | number_failed = srunner_ntests_failed (srunner); \ 101 | srunner_free (srunner); \ 102 | return ((number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE); \ 103 | } \ 104 | 105 | static inline void 106 | mr_ra_ptrdes_eq (mr_ra_ptrdes_t * ptrs, mr_ptrdes_t * expected, size_t expected_size) 107 | { 108 | ck_assert_msg (ptrs->size == expected_size, "size mismatch %d != %d", (int)ptrs->size, (int)expected_size); 109 | int i, count = expected_size / sizeof (*expected); 110 | for (i = 1; i < count; ++i) 111 | { 112 | ck_assert_msg (strcmp (ptrs->ra[i].fdp->name.str, expected[i].fdp->name.str) == 0, 113 | "[%d] name %s != %s", i, ptrs->ra[i].fdp->name.str, expected[i].fdp->name.str); 114 | ck_assert_msg (ptrs->ra[i].mr_type == expected[i].mr_type, 115 | "[%d] mr_type %d != %d", i, ptrs->ra[i].mr_type, expected[i].mr_type); 116 | 117 | if ((MR_TYPED_TYPES >> ptrs->ra[i].mr_type) & 1) 118 | ck_assert_msg (strcmp (ptrs->ra[i].fdp->stype.type, expected[i].fdp->stype.type) == 0, 119 | "[%d] type %s != %s", i, ptrs->ra[i].fdp->stype.type, expected[i].fdp->stype.type); 120 | ck_assert_msg (ptrs->ra[i].flags == expected[i].flags, 121 | "[%d] flags %d != %d", i, ptrs->ra[i].flags, expected[i].flags); 122 | ck_assert_msg (ptrs->ra[i].first_child == expected[i].first_child, 123 | "[%d] first_child %d != %d", i, ptrs->ra[i].first_child, expected[i].first_child); 124 | ck_assert_msg (ptrs->ra[i].next == expected[i].next, 125 | "[%d] next %d != %d", i, ptrs->ra[i].next, expected[i].next); 126 | } 127 | } 128 | 129 | #define ASSERT_MR_SAVE(TYPE, S_PTR, EXPECTED) ({ \ 130 | mr_ra_ptrdes_t ptrs = MR_SAVE (TYPE, S_PTR); \ 131 | ck_assert_msg (ptrs.ra != NULL, "Failed to MR_SAVE"); \ 132 | mr_ra_ptrdes_eq (&ptrs, EXPECTED, sizeof (EXPECTED)); \ 133 | MR_FREE (ptrs.ra); \ 134 | }) 135 | 136 | #endif /* _REGRESSION_H_ */ 137 | -------------------------------------------------------------------------------- /tests/smoke.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | /* 9 | Test is doing the following: 10 | 1. serialize mr_conf - library config structure 11 | 2. load back config from serialized representation into another variable 12 | 3. replace global variable with the main mr_conf on a loaded one 13 | 4. serialize mr_conf once again using loaded configuration 14 | 5. match it with the first dump 15 | 6. restore mr_conf from saved copy 16 | 7. free up all allocated memory 17 | 18 | One more test checks that complexity of save/load is not O(n * n). It should be O(n). 19 | Methods that have limitation of structure depth due to recursive implementation should define 20 | SKIP_PERFORMANCE_TEST_{METHOD} to 0 21 | */ 22 | 23 | #define SMOKE_METHOD(METHOD, ...) START_TEST (mr_conf_save_load) { \ 24 | mr_conf_init (); \ 25 | mr_conf_t mr_conf_saved = mr_conf; \ 26 | mr_conf_t * src = &mr_conf; \ 27 | mr_rarray_t mr_conf_serialized = MR_SAVE_ ## METHOD ## _RA (mr_conf_t, src++); \ 28 | ck_assert_msg (src - &mr_conf == 1, "Multiple src post increment for method " #METHOD); \ 29 | ck_assert_msg (((0 != mr_conf_serialized.MR_SIZE) && (NULL != mr_conf_serialized.data.ptr)), \ 30 | "save for method " #METHOD " failed"); \ 31 | mr_conf_t mr_conf_loaded; \ 32 | mr_conf_t * dst = &mr_conf_loaded; \ 33 | memset (&mr_conf_loaded, 0, sizeof (mr_conf_loaded)); \ 34 | mr_status_t status = MR_LOAD_ ## METHOD ## _RA (mr_conf_t, &mr_conf_serialized, dst++); \ 35 | ck_assert_msg (dst - &mr_conf_loaded == 1, "Multiple dst post increment for method " #METHOD); \ 36 | ck_assert_msg (MR_SUCCESS == status, "load for method " #METHOD " failed"); \ 37 | mr_conf = mr_conf_loaded; \ 38 | mr_rarray_t mr_conf_serialized_ = MR_SAVE_ ## METHOD ## _RA (mr_conf_t, &mr_conf); \ 39 | ck_assert_msg ((mr_conf_serialized.MR_SIZE == mr_conf_serialized_.MR_SIZE) && \ 40 | (0 == memcmp (mr_conf_serialized.data.ptr, mr_conf_serialized_.data.ptr, mr_conf_serialized.MR_SIZE)), \ 41 | "restored mr_conf mismatched original dump for method " #METHOD); \ 42 | MR_FREE (mr_conf_serialized_.data.ptr); \ 43 | MR_FREE (mr_conf_serialized.data.ptr); \ 44 | mr_conf = mr_conf_saved; \ 45 | MR_FREE_RECURSIVELY (mr_conf_t, &mr_conf_loaded); \ 46 | } END_TEST \ 47 | \ 48 | int main (int argc, char * argv[]) \ 49 | { \ 50 | int number_failed; \ 51 | Suite * suite = suite_create ("main"); \ 52 | if (NULL == suite) \ 53 | return (EXIT_FAILURE); \ 54 | SRunner * srunner = srunner_create (suite); \ 55 | if (NULL == srunner) \ 56 | return (EXIT_FAILURE); \ 57 | TCase * tcase = tcase_create ("mr_conf save/load"); \ 58 | if (NULL == tcase) \ 59 | return (EXIT_FAILURE); \ 60 | tcase_set_timeout (tcase, 0); \ 61 | tcase_add_test (tcase, mr_conf_save_load); \ 62 | suite_add_tcase (suite, tcase); \ 63 | srunner_run_all (srunner, CK_ENV); \ 64 | number_failed = srunner_ntests_failed (srunner); \ 65 | srunner_free (srunner); \ 66 | return ((number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE); \ 67 | } 68 | -------------------------------------------------------------------------------- /tests/smoke_cinit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | SMOKE_METHOD (CINIT) 4 | -------------------------------------------------------------------------------- /tests/smoke_json.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | SMOKE_METHOD (JSON) 4 | -------------------------------------------------------------------------------- /tests/smoke_scm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | SMOKE_METHOD (SCM) 4 | -------------------------------------------------------------------------------- /tests/smoke_xdr.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | SMOKE_METHOD (XDR) 4 | -------------------------------------------------------------------------------- /tests/smoke_xml1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | SMOKE_METHOD (XML1) 4 | -------------------------------------------------------------------------------- /tests/smoke_xml2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | SMOKE_METHOD (XML2) 4 | -------------------------------------------------------------------------------- /tests/smoke_yaml.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | SMOKE_METHOD (YAML) 4 | -------------------------------------------------------------------------------- /tests/string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef char char_array_t[256]; 7 | TYPEDEF_STRUCT (struct_string_t, string_t x); 8 | TYPEDEF_STRUCT (struct_charp_t, (char *, x)); 9 | TYPEDEF_STRUCT (struct_char_array_t, (char, x, [256])); /* saved as an array of characters */ 10 | TYPEDEF_STRUCT (struct_ca_t, (char, x, [256], , .stype.mr_type = MR_TYPE_CHAR_ARRAY, .stype.is_array = false)); /* saved as a quoted string */ 11 | TYPEDEF_STRUCT (struct_ca_type_t, (char_array_t, x)); 12 | 13 | TYPEDEF_STRUCT (struct_ca_str_t, (char_array_t, x), string_t y); 14 | TYPEDEF_STRUCT (struct_str_ca_t, string_t y, (char_array_t, x)); 15 | TYPEDEF_STRUCT (struct_str_str_t, string_t x, string_t y); 16 | 17 | TYPEDEF_STRUCT (struct_ca_int_t, ATTRIBUTES (__attribute__ ((packed))), 18 | (char, x, [1], , .stype.mr_type = MR_TYPE_CHAR_ARRAY, .stype.is_array = false), 19 | int y); 20 | 21 | #define ASSERT_SAVE_LOAD_CHAR_POINTER(METHOD, ...) ({ \ 22 | ASSERT_SAVE_LOAD_TYPE (METHOD, string_t, __VA_ARGS__); \ 23 | ASSERT_SAVE_LOAD_TYPE (METHOD, char *, __VA_ARGS__); \ 24 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_string_t, __VA_ARGS__); \ 25 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_charp_t, __VA_ARGS__); \ 26 | }) 27 | 28 | #define ASSERT_SAVE_LOAD_STRING(METHOD, ...) ({ \ 29 | ASSERT_SAVE_LOAD_CHAR_POINTER (METHOD, __VA_ARGS__); \ 30 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_char_array_t, __VA_ARGS__); \ 31 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_ca_t, __VA_ARGS__); \ 32 | ASSERT_SAVE_LOAD_TYPE (METHOD, struct_ca_type_t, __VA_ARGS__); \ 33 | }) 34 | 35 | #define ASSERT_SAVE_LOAD_CA_INT(METHOD, VALUE, ...) ({ \ 36 | struct_ca_int_t x = { VALUE, '0' }; \ 37 | ASSERT_SAVE_LOAD (METHOD, struct_ca_int_t, &x, __VA_ARGS__); \ 38 | }) 39 | 40 | START_TEST (null_string) { ALL_METHODS (ASSERT_SAVE_LOAD_CHAR_POINTER, NULL); } END_TEST 41 | START_TEST (empty_string) { ALL_METHODS (ASSERT_SAVE_LOAD_STRING, ""); } END_TEST 42 | START_TEST (printable_string) { ALL_METHODS (ASSERT_SAVE_LOAD_STRING, "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176"); } END_TEST 43 | START_TEST (xml_special_string) { ALL_METHODS (ASSERT_SAVE_LOAD_STRING, "&<>;'\"\t\r\n"); } END_TEST 44 | 45 | static int warnings = 0; 46 | static void 47 | msg_handler (const char * file_name, const char * func_name, int line, mr_log_level_t log_level, mr_message_id_t message_id, va_list args) 48 | { 49 | ++warnings; 50 | } 51 | 52 | START_TEST (char_array_overflow) { 53 | mr_msg_handler_t save_msg_handler = mr_conf.msg_handler; 54 | mr_conf.msg_handler = msg_handler; 55 | ALL_METHODS (ASSERT_SAVE_LOAD_CA_INT, "0"); 56 | mr_conf.msg_handler = save_msg_handler; 57 | ck_assert_msg ((0 == warnings), "Unexpected warnings #%d", warnings); 58 | } END_TEST 59 | 60 | START_TEST (pointer_match_content_known) { 61 | struct_ca_str_t orig = { .x = "string_t" }; 62 | orig.y = orig.x; 63 | mr_ra_ptrdes_t ptrs = MR_SAVE (struct_ca_str_t, &orig); 64 | if (ptrs.ra != NULL) 65 | { 66 | bool string_is_a_reference = false; 67 | int i; 68 | for (i = ptrs.size / sizeof (ptrs.ra[0]) - 1; i > 0; --i) 69 | { 70 | if (ptrs.ra[i].fdp && 71 | (ptrs.ra[i].fdp->name.str != NULL) && 72 | (0 == strcmp (ptrs.ra[i].fdp->name.str, "y")) && 73 | (ptrs.ra[i].flags & (MR_IS_REFERENCE | MR_IS_CONTENT_REFERENCE))) 74 | string_is_a_reference = true; 75 | } 76 | MR_FREE (ptrs.ra); 77 | ck_assert_msg (string_is_a_reference, "string was not resolved a reference on char array"); 78 | } 79 | ALL_METHODS (ASSERT_SAVE_LOAD, struct_ca_str_t, &orig); 80 | } END_TEST 81 | 82 | START_TEST (pointer_match_content_unknown) { 83 | struct_str_ca_t orig = { .x = "string_t" }; 84 | orig.y = orig.x; 85 | mr_ra_ptrdes_t ptrs = MR_SAVE (struct_str_ca_t, &orig); 86 | if (ptrs.ra != NULL) 87 | { 88 | bool string_is_a_reference = false; 89 | int i; 90 | for (i = ptrs.size / sizeof (ptrs.ra[0]) - 1; i > 0; --i) 91 | { 92 | if (ptrs.ra[i].fdp && 93 | (ptrs.ra[i].fdp->name.str != NULL) && 94 | (0 == strcmp (ptrs.ra[i].fdp->name.str, "y")) && 95 | (ptrs.ra[i].flags & (MR_IS_REFERENCE | MR_IS_CONTENT_REFERENCE))) 96 | string_is_a_reference = true; 97 | } 98 | MR_FREE (ptrs.ra); 99 | ck_assert_msg (string_is_a_reference, "string was not resolved a reference on char array"); 100 | } 101 | ALL_METHODS (ASSERT_SAVE_LOAD, struct_str_ca_t, &orig); 102 | } END_TEST 103 | 104 | START_TEST (pointer_match_another_pointer) { 105 | struct_str_str_t orig = { .x = "string_t", }; 106 | mr_td_t * string_tdp = mr_get_td_by_name ("string_t"); 107 | orig.y = orig.x; 108 | mr_ra_ptrdes_t ptrs = MR_SAVE (struct_str_str_t, &orig); 109 | 110 | if (ptrs.ra != NULL) 111 | { 112 | int i, count = 0; 113 | for (i = ptrs.size / sizeof (ptrs.ra[0]) - 1; i > 0; --i) 114 | if ((ptrs.ra[i].fdp->stype.tdp == string_tdp) && (ptrs.ra[i].flags & (MR_IS_REFERENCE | MR_IS_CONTENT_REFERENCE))) 115 | ++count; 116 | 117 | MR_FREE (ptrs.ra); 118 | ck_assert_msg (1 == count, "pointer on existing string was not detected properly"); 119 | } 120 | ALL_METHODS (ASSERT_SAVE_LOAD, struct_str_str_t, &orig); 121 | } END_TEST 122 | 123 | MAIN_TEST_SUITE ((null_string, "NULL string"), 124 | (empty_string, "empty string"), 125 | (printable_string, "all printable characters string"), 126 | (xml_special_string, "xml special characters string"), 127 | (char_array_overflow, "inline char array overflow"), 128 | (pointer_match_content_known, "strings points on known char array"), 129 | (pointer_match_content_unknown, "strings points on unknown char array"), 130 | (pointer_match_another_pointer, "two strings points on the same content") 131 | ); 132 | -------------------------------------------------------------------------------- /tests/union_resolution_complexity.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | TYPEDEF_STRUCT (a_t, 10 | ANON_UNION (), 11 | ANON_UNION (), 12 | ANON_UNION (), 13 | ANON_UNION (), 14 | ANON_UNION (), 15 | ANON_UNION (), 16 | ANON_UNION (), 17 | ANON_UNION (), 18 | ANON_UNION (), 19 | ANON_UNION (), 20 | ANON_UNION (), 21 | ANON_UNION (), 22 | ANON_UNION (), 23 | ANON_UNION (), 24 | (uint8_t, x), 25 | END_ANON_UNION (), 26 | END_ANON_UNION (), 27 | END_ANON_UNION (), 28 | END_ANON_UNION (), 29 | END_ANON_UNION (), 30 | END_ANON_UNION (), 31 | END_ANON_UNION (), 32 | END_ANON_UNION (), 33 | END_ANON_UNION (), 34 | END_ANON_UNION (), 35 | END_ANON_UNION (), 36 | END_ANON_UNION (), 37 | END_ANON_UNION (), 38 | END_ANON_UNION (), 39 | ); 40 | 41 | static int 42 | measure_time_for_n_elements (int n) 43 | { 44 | a_t * array = MR_CALLOC (n, sizeof (*array)); 45 | ck_assert_msg (array != NULL, "Memory allocation failed"); 46 | 47 | mr_rarray_t rarray; 48 | rarray.data.ptr = array; 49 | rarray.mr_size = n * sizeof (*array); 50 | rarray.type = "a_t"; 51 | 52 | clock_t _time = clock (); 53 | mr_ra_ptrdes_t ptrs = MR_SAVE (mr_rarray_t, &rarray); 54 | _time = clock () - _time; 55 | 56 | if (ptrs.ra) 57 | MR_FREE (ptrs.ra); 58 | 59 | MR_FREE (array); 60 | return (_time); 61 | } 62 | 63 | START_TEST (mr_save_discriminated_union_complexity) { 64 | int i, size = 1 << 8; 65 | int base_time, double_time = measure_time_for_n_elements (size); 66 | do { 67 | size <<= 1; 68 | base_time = double_time; 69 | double_time = measure_time_for_n_elements (size); 70 | } while (double_time < CLOCKS_PER_SEC / 8); 71 | 72 | for (i = 0; i < 3; ++i) 73 | { 74 | int another_try = measure_time_for_n_elements (size); 75 | double_time = MR_MIN (double_time, another_try); 76 | } 77 | 78 | ck_assert_msg (double_time < (base_time * 5) / 2, "Union resolution is not in constant time (%d vs %d)", double_time, base_time); 79 | } END_TEST 80 | 81 | MAIN_TEST_SUITE ((mr_save_discriminated_union_complexity, "validate that complexity of saving discriminated unions is not dependent on collisions in hash table")); 82 | --------------------------------------------------------------------------------