diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100755
index 0000000..8764130
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,85 @@
+FROM debian:bullseye-slim as devroot
+
+LABEL MAINTAINER="Barre Kevin"
+LABEL VERSION="1.0"
+LABEL SRC=https://github.com/neudinger/ \
+ DESCRIPTION="PDIC Container"
+
+
+ARG USERNAME=pdi
+ARG USER_UID=1000
+ENV PATH /bin:/sbin:/usr/bin:$PATH
+ENV DEBIAN_FRONTEND=noninteractive
+
+ENV LOGGING_LEVEL=INFO
+ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 HOME=/home/${USERNAME}
+ENV PATH=/usr/sbin:/bin:/sbin:/usr/bin:${HOME}/.local/bin:/usr/local/bin
+ENV USER_NAME=$USERNAME
+ENV CONDA_DIR=/opt/conda
+ENV PATH=${CONDA_DIR}/bin:${PATH}
+
+RUN set -eux && \
+ apt update -y && apt install -y --no-install-recommends \
+ curl ca-certificates tar build-essential sudo git binutils-gold \
+ libtool libtool-bin zlib1g-dev libssl-dev \
+ libncursesw5 libpthread-stubs0-dev \
+ clang-format clang-tidy clang-tools clang clangd libc++-dev \
+ libc++1 libc++abi-dev libc++abi1 libclang-dev libclang1 liblldb-dev \
+ libllvm-ocaml-dev libomp-dev libomp5 lld lldb llvm-dev llvm-runtime llvm python-clang
+RUN update-alternatives --install "/usr/bin/ld" "ld" `which ld.gold` 10
+
+SHELL ["/bin/bash", "-c"]
+
+USER root
+
+WORKDIR $HOME
+
+RUN groupadd --gid $USER_UID $USERNAME; \
+ useradd -s /bin/bash --uid $USER_UID --gid $USER_UID -m $USERNAME
+
+RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
+RUN chmod 0440 /etc/sudoers.d/$USERNAME
+RUN apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
+
+WORKDIR ${HOME}
+
+ENV APP_HOME ${HOME}/app/
+RUN set -eux;\
+ mkdir -p ${APP_HOME} && \
+ chown -R ${USERNAME}:${USERNAME} ${HOME}
+
+SHELL ["/bin/bash", "-c"]
+
+WORKDIR $HOME
+# MiniConda
+
+RUN set -eux && \
+ curl --progress-bar -L \
+ https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh -o Miniforge3.sh && \
+ bash Miniforge3.sh -b -p ${CONDA_DIR} && \
+ rm Miniforge3.sh
+
+RUN set -eux && \
+ curl --progress-bar -L \
+ https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-pypy3-$(uname)-$(uname -m).sh -o Mambaforge.sh && \
+ bash Mambaforge.sh -b -u ${CONDA_DIR} && \
+ rm Mambaforge.sh
+
+COPY requirement.yml ${HOME}
+
+RUN set -eux; \
+ conda env create --name pdic-env -f requirement.yml && \
+ conda init bash && \
+ rm requirement.yml
+
+ENV PATH=$HOME/miniconda/envs/pdic-env/bin:${PATH}
+RUN echo "PATH=${PATH}" >> ~/.bashrc
+WORKDIR $APP_HOME
+SHELL ["/bin/bash", "-c"]
+RUN echo "conda activate pdic-env" >> ~/.bashrc
+COPY --chown=${USER_NAME}:${USER_NAME} entrypoint.sh ${HOME}
+RUN chown -R ${USER_NAME}:${USER_NAME} /home
+ENTRYPOINT ["/bin/bash", "/home/pdi/entrypoint.sh"]
+CMD ["bash"]
+# USER root
+USER $USERNAME
\ No newline at end of file
diff --git a/.devcontainer/conda-github-requirement.yml b/.devcontainer/conda-github-requirement.yml
new file mode 100644
index 0000000..a01586d
--- /dev/null
+++ b/.devcontainer/conda-github-requirement.yml
@@ -0,0 +1,11 @@
+channels:
+ - defaults
+ - conda-forge
+dependencies:
+ - python=3.9
+ - pip
+ - twine
+ - mkdocs-material
+ - ninja
+ - pip:
+ - "pdoc3"
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100755
index 0000000..4fce5fa
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,9 @@
+{
+ "name": "PDIC container dev",
+ "dockerFile": "Dockerfile",
+ "extensions": [
+ "ms-python.python",
+ "austin.code-gnu-global",
+ "ms-vscode.cmake-tools"
+ ]
+}
\ No newline at end of file
diff --git a/.devcontainer/dockross.dockerfile b/.devcontainer/dockross.dockerfile
new file mode 100644
index 0000000..a95722e
--- /dev/null
+++ b/.devcontainer/dockross.dockerfile
@@ -0,0 +1,14 @@
+# https://github.com/dockcross/dockcross
+
+FROM dockcross/base
+
+ENV DEFAULT_DOCKCROSS_IMAGE pdic_cross_build
+RUN set -eux && \
+ apt update -y && apt install -y --no-install-recommends \
+ curl ca-certificates tar build-essential sudo git binutils-gold \
+ libtool libtool-bin zlib1g-dev libssl-dev \
+ libncursesw5 libpthread-stubs0-dev \
+ clang-format clang-tidy clang-tools clang clangd libc++-dev \
+ libc++1 libc++abi-dev libc++abi1 libclang-dev libclang1 liblldb-dev \
+ libllvm-ocaml-dev libomp-dev libomp5 lld lldb llvm-dev llvm-runtime llvm python-clang
+RUN pip install pdoc3 twine pyaml
diff --git a/.devcontainer/entrypoint.sh b/.devcontainer/entrypoint.sh
new file mode 100755
index 0000000..f63f267
--- /dev/null
+++ b/.devcontainer/entrypoint.sh
@@ -0,0 +1,4 @@
+# !/bin/bash --login
+# activate conda environment and let the following process take over
+source ~/.bashrc
+exec "$@"
\ No newline at end of file
diff --git a/.devcontainer/requirement.yml b/.devcontainer/requirement.yml
new file mode 100644
index 0000000..377123e
--- /dev/null
+++ b/.devcontainer/requirement.yml
@@ -0,0 +1,14 @@
+channels:
+ - defaults
+ - conda-forge
+dependencies:
+ - python=3.9
+ - pip
+ - cmake=3.21.2
+ - scikit-build
+ - ninja
+ - twine
+ - pytest
+ - pyyaml
+ - pip:
+ - "pdoc3"
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..8f3bf3b
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,11 @@
+llvm-project-llvmorg-12.0.1/
+build/
+docs/_build
+tests/bin
+Testing/
+CMakeFiles/
+dist/
+html/
+.pytest_cache/
+_skbuild/
+.vscode
diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
new file mode 100644
index 0000000..ee25232
--- /dev/null
+++ b/.github/workflows/ci-cd.yml
@@ -0,0 +1,129 @@
+name: Build pdic
+on:
+ push:
+ tags:
+ - "*"
+jobs:
+ create_release:
+ if: contains(github.ref, 'v')
+ name: Create release
+ runs-on: ubuntu-latest
+ outputs:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ id: ${{ steps.create_release.outputs.id }}
+ steps:
+ - name: Create release
+ id: create_release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ release_name: Release ${{ github.ref }}
+ draft: false
+ prerelease: false
+ build:
+ name: Build ${{ matrix.os }}
+ needs: create_release
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: true
+ matrix:
+ os: [ubuntu-20.04] # , macOS-10.15, windows-2019
+ if: contains(github.ref, 'v')
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Get the version
+ id: get_version
+ run: |
+ echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
+ - name: Install system requirement
+ if: ${{ matrix.os == 'ubuntu-20.04' }}
+ run: |
+ sudo apt update && sudo apt install -y \
+ ca-certificates sudo git
+ id: checkout
+ - name: Conda activate
+ uses: conda-incubator/setup-miniconda@v2
+ with:
+ miniconda-version: "latest"
+ activate-environment: pdic-env
+ - name: Install conda dependencies
+ shell: bash -l {0}
+ id: installation
+ run: |
+ set -eux; conda env update --name pdic-env --file .devcontainer/conda-github-requirement.yml
+ - name: Deploy mkdocs
+ if: ${{ contains(github.ref, 'p') && matrix.os != 'windows-2019'}}
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ shell: bash -l {0}
+ run: |
+ mkdocs gh-deploy --force
+ - name: Login to DockerHub
+ uses: docker/login-action@v1
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ - name: Build Docker image
+ run: docker build . -f .devcontainer/Dockerfile -t pdic:latest
+ - name: Build in Docker image
+ id: builder
+ shell: bash -l {0}
+ run: |
+ version=${{ steps.get_version.outputs.VERSION }}
+ export version=${version//[!0-9.]/}
+ echo ::set-output name=PYVERSION::$(echo ${version})
+ sudo chmod -R a+w `pwd`
+ docker run -e version=${version} -v `pwd`:/home/pdi/app pdic python3 setup.py build
+ docker run -e version=${version} -v `pwd`:/home/pdi/app pdic python3 setup.py bdist_wheel --plat-name manylinux1_x86_64 -j `nproc`
+ docker run -e version=${version} -v `pwd`:/home/pdi/app pdic python3 setup.py bdist_wheel --plat-name manylinux2010_x86_64 -j `nproc`
+ docker run -e version=${version} -v `pwd`:/home/pdi/app pdic python3 setup.py build_ext --inplace -j `nproc`
+ docker run -v `pwd`:/home/pdi/app pdic cmake -S . -DBINARY:BOOL=ON -B build
+ docker run -v `pwd`:/home/pdi/app pdic cmake --build build -- -j `nproc`
+ docker run -v `pwd`:/home/pdi/app pdic cmake -S . -DTEST:BOOL=ON -B build
+ docker run -v `pwd`:/home/pdi/app pdic cmake --build build -- -j `nproc`
+ docker run -v `pwd`:/home/pdi/app pdic /bin/bash -c "pip install dist/pdic-${version}-cp39-cp39-manylinux1_x86_64.whl && pytest"
+ docker run -v `pwd`:/home/pdi/app pdic ctest --test-dir build
+ docker run -v `pwd`:/home/pdi/app pdic /bin/bash -c "pip install dist/pdic-${version}-cp39-cp39-manylinux1_x86_64.whl && pdoc3 pdic --pdf > dist/pdic-pdoc3-${version}.md && pdoc3 pdic --html -o dist/"
+ sudo chown -R $USER `pwd`
+ mv build/pdic.static dist/
+ mv ./docs_format/*.ttf .
+ - name: Build pandoc documentation
+ uses: docker://pandoc/latex
+ with:
+ args: >- # allows you to break string into multiple lines
+ --metadata=title:"PDIC: (IDL) Transpiler Source-to-source compiler C/C++ to YAML Description based on clang "
+ --variable=documentclass:"extarticle"
+ --variable=mainfont:"Roboto"
+ --variable=mainfontoptions:"Extension=.ttf, UprightFont=*-Regular, BoldFont=*-Bold, ItalicFont=*-Italic, BoldItalicFont=*-BoldItalic"
+ --variable=fontsize:"10pt"
+ --variable=geometry:"margin=1.5cm,a4paper"
+ --metadata=author:"BARRE kevin"
+ --from=markdown+abbreviations+tex_math_single_backslash
+ --pdf-engine=xelatex
+ --toc --toc-depth=4
+ --output=dist/pdic-pdoc3-${{ steps.builder.outputs.PYVERSION }}.pdf
+ dist/pdic-pdoc3-${{ steps.builder.outputs.PYVERSION }}.md
+ - name: Upload Releases Assets
+ id: upload-release-assets
+ uses: dwenegar/upload-release-assets@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ release_id: ${{ needs.create_release.outputs.id }}
+ assets_path: ./dist/
+ - name: Deploy to PyPI ${{ matrix.os }}
+ if: ${{ contains(github.ref, 'p') && matrix.os != 'windows-2019'}}
+ shell: bash -l {0}
+ env:
+ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
+ run: |
+ twine upload -u __token__ -p $TWINE_PASSWORD dist/*.whl
+ - name: Deploy to PyPI windows-2019
+ if: ${{ contains(github.ref, 'p') && matrix.os == 'windows-2019'}}
+ run: |
+ pip install twine
+ twine upload -u __token__ -p ${{ secrets.PYPI_PASSWORD }} dist/*.whl
diff --git a/.gitignore b/.gitignore
index 32c0064..49bd1a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,76 @@
-llvm-project-llvmorg-12.0.1/
-dockerfiles/
+#
+# File: .gitignore
+# Project: pdic
+# File Created: Thursday, 22nd July 2021 11:05:12 pm
+# Author: kbarre (kevin.barre@epitech.eu)
+# -----
+# Last Modified: Friday, 30th July 2021 6:04:17 pm
+# Modified By: kbarre (kevin.barre@epitech.eu>)
+# -----
+# Licenses: EUPL
+# -----
+# Copyright 2021 - 2021 neudinger
+#
+
+# Build directory
build/
+llvm-project-llvmorg-12.0.1/
+docs/_build
+tests/bin
+Testing/
+CMakeFiles/
+dist/
+html/
+.pytest_cache/
+_skbuild/
+
+# Python
+*.egg-info
+__pycache__
+.eggs
+*.pyc
+
+# VS Code
+.vscode
+
+# Prerequisites
*.yml
*.tar*
-documentation/
-!examples/expected/*.yml
\ No newline at end of file
+!_config.yml
+!mkdocs.yml
+!.github/workflows/ci-cd.yml
+!examples/expected/*.yml
+!.devcontainer/*.yml
+!requirement.yml
+__version__.py
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+CMakeCache*
+Makefile
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled python files
+core
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7015ff4..759337c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,51 +1,58 @@
-cmake_minimum_required(VERSION 3.20)
-project(pdi)
+cmake_minimum_required(VERSION 3.21)
set(TARGET "pdic")
+project(${TARGET} VERSION 0.1)
+include(FetchContent)
-find_package(LLVM REQUIRED CONFIG)
-find_package(Clang REQUIRED CONFIG)
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
-message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
-message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+option(DEBUG "DEBUG option" OFF) # OFF by default
+message(STATUS "DEBUG is " ${DEBUG})
+option(SKBUILD "SKBUILD option" OFF) # OFF by default
+message(STATUS "SKBUILD is " ${SKBUILD})
+option(BINARY "BINARY option" OFF) # OFF by default
+message(STATUS "BINARY is " ${BINARY})
+option(TEST "TEST option" OFF) # OFF by default
+message(STATUS "TEST is " ${TEST})
-# Use given `clang` toolchain.
-set(CMAKE_CXX_COMPILER "${LLVM_TOOLS_BINARY_DIR}/clang++")
-set(CMAKE_C_COMPILER "${LLVM_TOOLS_BINARY_DIR}/clang")
-list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
-# set(CMAKE_CXX_STANDARD 20)
-# set(CMAKE_CXX_STANDARD_REQUIRED ON)
-# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a")
+if(DEBUG)
+ add_compile_definitions(DEBUG=True)
+endif(DEBUG)
-# will remove `--` compilation command
-# and add compilation databases for clang on this project.
-# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCMAKE_EXPORT_COMPILE_COMMANDS")
+set(WORKDIR ${CMAKE_CURRENT_LIST_DIR}/src/pdic)
+message(STATUS "WORKDIR in: ${WORKDIR}")
-# Set compiler flags.
-include(HandleLLVMOptions)
-# Use LLVM and clang headers.
-include_directories(${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS})
-
-include_directories(${LLVM_INCLUDE_DIRS})
-add_definitions(${LLVM_DEFINITIONS})
-list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
-include(AddLLVM)
-include("./llvm-project-llvmorg-12.0.1/clang/cmake/modules/AddClang.cmake")
-
-file(GLOB src
- "src/*.hpp"
- "src/*.cpp"
+file(GLOB SRC
+ "${WORKDIR}/*.hpp"
+ "${WORKDIR}/*.cpp"
)
-add_clang_executable(${TARGET} ${src})
-
-target_link_libraries(${TARGET}
- PRIVATE
- clangAST
- clangBasic
- clangFrontend
- clangTooling
- clangASTMatchers
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/modules)
+
+
+if((BINARY OR TEST) OR SKBUILD)
+ include(Builder)
+else((BINARY OR TEST) OR SKBUILD)
+ message("
+ Please Use one at least one cmake flag \n\
+ But only one between\n\
+ - SKBUILD : python lib\n\
+ - BINARY : embedded binary\n\
+ - TEST : ctest\n\n\
+
+ cmake -S . \n\
+ -DSKBUILD:BOOL=OFF # or ON\n\
+ -DBINARY:BOOL=ON # or OFF\n\
+ -DTEST:BOOL=OFF # or ON\n\
+ -DDEBUG:BOOL=ON # or OFF\n\
+ -B build "
)
+endif((BINARY OR TEST) OR SKBUILD)
+
+set(ignoreMe "${SKBUILD}")
-# cmake .. ; make && ./pdic ../../PDI_test_parse.h --
\ No newline at end of file
+unset(DEBUG CACHE)
+unset(SKBUILD CACHE)
+unset(BINARY CACHE)
+unset(TEST CACHE)
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..46d8a57
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,190 @@
+EUROPEAN UNION PUBLIC LICENCE v. 1.2
+EUPL © the European Union 2007, 2016
+
+This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined below) which is provided under the
+terms of this Licence. Any use of the Work, other than as authorised under this Licence is prohibited (to the extent such
+use is covered by a right of the copyright holder of the Work).
+The Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following
+notice immediately following the copyright notice for the Work:
+ Licensed under the EUPL
+or has expressed by any other means his willingness to license under the EUPL.
+
+1.Definitions
+In this Licence, the following terms have the following meaning:
+— ‘The Licence’:this Licence.
+— ‘The Original Work’:the work or software distributed or communicated by the Licensor under this Licence, available
+as Source Code and also as Executable Code as the case may be.
+— ‘Derivative Works’:the works or software that could be created by the Licensee, based upon the Original Work or
+modifications thereof. This Licence does not define the extent of modification or dependence on the Original Work
+required in order to classify a work as a Derivative Work; this extent is determined by copyright law applicable in
+the country mentioned in Article 15.
+— ‘The Work’:the Original Work or its Derivative Works.
+— ‘The Source Code’:the human-readable form of the Work which is the most convenient for people to study and
+modify.
+— ‘The Executable Code’:any code which has generally been compiled and which is meant to be interpreted by
+a computer as a program.
+— ‘The Licensor’:the natural or legal person that distributes or communicates the Work under the Licence.
+— ‘Contributor(s)’:any natural or legal person who modifies the Work under the Licence, or otherwise contributes to
+the creation of a Derivative Work.
+— ‘The Licensee’ or ‘You’:any natural or legal person who makes any usage of the Work under the terms of the
+Licence.
+— ‘Distribution’ or ‘Communication’:any act of selling, giving, lending, renting, distributing, communicating,
+transmitting, or otherwise making available, online or offline, copies of the Work or providing access to its essential
+functionalities at the disposal of any other natural or legal person.
+
+2.Scope of the rights granted by the Licence
+The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, sublicensable licence to do the following, for
+the duration of copyright vested in the Original Work:
+— use the Work in any circumstance and for all usage,
+— reproduce the Work,
+— modify the Work, and make Derivative Works based upon the Work,
+— communicate to the public, including the right to make available or display the Work or copies thereof to the public
+and perform publicly, as the case may be, the Work,
+— distribute the Work or copies thereof,
+— lend and rent the Work or copies thereof,
+— sublicense rights in the Work or copies thereof.
+Those rights can be exercised on any media, supports and formats, whether now known or later invented, as far as the
+applicable law permits so.
+In the countries where moral rights apply, the Licensor waives his right to exercise his moral right to the extent allowed
+by law in order to make effective the licence of the economic rights here above listed.
+The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to any patents held by the Licensor, to the
+extent necessary to make use of the rights granted on the Work under this Licence.
+
+3.Communication of the Source Code
+The Licensor may provide the Work either in its Source Code form, or as Executable Code. If the Work is provided as
+Executable Code, the Licensor provides in addition a machine-readable copy of the Source Code of the Work along with
+each copy of the Work that the Licensor distributes or indicates, in a notice following the copyright notice attached to
+the Work, a repository where the Source Code is easily and freely accessible for as long as the Licensor continues to
+distribute or communicate the Work.
+
+4.Limitations on copyright
+Nothing in this Licence is intended to deprive the Licensee of the benefits from any exception or limitation to the
+exclusive rights of the rights owners in the Work, of the exhaustion of those rights or of other applicable limitations
+thereto.
+
+5.Obligations of the Licensee
+The grant of the rights mentioned above is subject to some restrictions and obligations imposed on the Licensee. Those
+obligations are the following:
+
+Attribution right: The Licensee shall keep intact all copyright, patent or trademarks notices and all notices that refer to
+the Licence and to the disclaimer of warranties. The Licensee must include a copy of such notices and a copy of the
+Licence with every copy of the Work he/she distributes or communicates. The Licensee must cause any Derivative Work
+to carry prominent notices stating that the Work has been modified and the date of modification.
+
+Copyleft clause: If the Licensee distributes or communicates copies of the Original Works or Derivative Works, this
+Distribution or Communication will be done under the terms of this Licence or of a later version of this Licence unless
+the Original Work is expressly distributed only under this version of the Licence — for example by communicating
+‘EUPL v. 1.2 only’. The Licensee (becoming Licensor) cannot offer or impose any additional terms or conditions on the
+Work or Derivative Work that alter or restrict the terms of the Licence.
+
+Compatibility clause: If the Licensee Distributes or Communicates Derivative Works or copies thereof based upon both
+the Work and another work licensed under a Compatible Licence, this Distribution or Communication can be done
+under the terms of this Compatible Licence. For the sake of this clause, ‘Compatible Licence’ refers to the licences listed
+in the appendix attached to this Licence. Should the Licensee's obligations under the Compatible Licence conflict with
+his/her obligations under this Licence, the obligations of the Compatible Licence shall prevail.
+
+Provision of Source Code: When distributing or communicating copies of the Work, the Licensee will provide
+a machine-readable copy of the Source Code or indicate a repository where this Source will be easily and freely available
+for as long as the Licensee continues to distribute or communicate the Work.
+Legal Protection: This Licence does not grant permission to use the trade names, trademarks, service marks, or names
+of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and
+reproducing the content of the copyright notice.
+
+6.Chain of Authorship
+The original Licensor warrants that the copyright in the Original Work granted hereunder is owned by him/her or
+licensed to him/her and that he/she has the power and authority to grant the Licence.
+Each Contributor warrants that the copyright in the modifications he/she brings to the Work are owned by him/her or
+licensed to him/her and that he/she has the power and authority to grant the Licence.
+Each time You accept the Licence, the original Licensor and subsequent Contributors grant You a licence to their contributions
+to the Work, under the terms of this Licence.
+
+7.Disclaimer of Warranty
+The Work is a work in progress, which is continuously improved by numerous Contributors. It is not a finished work
+and may therefore contain defects or ‘bugs’ inherent to this type of development.
+For the above reason, the Work is provided under the Licence on an ‘as is’ basis and without warranties of any kind
+concerning the Work, including without limitation merchantability, fitness for a particular purpose, absence of defects or
+errors, accuracy, non-infringement of intellectual property rights other than copyright as stated in Article 6 of this
+Licence.
+This disclaimer of warranty is an essential part of the Licence and a condition for the grant of any rights to the Work.
+
+8.Disclaimer of Liability
+Except in the cases of wilful misconduct or damages directly caused to natural persons, the Licensor will in no event be
+liable for any direct or indirect, material or moral, damages of any kind, arising out of the Licence or of the use of the
+Work, including without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, loss
+of data or any commercial damage, even if the Licensor has been advised of the possibility of such damage. However,
+the Licensor will be liable under statutory product liability laws as far such laws apply to the Work.
+
+9.Additional agreements
+While distributing the Work, You may choose to conclude an additional agreement, defining obligations or services
+consistent with this Licence. However, if accepting obligations, You may act only on your own behalf and on your sole
+responsibility, not on behalf of the original Licensor or any other Contributor, and only if You agree to indemnify,
+defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against such Contributor by
+the fact You have accepted any warranty or additional liability.
+
+10.Acceptance of the Licence
+The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ placed under the bottom of a window
+displaying the text of this Licence or by affirming consent in any other similar way, in accordance with the rules of
+applicable law. Clicking on that icon indicates your clear and irrevocable acceptance of this Licence and all of its terms
+and conditions.
+Similarly, you irrevocably accept this Licence and all of its terms and conditions by exercising any rights granted to You
+by Article 2 of this Licence, such as the use of the Work, the creation by You of a Derivative Work or the Distribution
+or Communication by You of the Work or copies thereof.
+
+11.Information to the public
+In case of any Distribution or Communication of the Work by means of electronic communication by You (for example,
+by offering to download the Work from a remote location) the distribution channel or media (for example, a website)
+must at least provide to the public the information requested by the applicable law regarding the Licensor, the Licence
+and the way it may be accessible, concluded, stored and reproduced by the Licensee.
+
+12.Termination of the Licence
+The Licence and the rights granted hereunder will terminate automatically upon any breach by the Licensee of the terms
+of the Licence.
+Such a termination will not terminate the licences of any person who has received the Work from the Licensee under
+the Licence, provided such persons remain in full compliance with the Licence.
+
+13.Miscellaneous
+Without prejudice of Article 9 above, the Licence represents the complete agreement between the Parties as to the
+Work.
+If any provision of the Licence is invalid or unenforceable under applicable law, this will not affect the validity or
+enforceability of the Licence as a whole. Such provision will be construed or reformed so as necessary to make it valid
+and enforceable.
+The European Commission may publish other linguistic versions or new versions of this Licence or updated versions of
+the Appendix, so far this is required and reasonable, without reducing the scope of the rights granted by the Licence.
+New versions of the Licence will be published with a unique version number.
+All linguistic versions of this Licence, approved by the European Commission, have identical value. Parties can take
+advantage of the linguistic version of their choice.
+
+14.Jurisdiction
+Without prejudice to specific agreement between parties,
+— any litigation resulting from the interpretation of this License, arising between the European Union institutions,
+bodies, offices or agencies, as a Licensor, and any Licensee, will be subject to the jurisdiction of the Court of Justice
+of the European Union, as laid down in article 272 of the Treaty on the Functioning of the European Union,
+— any litigation arising between other parties and resulting from the interpretation of this License, will be subject to
+the exclusive jurisdiction of the competent court where the Licensor resides or conducts its primary business.
+
+15.Applicable Law
+Without prejudice to specific agreement between parties,
+— this Licence shall be governed by the law of the European Union Member State where the Licensor has his seat,
+resides or has his registered office,
+— this licence shall be governed by Belgian law if the Licensor has no seat, residence or registered office inside
+a European Union Member State.
+
+
+ Appendix
+
+‘Compatible Licences’ according to Article 5 EUPL are:
+— GNU General Public License (GPL) v. 2, v. 3
+— GNU Affero General Public License (AGPL) v. 3
+— Open Software License (OSL) v. 2.1, v. 3.0
+— Eclipse Public License (EPL) v. 1.0
+— CeCILL v. 2.0, v. 2.1
+— Mozilla Public Licence (MPL) v. 2
+— GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
+— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for works other than software
+— European Union Public Licence (EUPL) v. 1.1, v. 1.2
+— Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+).
+
+The European Commission may update this Appendix to later versions of the above licences without producing
+a new version of the EUPL, as long as they provide the rights granted in Article 2 of this Licence and protect the
+covered Source Code from exclusive appropriation.
+All other changes or additions to this Appendix require the production of a new EUPL version.
diff --git a/README.md b/README.md
index bdf07ed..ff49bad 100644
--- a/README.md
+++ b/README.md
@@ -1,115 +1,68 @@
-# PDIC
+# PDIC [![Open Source Love svg1](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/)
PDIC: [(IDL)](https://en.wikipedia.org/wiki/Interface_description_language) Transpiler Source-to-source compiler C/C++ to YAML Portable Data Interface Description
-## Abstract
+Project related to [PDI](https://gitlab.maisondelasimulation.fr/pdidev/pdi)
+[![Linux](https://svgshare.com/i/Zhy.svg)](https://svgshare.com/i/Zhy.svg)
-Pronounce: PDI SEE
+[![GitHub license](https://img.shields.io/badge/license-EUPL-blue.svg)](https://raw.githubusercontent.com/herotc/hero-rotation/master/LICENSE) [![Build Github Status](https://github.com/neudinger/PDIC/workflows/Build%20pdic/badge.svg)](https://github.com/neudinger/PDIC/actions)
-[Why clang ?](https://clang.llvm.org/index.html)
+[![PyPI version](https://badge.fury.io/py/pdic.svg)](https://badge.fury.io/py/pdic)
+[![PyPI implementation](https://img.shields.io/pypi/implementation/pdic.svg)](https://pypi.python.org/pypi/pdic/)
-- Fast compiles and low memory use
-- Expressive diagnostics (examples)
-- GCC compatibility
-- Modular library based architecture
-- Support diverse clients (refactoring, static analysis, code generation, etc.)
-- A real-world, production quality compiler
-- A simple and hackable code base
-- A single unified parser for C, Objective C, C++, and Objective C++
-- Conformance with C/C++/ObjC and their variants
+[![Doc](https://readthedocs.org/projects/pip/badge/?version=latest)](https://neudinger.github.io/PDIC/)
+[![made-with-Markdown](https://img.shields.io/badge/Made%20with-Markdown-1f425f.svg)](http://commonmark.org)
-This project can see [PDI Portable Data Interface](https://gitlab.maisondelasimulation.fr/pdidev/pdi) representation in c/c++
+[![GitHub release](https://img.shields.io/github/release/neudinger/PDIC.svg)](https://GitHub.com/neudinger/PDIC/releases/) [![Docker](https://badgen.net/badge/icon/docker?icon=docker&label)](https://https://docker.com/)
-## Descriptions
+From C/C++ to Yaml Description
-[![GitHub license](https://img.shields.io/badge/license-EUPL-blue.svg)](https://raw.githubusercontent.com/herotc/hero-rotation/master/LICENSE)
+|Simple binary|Python library|
+|:-:|:-:|
+|static binary|Python 3|
+|`./pdic file.c`|`import pdic; result:str = pdic.files_to_pdi()`|
-## Usage
-
-```sh
-./pdic ../PDI_test_parse.h --
-```
-
-`PDI_test_parse.yml` will be created
-
-## Installation
-
-Dependencies:
+## Instalation
-- cmake
-- ninja
-- make
-- all clang and llvm tools
-- boost
-
-### Simple
+Binary
```sh
-wget https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-12.0.1.tar.gz
-tar xvf llvmorg-12.0.1.tar.gz
-mkdir build && cd build
-cmake ..
-make
+cmake -S . -DBINARY:BOOL=ON -B build && cmake --build build -- -j `nproc`
```
-### Complete
-
-Follow: [LibTooling and LibASTMatchers](https://clang.llvm.org/docs/LibASTMatchersTutorial.html) installation tutorial if you want to contribute.
-
-Use `gold` or `lld` because `ld` use too much ram
+Google Test
```sh
-wget https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-12.0.1.tar.gz
-tar xvf llvmorg-12.0.1.tar.gz
-cd llvm-project-llvmorg-12.0.1
-mkdir build && cd build
-cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_LINKER=gold
-ninja
-# ninja check # Test LLVM only.
-# ninja clang-test # Test Clang only.
-ninja install
-cd ../..
-mkdir build && cd build
-cmake ..
-make
+cmake -S . -DTEST:BOOL=ON -B build && cmake --build build -- -j `nproc`
+cd build && ctest
```
-## Examples
-
-Files can be:
-
-- file.c
-- file.h
-- file.hh / file.hpp
-- file.cc / file.cpp
-
-`--` is for [Compilation databases for Clang-based tools](https://eli.thegreenplace.net/2014/05/21/compilation-databases-for-clang-based-tools)
-> Note that anything before the double dash “--” is an input to your LibTooling program, argv in main(), while anything after the double dash is an input to Clang itself (you won’t concern yourself with those). (source `LibTooling Example`)
+Python
```sh
-./pdic ../examples/level_1.c --
+python setup.py build -G "Unix Makefiles"
+python3 setup.py bdist_wheel -G "Unix Makefiles" -j `nproc`
+python setup.py build_ext -G "Unix Makefiles" --inplace -j `nproc`
+pytest
```
-pdic extract all information from [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) and write PDI representation.
+## Usage
-```c
+```c++
#pragma pdi on
-int global_int;
-char global_char;
-void *global_pointer;
-float **global_float_pointer_of_pointer;
-int array[24];
+typedef struct Var8
+{
+#pragma pdi type : int64
+ int my_int;
+ char char_tab[20];
+ char my_char;
+} var;
-// pointer to array of int of size 42
-#pragma pdi type:int32; size:[42]
-int **pointer_of_array;
+#pragma pdi size:[42]
+int **array_of_pointer_of_array[21];
-double *array_of_pointers[21];
-
-#pragma pdi type:uint64
-#pragma pdi size:[10][10][10]
-unsigned ****my_cube;
+var my_var;
#pragma pdi off
```
@@ -117,53 +70,80 @@ unsigned ****my_cube;
Will be see and describe as follow
```yml
+structs:
+ Var8:
+ type: record
+ name: Var8
+ alias: [var]
+ fieldsize: 3
+ buffersize: 28
+ packed: false
+ members:
+ char_tab: { type: array, subtype: char, size: 20 }
+ my_char:
+ offset: 24
+ type: char
+ my_int:
+ type: int64
data:
- array: { type: array, subtype: int, size: 24 }
- array_of_pointers: { type: array, subtype: { type: pointer, subtype: double }, size: 21 }
- global_char:
- type: char
- global_float_pointer_of_pointer: { type: pointer, subtype: { type: pointer, subtype: float } }
- global_int:
- type: int
- global_pointer: { type: pointer, subtype: void }
- my_cube: { type: pointer, subtype: { type: array, subtype: uint64, size: [10, 10, 10] } }
- pointer_of_array: { type: pointer, subtype: { type: array, subtype: int32, size: 42 } }
+ array_of_pointer_of_array: { type: array, subtype: { type: pointer, subtype: { type: array, subtype: int, size: 42 } }, size: 21 }
+ my_var:
+ type: record
+ name: Var8
+ alias: [var]
+ fieldsize: 3
+ buffersize: 28
+ packed: false
+ members:
+ char_tab: { type: array, subtype: char, size: 20 }
+ my_char:
+ offset: 24
+ type: char
+ my_int:
+ type: int64
```
-You can find differents examples -> [Here](./examples/)
-
-## Usefull links
-
-[Clang API](http://man.hubwiz.com/manual/Clang)
-
-### Clang / LLVM
-
-#### Official documentation
-
-- [Clang Plugins doc](https://clang.llvm.org/docs/ClangPlugins.html)
-- [Clang Driver Design](https://clang.llvm.org/docs/DriverInternals.html)
-- [RecursiveASTVisitor Tutorial](https://clang.llvm.org/docs/RAVFrontendAction.html)
-
-#### Other documentation
-
-- [Basics of AST manipulation](https://freecompilercamp.org/clang-AST-basics/)
-- [Comment parser](https://danielbeard.io/2016/04/19/clang-frontend-action-part-1.html)
-- [Hacking on Clang is surprisingly easy](https://mort.coffee/home/clang-compiler-hacking/)
-- [understanding the clang ast](https://jonasdevlieghere.com/understanding-the-clang-ast/)
-- [Clang Tutorial: The AST Matcher](https://xinhuang.github.io/posts/2015-02-08-clang-tutorial-the-ast-matcher.html)
-- [Clang Tutorial: Finding Declarations](https://xinhuang.github.io/posts/2014-10-19-clang-tutorial-finding-declarations.html)
-
-#### Clang Tutorial Part: LibTooling Example
-
-1. [Part I](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-i-introduction/)
-2. [Part II](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/)
-3. [Part III](https://kevinaboos.wordpress.com/2013/07/29/clang-tutorial-part-iii-plugin-example/)
-
-#### Pragma
-
-- [Pragma token kind identifier](https://repo.hca.bsc.es/gitlab/rferrer/llvm-epi-0.8/-/commit/ea4f7c776194c96f8ece1456bc22102c6cbc9a33)
-- [Ex custom pragma 'TritonAssert'](https://github.com/quarkslab/clang/commit/0163f52f70e4781ce99710575bb66943125357b2)
-
-### Padding and packing in c/c++
+Python Usage
+
+```python
+import os
+import pathlib
+import yaml
+import pdic
+
+here = pathlib.Path(__file__).parent.resolve()
+# pip show -f pdic
+if __name__ == "__main__":
+ pdi_yml_description: str = pdic.files_to_pdi([os.path.join(here, "level_1.c"),
+ os.path.join(here, "level_2.c")])
+ print(pdi_yml_description)
+ print(yaml.dump(yaml.load(pdi_yml_description)))
+```
--
+## Index
+
+1. [Abstract](/docs/1.0-Abstract.md)
+2. [Usage](/docs/2.0-Requirement.md)
+ 1. [Binary](/docs/2.1-Binary.md)
+ 2. [Python](/docs/2.2-Python.md)
+3. [Developpement](/docs/3.0-Developpement.md)
+ - Code
+ - Documentation
+ - Test
+ - Deploy
+4. [Links](/docs/4.0-Links)
+ - [Autre Documentation](/docs/5.1-Documentations.md)
+ - Biblio
+ - Code example
+5. [Extra](/docs/5.0-Extra.md)
+ - Clang LLVM
+ - Mind Map
+ - Graph
+ - UML
+6. Contact / Credits
+
+Credits
+
+Barre Kevin [neudinger](https://github.com/) (Software Scientist)
+
+CEA pdi team
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..cc35c1d
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-modernist
\ No newline at end of file
diff --git a/dockcross-Makefile b/dockcross-Makefile
new file mode 100644
index 0000000..cc7d2d6
--- /dev/null
+++ b/dockcross-Makefile
@@ -0,0 +1,256 @@
+
+#
+# Parameters
+#
+
+# Name of the docker executable
+DOCKER = docker
+
+# Docker organization to pull the images from
+ORG = dockcross
+
+# Directory where to generate the dockcross script for each images (e.g bin/dockcross-manylinux2014-x64)
+BIN = ./bin
+
+# These images are built using the "build implicit rule"
+STANDARD_IMAGES = android-arm android-arm64 android-x86 android-x86_64 \
+ linux-x86 linux-x64 linux-x64-clang linux-arm64 linux-arm64-musl linux-arm64-full \
+ linux-armv5 linux-armv5-musl linux-m68k-uclibc linux-s390x linux-x64-tinycc \
+ linux-armv6 linux-armv6-lts linux-armv6-musl \
+ linux-armv7l-musl linux-armv7 linux-armv7a linux-x86_64-full \
+ linux-mips linux-ppc64le linux-riscv64 linux-riscv32 linux-xtensa-uclibc \
+ windows-static-x86 windows-static-x64 windows-static-x64-posix windows-armv7 \
+ windows-shared-x86 windows-shared-x64 windows-shared-x64-posix windows-arm64
+
+# Generated Dockerfiles.
+GEN_IMAGES = android-arm android-arm64 \
+ linux-x86 linux-x64 linux-x64-clang linux-arm64 linux-arm64-musl linux-arm64-full \
+ manylinux2014-x64 manylinux2014-x86 \
+ manylinux2014-aarch64 \
+ web-wasm linux-mips windows-arm64 windows-armv7 \
+ windows-static-x86 windows-static-x64 windows-static-x64-posix \
+ windows-shared-x86 windows-shared-x64 windows-shared-x64-posix \
+ linux-armv7 linux-armv7a linux-armv7l-musl linux-x86_64-full \
+ linux-armv6 linux-armv6-lts linux-armv6-musl \
+ linux-armv5 linux-armv5-musl linux-ppc64le linux-s390x \
+ linux-riscv64 linux-riscv32 linux-m68k-uclibc linux-x64-tinycc linux-xtensa-uclibc
+
+GEN_IMAGE_DOCKERFILES = $(addsuffix /Dockerfile,$(GEN_IMAGES))
+
+# These images are expected to have explicit rules for *both* build and testing
+NON_STANDARD_IMAGES = manylinux2014-x64 manylinux2014-x86 \
+ manylinux2014-aarch64 web-wasm
+
+# Docker composite files
+DOCKER_COMPOSITE_SOURCES = common.docker common.debian common.manylinux common.buildroot \
+ common.crosstool common.windows common-manylinux.crosstool common.dockcross common.label-and-env
+DOCKER_COMPOSITE_FOLDER_PATH = common/
+DOCKER_COMPOSITE_PATH = $(addprefix $(DOCKER_COMPOSITE_FOLDER_PATH),$(DOCKER_COMPOSITE_SOURCES))
+
+# This list all available images
+IMAGES = $(STANDARD_IMAGES) $(NON_STANDARD_IMAGES)
+
+# Optional arguments for test runner (test/run.py) associated with "testing implicit rule"
+linux-x64-tinycc.test_ARGS = --languages C
+windows-static-x86.test_ARGS = --exe-suffix ".exe"
+windows-static-x64.test_ARGS = --exe-suffix ".exe"
+windows-static-x64-posix.test_ARGS = --exe-suffix ".exe"
+windows-shared-x86.test_ARGS = --exe-suffix ".exe"
+windows-shared-x64.test_ARGS = --exe-suffix ".exe"
+windows-shared-x64-posix.test_ARGS = --exe-suffix ".exe"
+
+# On CircleCI, do not attempt to delete container
+# See https://circleci.com/docs/docker-btrfs-error/
+RM = --rm
+ifeq ("$(CIRCLECI)", "true")
+ RM =
+endif
+
+# Tag images with date and Git short hash in addition to revision
+TAG := $(shell date '+%Y%m%d')-$(shell git rev-parse --short HEAD)
+
+# shellcheck executable
+SHELLCHECK := shellcheck
+
+# Defines the level of verification (error, warning, info...)
+SHELLCHECK_SEVERITY_LEVEL := error
+
+#
+# images: This target builds all IMAGES (because it is the first one, it is built by default)
+#
+images: base $(IMAGES)
+
+#
+# test: This target ensures all IMAGES are built and run the associated tests
+#
+test: base.test $(addsuffix .test,$(IMAGES))
+
+#
+# Generic Targets (can specialize later).
+#
+
+$(GEN_IMAGE_DOCKERFILES) Dockerfile: %Dockerfile: %Dockerfile.in $(DOCKER_COMPOSITE_PATH)
+ sed \
+ -e '/common.docker/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.docker' \
+ -e '/common.debian/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.debian' \
+ -e '/common.manylinux/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.manylinux' \
+ -e '/common.crosstool/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.crosstool' \
+ -e '/common.buildroot/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.buildroot' \
+ -e '/common-manylinux.crosstool/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common-manylinux.crosstool' \
+ -e '/common.windows/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.windows' \
+ -e '/common.dockcross/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.dockcross' \
+ -e '/common.label-and-env/ r $(DOCKER_COMPOSITE_FOLDER_PATH)common.label-and-env' \
+ $< > $@
+
+#
+# web-wasm
+#
+web-wasm: web-wasm/Dockerfile
+ mkdir -p $@/imagefiles && cp -r imagefiles $@/
+ cp -r test web-wasm/
+ $(DOCKER) build -t $(ORG)/web-wasm:latest \
+ -t $(ORG)/web-wasm:$(TAG) \
+ --build-arg IMAGE=$(ORG)/web-wasm \
+ --build-arg VCS_REF=`git rev-parse --short HEAD` \
+ --build-arg VCS_URL=`git config --get remote.origin.url` \
+ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
+ web-wasm
+ rm -rf web-wasm/test
+ rm -rf $@/imagefiles
+
+web-wasm.test: web-wasm
+ cp -r test web-wasm/
+ $(DOCKER) run $(RM) $(ORG)/web-wasm > $(BIN)/dockcross-web-wasm && chmod +x $(BIN)/dockcross-web-wasm
+ $(BIN)/dockcross-web-wasm python test/run.py --exe-suffix ".js"
+ rm -rf web-wasm/test
+
+#
+# manylinux2014-aarch64
+#
+manylinux2014-aarch64: manylinux2014-aarch64/Dockerfile
+ @# Register qemu
+ docker run --rm --privileged hypriot/qemu-register
+ @# Get libstdc++ from quay.io/pypa/manylinux2014_aarch64 container
+ docker run -v `pwd`:/host --rm -e LIB_PATH=/host/$@/xc_script/ quay.io/pypa/manylinux2014_aarch64 bash -c "PASS=1 /host/$@/xc_script/docker_setup_scrpits/copy_libstd.sh"
+ mkdir -p $@/imagefiles && cp -r imagefiles $@/
+ $(DOCKER) build -t $(ORG)/manylinux2014-aarch64:latest \
+ -t $(ORG)/manylinux2014-aarch64:$(TAG) \
+ --build-arg IMAGE=$(ORG)/manylinux2014-aarch64 \
+ --build-arg VCS_REF=`git rev-parse --short HEAD` \
+ --build-arg VCS_URL=`git config --get remote.origin.url` \
+ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
+ -f manylinux2014-aarch64/Dockerfile .
+ rm -rf $@/imagefiles
+ @# libstdc++ is coppied into image, now remove it
+ docker run -v `pwd`:/host --rm quay.io/pypa/manylinux2014_aarch64 bash -c "rm -rf /host/$@/xc_script/usr"
+
+manylinux2014-aarch64.test: manylinux2014-aarch64
+ $(DOCKER) run $(RM) $(ORG)/manylinux2014-aarch64 > $(BIN)/dockcross-manylinux2014-aarch64 \
+ && chmod +x $(BIN)/dockcross-manylinux2014-aarch64
+ $(BIN)/dockcross-manylinux2014-aarch64 /opt/python/cp38-cp38/bin/python test/run.py
+
+#
+# manylinux2014-x64
+#
+manylinux2014-x64: manylinux2014-x64/Dockerfile
+ mkdir -p $@/imagefiles && cp -r imagefiles $@/
+ $(DOCKER) build -t $(ORG)/manylinux2014-x64:latest \
+ -t $(ORG)/manylinux2014-x64:$(TAG) \
+ --build-arg IMAGE=$(ORG)/manylinux2014-x64 \
+ --build-arg VCS_REF=`git rev-parse --short HEAD` \
+ --build-arg VCS_URL=`git config --get remote.origin.url` \
+ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
+ -f manylinux2014-x64/Dockerfile .
+ rm -rf $@/imagefiles
+
+manylinux2014-x64.test: manylinux2014-x64
+ $(DOCKER) run $(RM) $(ORG)/manylinux2014-x64 > $(BIN)/dockcross-manylinux2014-x64 \
+ && chmod +x $(BIN)/dockcross-manylinux2014-x64
+ $(BIN)/dockcross-manylinux2014-x64 /opt/python/cp38-cp38/bin/python test/run.py
+
+#
+# manylinux2014-x86
+#
+manylinux2014-x86: manylinux2014-x86/Dockerfile
+ mkdir -p $@/imagefiles && cp -r imagefiles $@/
+ $(DOCKER) build -t $(ORG)/manylinux2014-x86:latest \
+ -t $(ORG)/manylinux2014-x86:$(TAG) \
+ --build-arg IMAGE=$(ORG)/manylinux2014-x86 \
+ --build-arg VCS_REF=`git rev-parse --short HEAD` \
+ --build-arg VCS_URL=`git config --get remote.origin.url` \
+ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
+ -f manylinux2014-x86/Dockerfile .
+ rm -rf $@/imagefiles
+
+manylinux2014-x86.test: manylinux2014-x86
+ $(DOCKER) run $(RM) $(ORG)/manylinux2014-x86 > $(BIN)/dockcross-manylinux2014-x86 \
+ && chmod +x $(BIN)/dockcross-manylinux2014-x86
+ $(BIN)/dockcross-manylinux2014-x86 /opt/python/cp38-cp38/bin/python test/run.py
+
+base: Dockerfile imagefiles/
+ $(DOCKER) build -t $(ORG)/base:latest \
+ -t $(ORG)/base:$(TAG) \
+ --build-arg IMAGE=$(ORG)/base \
+ --build-arg VCS_URL=`git config --get remote.origin.url` \
+ .
+
+base.test: base
+ $(DOCKER) run $(RM) $(ORG)/base > $(BIN)/dockcross-base && chmod +x $(BIN)/dockcross-base
+
+# display
+#
+display_images:
+ for image in $(IMAGES); do echo $$image; done
+
+$(VERBOSE).SILENT: display_images
+
+#
+# build implicit rule
+#
+
+$(STANDARD_IMAGES): %: %/Dockerfile base
+ mkdir -p $@/imagefiles && cp -r imagefiles $@/
+ $(DOCKER) build -t $(ORG)/$@:latest \
+ -t $(ORG)/$@:$(TAG) \
+ --build-arg IMAGE=$(ORG)/$@ \
+ --build-arg VCS_REF=`git rev-parse --short HEAD` \
+ --build-arg VCS_URL=`git config --get remote.origin.url` \
+ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
+ $@
+ rm -rf $@/imagefiles
+
+clean:
+ for d in $(IMAGES) ; do rm -rf $$d/imagefiles ; done
+ for d in $(IMAGES) ; do rm -rf $(BIN)/dockcross-$$d ; done
+ for d in $(GEN_IMAGE_DOCKERFILES) ; do rm -f $$d ; done
+ rm -f Dockerfile
+
+purge: clean
+# Remove all untagged images
+ $(DOCKER) container ls -aq | xargs -r $(DOCKER) container rm -f
+# Remove all images with organization (ex dockcross/*)
+ $(DOCKER) images --filter=reference='$(ORG)/*' --format='{{.Repository}}:{{.Tag}}' | xargs -r $(DOCKER) rmi -f
+
+# Check bash syntax
+bash-check:
+ find . -type f \( -name "*.sh" -o -name "*.bash" \) -print0 | xargs -0 -P"$(shell nproc)" -I{} \
+ $(SHELLCHECK) --check-sourced --color=auto --format=gcc --severity=warning --shell=bash --enable=all "{}"
+
+#
+# testing implicit rule
+#
+.SECONDEXPANSION:
+$(addsuffix .test,$(STANDARD_IMAGES)): $$(basename $$@)
+ $(DOCKER) run $(RM) $(ORG)/$(basename $@) > $(BIN)/dockcross-$(basename $@) \
+ && chmod +x $(BIN)/dockcross-$(basename $@)
+ $(BIN)/dockcross-$(basename $@) python3 test/run.py $($@_ARGS)
+
+#
+# testing prerequisites implicit rule
+#
+test.prerequisites:
+ mkdir -p $(BIN)
+
+$(addsuffix .test,base $(IMAGES)): test.prerequisites
+
+.PHONY: base images $(IMAGES) test %.test clean purge bash-check display_images
diff --git a/docs/1.0-Abstract.md b/docs/1.0-Abstract.md
new file mode 100644
index 0000000..108e387
--- /dev/null
+++ b/docs/1.0-Abstract.md
@@ -0,0 +1,19 @@
+# Abstract
+
+Pronounce: PD I SEE
+
+Can you see the portable data iterface in this program ?
+
+[Why clang ?](https://clang.llvm.org/index.html)
+
+- Fast compiles and low memory use
+- Expressive diagnostics (examples)
+- GCC compatibility
+- Modular library based architecture
+- Support diverse clients (refactoring, static analysis, code generation, etc.)
+- A real-world, production quality compiler
+- A simple and hackable code base
+- A single unified parser for C, Objective C, C++, and Objective C++
+- Conformance with C/C++/ObjC and their variants
+
+This project can see [PDI Portable Data Interface](https://gitlab.maisondelasimulation.fr/pdidev/pdi) representation in c/c++.
diff --git a/docs/2.0-Requirement.md b/docs/2.0-Requirement.md
new file mode 100644
index 0000000..d5259e4
--- /dev/null
+++ b/docs/2.0-Requirement.md
@@ -0,0 +1,15 @@
+# Usages
+
+## Feature
+
+|Work on :|C files|C++ files|
+|:-:|:-:|:-:|
+|Header|`.h`|`.hh` `.hxx` `.hpp`|
+|Code|`.c`|`.cc` `.cxx` `.cpp`|
+
+## Installation
+
+Dependencies:
+
+- cmake
+- make
diff --git a/docs/2.1-Binary.md b/docs/2.1-Binary.md
new file mode 100644
index 0000000..ef9cbd6
--- /dev/null
+++ b/docs/2.1-Binary.md
@@ -0,0 +1,37 @@
+# Binary
+
+The Binary is static:
+
+- LLVM embeded
+- Clang embeded
+- Libc embeded
+
+(build on ubuntu)
+
+Binary
+
+```sh
+cmake -S . -DBINARY:BOOL=ON -B build && cmake --build build -- -j `nproc`
+```
+
+Google Test
+
+```sh
+cmake -S . -DTEST:BOOL=ON -B build && cmake --build build -- -j `nproc`
+cd build && ctest
+```
+
+```sh
+./pdic ../PDI_test_parse.h --
+./pdic ../PDI_test_parse.h --stdout on -- # on/off
+./pdic ../PDI_test_parse.h ../level_1.c --outputfilename out.yml --
+```
+
+`--` is for [Compilation databases for Clang-based tools](https://eli.thegreenplace.net/2014/05/21/compilation-databases-for-clang-based-tools)
+> Note that anything before the double dash “--” is an input to your LibTooling program, argv in main(), while anything after the double dash is an input to Clang itself (you won’t concern yourself with those). (source `LibTooling Example`)
+
+```sh
+./pdic ../examples/level_1.c --
+```
+
+pdic extract all information from [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) and write PDI representation.
diff --git a/docs/2.2-Python.md b/docs/2.2-Python.md
new file mode 100644
index 0000000..7b9409e
--- /dev/null
+++ b/docs/2.2-Python.md
@@ -0,0 +1,48 @@
+# Python Api
+
+Requirement:
+
+All dev requirements ([DevRequirement](/docs/2.0-Usages.md#Installation)) and:
+
+- libncursesw5
+- Clang / LLVM (all dev tools)
+ - libomp5
+ - libc++-dev
+ - libclang-dev
+ - ...
+
+Installation example (ubuntu)
+
+Source:
+
+```sh
+sudo apt update
+sudo apt install libncursesw5 libpthread-stubs0-dev
+sudo apt install clang-format clang-tidy clang-tools clang clangd libc++-dev libc++1 libc++abi-dev libc++abi1 libclang-dev libclang1 liblldb-dev libllvm-ocaml-dev libomp-dev libomp5 lld lldb llvm-dev llvm-runtime llvm python-clang
+```
+
+OR
+
+```sh
+sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
+# libclang-13-dev
+```
+
+> WARNING It may fail or somme dependency are not include (during pdic build or runtime) . Prefer the first command instead.
+
+## Python Test
+
+```sh
+python3 setup.py build -G "Unix Makefiles"
+python3 setup.py bdist_wheel -G "Unix Makefiles" -j `nproc`
+python3 setup.py build_ext -G "Unix Makefiles" --inplace -j `nproc`
+pytest
+```
+
+### pydoc
+
+```sh
+pdoc3 pdic --http 0.0.0.0:8888
+# Or
+pdoc3 pdic --html
+```
diff --git a/docs/3.0-Developpement.md b/docs/3.0-Developpement.md
new file mode 100644
index 0000000..042faab
--- /dev/null
+++ b/docs/3.0-Developpement.md
@@ -0,0 +1,20 @@
+# Developpement
+
+Herre i present how to compile build and develop features.
+
+## Requirement
+
+- lib pthread (-lpthread)
+- lib math (-lm)
+- lib dynamic loader (-ldl)
+- zlib (-lz)
+
+```sh
+cmake -S . -B build
+cmake --build build -- -j `nproc`
+cd build && ctest
+```
+
+## Examples
+
+You can find differents examples -> [Here](./examples/)
diff --git a/docs/4.0-Links.md b/docs/4.0-Links.md
new file mode 100644
index 0000000..8453574
--- /dev/null
+++ b/docs/4.0-Links.md
@@ -0,0 +1,71 @@
+# Usefull links
+
+[Clang API](http://man.hubwiz.com/manual/Clang)
+
+## Clang / LLVM
+
+### Official documentation
+
+- [Clang Plugins doc](https://clang.llvm.org/docs/ClangPlugins.html)
+- [Clang Driver Design](https://clang.llvm.org/docs/DriverInternals.html)
+- [RecursiveASTVisitor Tutorial](https://clang.llvm.org/docs/RAVFrontendAction.html)
+
+### Other documentation
+
+- [Basics of AST manipulation](https://freecompilercamp.org/clang-AST-basics/)
+- [Comment parser](https://danielbeard.io/2016/04/19/clang-frontend-action-part-1.html)
+- [Hacking on Clang is surprisingly easy](https://mort.coffee/home/clang-compiler-hacking/)
+- [understanding the clang ast](https://jonasdevlieghere.com/understanding-the-clang-ast/)
+- [Clang Tutorial: The AST Matcher](https://xinhuang.github.io/posts/2015-02-08-clang-tutorial-the-ast-matcher.html)
+- [Clang Tutorial: Finding Declarations](https://xinhuang.github.io/posts/2014-10-19-clang-tutorial-finding-declarations.html)
+
+### Clang Tutorial Part: LibTooling Example
+
+1. [Part I](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-i-introduction/)
+2. [Part II](https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/)
+3. [Part III](https://kevinaboos.wordpress.com/2013/07/29/clang-tutorial-part-iii-plugin-example/)
+
+### libclang static
+
+- [libclang-static-build](https://github.com/deech/libclang-static-build)
+
+- [Cmake standalone-static-libclang](https://prozacchiwawa.medium.com/deechs-standalone-static-libclang-a-libclang-distro-that-works-187efdd4102e)
+
+### Pragma
+
+- [Pragma token kind identifier](https://repo.hca.bsc.es/gitlab/rferrer/llvm-epi-0.8/-/commit/ea4f7c776194c96f8ece1456bc22102c6cbc9a33)
+- [Ex custom pragma 'TritonAssert'](https://github.com/quarkslab/clang/commit/0163f52f70e4781ce99710575bb66943125357b2)
+
+### Padding and packing in C/C++
+
+-
+
+### Python Binding (pybind11)
+
+- https://pybind11.readthedocs.io/en/stable/cmake/index.html
+- https://pybind11.readthedocs.io/en/stable/compiling.html#pybind11-add-module
+
+### Builder
+
+- https://scikit-build.readthedocs.io/en/latest/index.html
+- https://github.com/scikit-build/scikit-build-sample-projects
+
+- https://github.com/scikit-build/scikit-ci
+- https://github.com/scikit-build/scikit-ci/blob/master/docs/installation.rst
+
+- https://blog.kitware.com/creating-static-executables-on-linux/
+- https://cliutils.gitlab.io/modern-cmake/
+
+### C/C++ Googletest & python3 unittest
+
+- https://google.github.io/googletest/
+- https://github.com/google/googletest/tree/master/googletest/samples
+
+- https://python-packaging-user-guide.readthedocs.io/
+- https://docs.python.org/3/library/unittest.html
+- https://gayerie.dev/docs/python/python3/unittest.html
+
+
+### Doc
+
+- https://squidfunk.github.io/mkdocs-material/
\ No newline at end of file
diff --git a/docs/5.0-Extra.md b/docs/5.0-Extra.md
new file mode 100644
index 0000000..7d3092a
--- /dev/null
+++ b/docs/5.0-Extra.md
@@ -0,0 +1,34 @@
+# Extra
+
+## Install Clang llvm lld from source
+
+Follow: [LibTooling and LibASTMatchers](https://clang.llvm.org/docs/LibASTMatchersTutorial.html) installation tutorial if you want to contribute.
+
+Use `gold` or `lld` because `bfd` use too much ram
+
+`wget` or `curl --progress-bar -LO`
+
+```sh
+wget https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-12.0.1.tar.gz
+tar xvf llvmorg-12.0.1.tar.gz
+cd llvm-project-llvmorg-12.0.1
+
+cmake -G Ninja -S ./llvm -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld" -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_LINKER=gold -B build
+
+# export CC=`which clang`
+# export CXX=`which clang++`
+# export CFLAGS='-fuse-ld=ld.lld -rtlib=compiler-rt'
+# export CXXFLAGS='-fuse-ld=lld' # gcc
+# export CXXFLAGS='-B lld' # clang
+# sudo update-alternatives --install "/usr/bin/ld" "ld" `which ld.lld` 10
+
+cmake --build build -- -j`nproc`
+sudo cmake --install build
+cd build
+ninja install
+```
+
+```sh
+# uninstall from build
+xargs rm < install_manifest.txt
+```
diff --git a/docs/5.1-Documentations.md b/docs/5.1-Documentations.md
new file mode 100644
index 0000000..704c74b
--- /dev/null
+++ b/docs/5.1-Documentations.md
@@ -0,0 +1,10 @@
+# Documentation sevice
+
+```sh
+mkdocs serve
+docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material
+```
+
+```bash
+pdoc3 pdic
+```
diff --git a/docs/index.md b/docs/index.md
new file mode 120000
index 0000000..32d46ee
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1 @@
+../README.md
\ No newline at end of file
diff --git a/docs_format/Roboto-Black.ttf b/docs_format/Roboto-Black.ttf
new file mode 100644
index 0000000..2d45238
Binary files /dev/null and b/docs_format/Roboto-Black.ttf differ
diff --git a/docs_format/Roboto-BlackItalic.ttf b/docs_format/Roboto-BlackItalic.ttf
new file mode 100644
index 0000000..29a4359
Binary files /dev/null and b/docs_format/Roboto-BlackItalic.ttf differ
diff --git a/docs_format/Roboto-Bold.ttf b/docs_format/Roboto-Bold.ttf
new file mode 100644
index 0000000..d998cf5
Binary files /dev/null and b/docs_format/Roboto-Bold.ttf differ
diff --git a/docs_format/Roboto-BoldItalic.ttf b/docs_format/Roboto-BoldItalic.ttf
new file mode 100644
index 0000000..b4e2210
Binary files /dev/null and b/docs_format/Roboto-BoldItalic.ttf differ
diff --git a/docs_format/Roboto-Italic.ttf b/docs_format/Roboto-Italic.ttf
new file mode 100644
index 0000000..5b390ff
Binary files /dev/null and b/docs_format/Roboto-Italic.ttf differ
diff --git a/docs_format/Roboto-Light.ttf b/docs_format/Roboto-Light.ttf
new file mode 100644
index 0000000..3526798
Binary files /dev/null and b/docs_format/Roboto-Light.ttf differ
diff --git a/docs_format/Roboto-LightItalic.ttf b/docs_format/Roboto-LightItalic.ttf
new file mode 100644
index 0000000..46e9bf7
Binary files /dev/null and b/docs_format/Roboto-LightItalic.ttf differ
diff --git a/docs_format/Roboto-Medium.ttf b/docs_format/Roboto-Medium.ttf
new file mode 100644
index 0000000..f714a51
Binary files /dev/null and b/docs_format/Roboto-Medium.ttf differ
diff --git a/docs_format/Roboto-MediumItalic.ttf b/docs_format/Roboto-MediumItalic.ttf
new file mode 100644
index 0000000..5dc6a2d
Binary files /dev/null and b/docs_format/Roboto-MediumItalic.ttf differ
diff --git a/docs_format/Roboto-Regular.ttf b/docs_format/Roboto-Regular.ttf
new file mode 100644
index 0000000..2b6392f
Binary files /dev/null and b/docs_format/Roboto-Regular.ttf differ
diff --git a/docs_format/Roboto-Thin.ttf b/docs_format/Roboto-Thin.ttf
new file mode 100644
index 0000000..4e797cf
Binary files /dev/null and b/docs_format/Roboto-Thin.ttf differ
diff --git a/docs_format/Roboto-ThinItalic.ttf b/docs_format/Roboto-ThinItalic.ttf
new file mode 100644
index 0000000..eea836f
Binary files /dev/null and b/docs_format/Roboto-ThinItalic.ttf differ
diff --git a/entrypoint.sh b/entrypoint.sh
new file mode 100755
index 0000000..f63f267
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,4 @@
+# !/bin/bash --login
+# activate conda environment and let the following process take over
+source ~/.bashrc
+exec "$@"
\ No newline at end of file
diff --git a/examples/PDI_test_parse.c b/examples/PDI_test_parse.c
new file mode 100644
index 0000000..370061c
--- /dev/null
+++ b/examples/PDI_test_parse.c
@@ -0,0 +1,42 @@
+#pragma pdi on
+
+typedef struct
+{
+ int my_int;
+ char my_char;
+} var8;
+
+typedef struct
+{
+ char my_char;
+ int my_array[10][10];
+} var9;
+
+typedef struct
+{
+ char my_char;
+ var9 v9;
+} var10;
+
+typedef struct
+{
+ char *my_pointer;
+ int my_int;
+} var16;
+
+char var1;
+short int var2;
+int var3;
+double var4;
+float var5;
+char var6[10];
+int var7[10000][10000];
+
+int *var11; // pointer to int
+int **var12; // pointer to int pointer
+int **var13; // pointer to 32bit array of int
+int *var14[32]; // array of int pointers
+
+var8 var15;
+
+#pragma pdi off
\ No newline at end of file
diff --git a/examples/__init__.py b/examples/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/examples/example.py b/examples/example.py
new file mode 100644
index 0000000..36f49d0
--- /dev/null
+++ b/examples/example.py
@@ -0,0 +1,13 @@
+import os
+import pathlib
+import yaml
+import pdic
+
+here = pathlib.Path(__file__).parent.resolve()
+# pip3 install --use-feature=in-tree-build . -v
+# pip show -f pdic
+if __name__ == "__main__":
+ pdi_yml_description: str = pdic.files_to_pdi([os.path.join(here, "level_1.c"),
+ os.path.join(here, "level_2.c")])
+ print(pdi_yml_description)
+ print(yaml.dump(yaml.load(pdi_yml_description)))
diff --git a/examples/level_1.c b/examples/level_1.c
index 7f4dbed..91c19ea 100644
--- a/examples/level_1.c
+++ b/examples/level_1.c
@@ -9,7 +9,7 @@
* -----
* Licenses: EUPL
* -----
- * Copyright 2021 - 2021 NinjaTech
+ * Copyright 2021 - 2021 neudinger
*/
short notsee;
diff --git a/examples/level_2.c b/examples/level_2.c
index 9f39af6..dbb97ad 100644
--- a/examples/level_2.c
+++ b/examples/level_2.c
@@ -9,7 +9,7 @@
* -----
* Licenses: EUPL
* -----
- * Copyright 2021 - 2021 NinjaTech
+ * Copyright 2021 - 2021 neudinger
*/
#pragma pdi on
diff --git a/examples/level_3.cpp b/examples/level_3.cpp
index 4d88dab..fac0410 100644
--- a/examples/level_3.cpp
+++ b/examples/level_3.cpp
@@ -9,7 +9,7 @@
* -----
* Licenses: EUPL
* -----
- * Copyright 2021 - 2021 NinjaTech
+ * Copyright 2021 - 2021 neudinger
*/
#pragma pdi on
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..2312065
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,65 @@
+# Project information
+site_name: PDIC
+site_description: 'Interface description language c/c++ to PDI'
+site_author: 'Barre Kevin'
+# site_url: ''
+# material, readthedocs, bootstrap4
+
+theme:
+ features:
+ - navigation.instant
+ name: 'material'
+ language: 'fr'
+ palette:
+ primary: 'blue grey'
+ accent: 'teal'
+ font:
+ text: 'Ubuntu'
+ code: 'Ubuntu Mono'
+ extra:
+ disqus: 'Barre kevin'
+ version:
+ default: stable
+
+markdown_extensions:
+ - admonition
+ - meta
+ - codehilite:
+ linenums: true
+ guess_lang: false
+ - footnotes
+ - toc:
+ permalink: "#"
+ - pymdownx.arithmatex
+ - pymdownx.betterem:
+ smart_enable: all
+ - pymdownx.caret
+ - pymdownx.critic
+ - pymdownx.details
+ - pymdownx.emoji:
+ emoji_generator: python/name:pymdownx.emoji.to_svg
+ - pymdownx.inlinehilite
+ - pymdownx.magiclink
+ - pymdownx.mark
+ - pymdownx.smartsymbols
+ - pymdownx.superfences
+ - pymdownx.tasklist:
+ custom_checkbox: true
+ - pymdownx.tilde
+
+nav:
+ - Abstract: '1.0-Abstract.md'
+ - Usage:
+ - Requirement: '2.0-Requirement.md'
+ - Binary: '2.1-Binary.md'
+ - Python: '2.2-Python.md'
+ - Developpement: '3.0-Developpement.md'
+ - Links: 4.0-Links.md
+ - Extra: 5.0-Extra.md
+ - Documentations: 5.1-Documentations.md
+# plugins:
+# - redirects:
+# redirect_maps:
+# ./docs/1.0-Abstract.md: 1.0-Abstract.md
+# # 'old/file.md': 'new/file.md'
+# # 'some_file.md': 'http://external.url.com/foobar'
diff --git a/modules/Binary.cmake b/modules/Binary.cmake
new file mode 100644
index 0000000..62bffa6
--- /dev/null
+++ b/modules/Binary.cmake
@@ -0,0 +1,21 @@
+add_compile_options(-fno-rtti)
+set(CLANG_LIB clang_bundled) # static
+set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
+option(BUILD_SHARED_LIBS "Build using shared libraries" OFF)
+set(CMAKE_EXE_LINKER_FLAGS -static)
+message(STATUS "The project will build a binary")
+set(BINTARGET "${TARGET}.static")
+add_executable(${BINTARGET}
+ ${SRC}
+)
+target_link_libraries(${BINTARGET}
+ PRIVATE
+ ${CLANG_LIB} # clang lib
+ pthread # multithreading
+ m # math
+ dl # dynamic loader
+ z # zlib
+)
+add_dependencies(${BINTARGET} libclang-static-build)
+set_property(TARGET ${BINTARGET} PROPERTY CXX_STANDARD 20)
+unset(CLANG_LIB CACHE)
\ No newline at end of file
diff --git a/modules/Builder.cmake b/modules/Builder.cmake
new file mode 100644
index 0000000..17f15ad
--- /dev/null
+++ b/modules/Builder.cmake
@@ -0,0 +1,39 @@
+# IF MSVC
+# set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
+# SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.dll.a;.dll")
+# target_compile_options(your_target_name [PUBLIC|PRIVATE] /MT)
+# target_link_options(your_target_name [PUBLIC|PRIVATE] /INCREMENTAL:NO /NODEFAULTLIB:MSVCRT)
+# IF MFC
+# https://cmake.org/cmake/help/latest/variable/CMAKE_MFC_FLAG.html
+# set(CMAKE_MFC_FLAG 1)
+
+
+if(SKBUILD) # Python pybind build
+ include(Pybuild)
+endif(SKBUILD)
+
+if(BINARY OR TEST) # pdic portable binary
+ include(LibClang)
+ message(STATUS "clang binary_dir is " ${binary_dir})
+ link_directories(
+ ${binary_dir} # some lib are there
+ ${binary_dir}/_all_archives # other are there
+ ${binary_dir}/libclang-copied/lib # all are copied there
+ )
+
+ include_directories(
+ ${binary_dir}/_deps/clang_sources-src/include
+ ${binary_dir}/_deps/libclang_prebuilt-src/include
+ )
+
+ if(BINARY) # pdic portable binary
+ include(Binary)
+ endif(BINARY)
+ if(TEST) # cmake google test
+ include(Tests)
+ endif(TEST)
+endif(BINARY OR TEST)
+
+
+
+
diff --git a/modules/LibClang.cmake b/modules/LibClang.cmake
new file mode 100644
index 0000000..4123cf2
--- /dev/null
+++ b/modules/LibClang.cmake
@@ -0,0 +1,12 @@
+include(ExternalProject)
+# Clang 12
+set(LIBCLANG_INSTALL libclang-copied)
+ExternalProject_Add(libclang-static-build
+ DOWNLOAD_DIR "libclang-static-build"
+ INSTALL_DIR "${LIBCLANG_INSTALL}"
+ GIT_REPOSITORY "https://github.com/deech/libclang-static-build"
+ GIT_TAG "3daf7793644764bff2dad11021051a6b8f450a52" # latest
+ # GIT_TAG "0cae8e85ef1ad951e1bb560e1eadcd64b2f0828e"
+ CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${LIBCLANG_INSTALL}"
+)
+ExternalProject_Get_Property(libclang-static-build binary_dir)
diff --git a/modules/Pybuild.cmake b/modules/Pybuild.cmake
new file mode 100644
index 0000000..10a4bee
--- /dev/null
+++ b/modules/Pybuild.cmake
@@ -0,0 +1,48 @@
+# Python pybind build
+
+FetchContent_Declare(
+ pybind11
+ URL https://github.com/pybind/pybind11/archive/refs/tags/v2.7.1.tar.gz
+)
+FetchContent_MakeAvailable(pybind11)
+message(STATUS "The project is built using scikit-build")
+set(PYTARGET "py${TARGET}")
+# export LLVM_DIR=/media/kbarre/1d7f0a7c-34d5-4837-ad9a-95be3ec8cb53/Documents/dev/desciptor/pdic/src/llvm-project-llvmorg-12.0.1/build/
+# export Clang_DIR=/media/kbarre/1d7f0a7c-34d5-4837-ad9a-95be3ec8cb53/Documents/dev/desciptor/pdic/src/llvm-project-llvmorg-12.0.1/build/
+find_package(LLVM REQUIRED)
+find_package(Clang REQUIRED)
+list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
+set(LLVM_ENABLE_PLUGINS ON)
+set(LLVM_LINK_COMPONENTS Support)
+# # Set compiler flags.
+# include(HandleLLVMOptions) # Hardcore warning
+# # Use LLVM and clang headers.
+include(AddLLVM)
+include_directories(${LLVM_INCLUDE_DIRS})
+include_directories(${CLANG_INCLUDE_DIRS})
+
+add_definitions(${LLVM_DEFINITIONS})
+add_definitions(${CLANG_DEFINITIONS})
+
+pybind11_add_module(${PYTARGET}
+ MODULE
+ ${SRC}
+)
+target_link_libraries(${PYTARGET}
+ PRIVATE
+ clang
+ clangAST
+ clangBasic
+ clangFrontend
+ clangTooling
+ clangASTMatchers
+ clangSerialization
+ pthread # multithreading
+ m # math
+ dl # dynamic loader
+ z # zlib
+)
+add_compile_definitions(SKBUILD=True)
+set_property(TARGET ${PYTARGET} PROPERTY CXX_STANDARD 20)
+# add_dependencies(${PYTARGET} libclang-static-build)
+install(TARGETS ${PYTARGET} LIBRARY DESTINATION .)
diff --git a/modules/Tests.cmake b/modules/Tests.cmake
new file mode 100644
index 0000000..f80e369
--- /dev/null
+++ b/modules/Tests.cmake
@@ -0,0 +1,43 @@
+FetchContent_Declare(
+ googletest
+ URL https://github.com/google/googletest/archive/refs/tags/release-1.11.0.tar.gz
+)
+message(STATUS "The project will build google tests")
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+FetchContent_MakeAvailable(googletest)
+add_compile_options(-fno-rtti)
+
+list(APPEND FileName c_yaml_test)
+
+add_compile_definitions(GOOGLE_TEST=True)
+
+
+get_filename_component(WORKDIR "${CMAKE_CURRENT_LIST_DIR}" PATH)
+set(WORKDIR ${WORKDIR}/src/pdic)
+include_directories(
+ ${WORKDIR}
+)
+
+include(GoogleTest)
+enable_testing()
+foreach(X IN LISTS FileName)
+ message(STATUS "Build TEST: ${X}")
+ add_executable(
+ ${X}
+ tests/${X}.cc
+ ${SRC}
+ )
+ target_link_libraries(${X}
+ PRIVATE
+ gtest_main # Google test lib
+ clang_bundled # Dynamic clang lib
+ pthread # multithreading
+ m # math
+ dl # dynamic loader
+ z # zlib
+ )
+ add_dependencies(${X} libclang-static-build)
+ set_property(TARGET ${X} PROPERTY CXX_STANDARD 20)
+ gtest_discover_tests(${X})
+ add_test(NAME ${X} COMMAND ${X})
+endforeach()
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..8410104
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,5 @@
+[build-system]
+requires = ["setuptools", "wheel", "scikit-build", "cmake", "ninja", "pytest"]
+build-backend = "setuptools.build_meta"
+[tool.pytest.ini_options]
+testpaths = ["tests"]
diff --git a/requirement.yml b/requirement.yml
new file mode 100644
index 0000000..733cfa7
--- /dev/null
+++ b/requirement.yml
@@ -0,0 +1,13 @@
+channels:
+ - defaults
+ - conda-forge
+dependencies:
+ - python=3.9
+ - pip
+ - cmake=3.21.2
+ - scikit-build
+ - twine
+ - pytest
+ - pyyaml
+ - pip:
+ - "pdoc3"
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..7342fae
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,69 @@
+__author__ = "Barre Kevin"
+__maintainer__ = "Barre kevin"
+__credits__ = ["https://github.com/neudinger"]
+__email__ = "kevin.barre@epitech.eu"
+__status__ = "Beta"
+
+import os
+import sys
+import pathlib
+import re
+try:
+ from skbuild import setup
+except ImportError:
+ print('Please update pip, you need pip 10 or greater,\n'
+ ' or you need to install the PEP 518 requirements in pyproject.toml yourself', file=sys.stderr)
+ raise
+
+here = pathlib.Path(__file__).parent.resolve()
+long_description = (here / "README.md").read_text(encoding="utf-8")
+
+
+version = os.getenv("version", default="0.0.1")
+version = re.match(r".*?(\d+\.?\d+\.?\d+).*?",
+ version, re.S).groups()[0]
+
+
+print(f"__version__ = '{version}'",
+ file=open(f"{here}/src/pdic/__version__.py", "w"))
+
+setup(
+ name="pdic",
+ version=version,
+ author_email="kevin.barre@epitech.eu",
+ description="Python api (IDL) Transpiler Source-to-source compiler C/C++ to YAML Description based on clang",
+ long_description_content_type="text/markdown",
+ long_description=long_description,
+ author="Barre Kevin",
+ license="EUPL",
+ python_requires=">=3.6",
+ packages=["pdic"],
+ package_dir={"": "src"},
+ project_urls={
+ 'Source': 'https://github.com/neudinger/pdic',
+ },
+ cmake_install_dir="src/pdic",
+ cmake_args=['-DDEBUG:BOOL=OFF'],
+ install_requires=[
+ "pyyaml"
+ ],
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ "Programming Language :: C++",
+ "Topic :: Software Development",
+ "Topic :: Scientific/Engineering",
+ "Typing :: Typed",
+ "Operating System :: POSIX",
+ "Operating System :: Unix",
+ "Operating System :: MacOS",
+ "Programming Language :: Python :: 3",
+ "Operating System :: OS Independent",
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3 :: Only',
+ ],
+)
diff --git a/src/pdic/PDIDecls.cpp b/src/pdic/PDIDecls.cpp
new file mode 100644
index 0000000..e1e1833
--- /dev/null
+++ b/src/pdic/PDIDecls.cpp
@@ -0,0 +1,251 @@
+/*
+ * File: PDIDecls.cpp
+ * Project: PDIC
+ * File Created: Monday, 10th May 2021 12:23:33 am
+ * Author: kbarre (kevin.barre@epitech.eu)
+ * -----
+ * Last Modified: Thursday, 22nd July 2021 12:57:01 am
+ * Modified By: kbarre (kevin.barre@epitech.eu>)
+ * -----
+ * Licenses: EUPL
+ * -----
+ * Copyright 2021 - 2021 neudinger
+ */
+
+// clang::ASTFrontendAction
+#include "clang/AST/RecursiveASTVisitor.h"
+
+// import clang::CompilerInstance
+#include "clang/Frontend/CompilerInstance.h"
+
+// import clang::tooling::ClangTool
+#include "clang/Tooling/Tooling.h"
+
+// import clang::tooling::CommonOptionsParser
+// #include "clang/Tooling/CommonOptionsParser.h" $ only for pdi binary
+
+// use of clang::ASTRecordLayout &typeLayout
+#include "clang/AST/RecordLayout.h"
+
+#include "PDIDecls.hpp"
+
+namespace PDI
+{
+ // Usefull link
+ // https://github.com/quarkslab/clang/commit/0163f52f70e4781ce99710575bb66943125357b2
+
+ /// push the declaration of __attribute(annotate(char const*))) into the stream
+ /// it is added before each call
+ static void PragmaPDItoAnnotate(clang::Preprocessor &PP,
+ clang::SmallVectorImpl &TokenList,
+ std::string AnnotateStr)
+ {
+ static char const _attrAnnotate[] = "annotate";
+ clang::Token AttrNameTok;
+ AttrNameTok.startToken();
+ AttrNameTok.setKind(clang::tok::string_literal);
+ AttrNameTok.setLength(AnnotateStr.size());
+ AttrNameTok.setLiteralData(strdup(AnnotateStr.data()));
+
+ clang::Token AttrTok;
+ AttrTok.startToken();
+ AttrTok.setKind(clang::tok::kw___attribute);
+
+ clang::Token LParTok;
+ LParTok.startToken();
+ LParTok.setKind(clang::tok::l_paren);
+
+ clang::Token RParTok;
+ RParTok.startToken();
+ RParTok.setKind(clang::tok::r_paren);
+
+ clang::Token AnnotTok;
+ AnnotTok.startToken();
+ AnnotTok.setKind(clang::tok::identifier);
+ AnnotTok.setIdentifierInfo(PP.getIdentifierInfo(_attrAnnotate));
+
+ TokenList.push_back(AttrTok);
+ TokenList.push_back(LParTok);
+ TokenList.push_back(LParTok);
+ TokenList.push_back(AnnotTok);
+ TokenList.push_back(LParTok);
+ TokenList.push_back(AttrNameTok);
+ TokenList.push_back(RParTok);
+ TokenList.push_back(RParTok);
+ TokenList.push_back(RParTok);
+ }
+ void PragmaHandler::HandlePragma(clang::Preprocessor &PP,
+ clang::PragmaIntroducer Introducer,
+ clang::Token &PragmaTok)
+ {
+ clang::Token Tok;
+ clang::SmallVector TokenList;
+ std::ostringstream PDIDirectiveStream;
+
+ PDIDirectiveStream << "\"";
+
+ while ((PP.Lex(Tok), true) && Tok.isNot(clang::tok::eod))
+ PDIDirectiveStream << PP.getSpelling(Tok);
+ if (pdiSwitch.isRaised(/* stringStream= */ PDIDirectiveStream,
+ /* sourceLocation= */ Tok.getLocation()))
+ return;
+
+ PDIDirectiveStream << "\"";
+
+ PragmaPDItoAnnotate(PP, TokenList, PDIDirectiveStream.str());
+ clang::Token *TokenArray = new clang::Token[TokenList.size()];
+ std::copy(TokenList.begin(), TokenList.end(), TokenArray);
+ PP.EnterTokenStream(/* Toks= */ llvm::makeArrayRef(TokenArray, TokenList.size()),
+ /* DisableMacroExpansion= */ false,
+ /* IsReinject= */ true);
+ // Do NOT delete TokenArray
+ // It will remove AST information
+ }
+ const bool PDIDeclVisitor::VisitVarDecl(const clang::VarDecl *varDecl)
+ {
+ typeIdentifiers[varDecl->getNameAsString()] = EvalDecl(varDecl);
+ return !PragmaError;
+ }
+ const bool PDIDeclVisitor::VisitRecordDecl(const clang::RecordDecl *recordDecl)
+ {
+ const clang::ASTRecordLayout &typeLayout(recordDecl->getASTContext().getASTRecordLayout(recordDecl));
+ StructAttr curentStruct = StructAttr(/* name= */ recordDecl->getNameAsString(),
+ /* size= */ typeLayout.getSize(),
+ /* fieldCount= */ typeLayout.getFieldCount(),
+ /* sourceLocation= */ recordDecl->getLocation());
+
+ if (!recordDecl->isStruct())
+ RAISE("Only struct allowed", recordDecl);
+
+ if (recordDecl->getNameAsString().empty())
+ WARN("Anonymous struct used : First alias Or generated ID will be used as StructName", recordDecl);
+
+ // Check if
+ // #pragma pack
+ // #pragma pack(n)
+ // https://docs.microsoft.com/en-us/cpp/preprocessor/pack?view=msvc-160
+ // and __attribute__((packed))
+ if (const auto *MFAA = recordDecl->getAttr())
+ curentStruct.packed = true;
+ else if (recordDecl->getAttr())
+ curentStruct.packed = true;
+
+ structIdentifiers[reinterpret_cast(recordDecl->getTypeForDecl())] = curentStruct;
+
+ // return true if no PragmaError was raised
+ // This method must return true if no error occurred
+ // PragmaError must alway be false if no error occurred
+ return !PragmaError;
+ }
+ const bool PDIDeclVisitor::VisitFieldDecl(const clang::FieldDecl *fieldDecl)
+ {
+ const auto recordAddr = reinterpret_cast(fieldDecl->getParent()->getTypeForDecl());
+ auto &curentStruct = structIdentifiers[recordAddr];
+ const clang::ASTRecordLayout &typeLayout = fieldDecl->getASTContext().getASTRecordLayout(fieldDecl->getParent());
+ TypeAttr curentType = EvalDecl(fieldDecl);
+
+ if (!fieldDecl->getParent()->isStruct())
+ RAISE("Only struct type are suported", fieldDecl);
+
+ if (wrapMap(structIdentifiers).hasNot(/* key= */ recordAddr))
+ RAISE("Parent record type are not suported", fieldDecl);
+
+ // Add offset on each field base on padding and packing struct memory alignement
+ curentType.offset = typeLayout.getFieldOffset(fieldDecl->getFieldIndex()) / BYTE_SIZE;
+
+ // Add Field description to current struct description
+ curentStruct.fields[fieldDecl->getNameAsString()] = curentType;
+
+ // return true if no PragmaError was raised
+ // This must return true if no error occurred
+ // PragmaError must alway be false if no error occurred
+ return !PragmaError;
+ }
+ const bool PDIDeclVisitor::VisitTypedefDecl(const clang::TypedefDecl *typedefDecl)
+ {
+ // Retreive struct inserted during VisitRecordDecl process
+ auto &curentStruct = structIdentifiers[reinterpret_cast(typedefDecl->getTypeSourceInfo()->getType()->getAs())];
+ // Define this alias as global name if struct is Anonymous
+ if (curentStruct.name.empty())
+ curentStruct.name = typedefDecl->getNameAsString();
+ // Add typedef alias to this struct description
+ curentStruct.alias.push_back(typedefDecl->getNameAsString());
+ return true;
+ }
+ bool ASTConsumerDeclConsumer::HandleTopLevelDecl(clang::DeclGroupRef dg)
+ {
+ for (clang::Decl *decl : dg)
+ {
+ /// Create Custom annotation
+ // decl->addAttr(clang::AnnotateAttr::CreateImplicit(decl->getASTContext(),
+ // pragmaTypeIdentifiers.type));
+
+ /// Check if the current declaration is between pragma on and off
+ /// pragma pdi on
+ /// (decl)
+ /// pragma pdi off
+ if (!(pdiSwitch.isOnRaised && IsBefore(/* LHS= */ pdiSwitch.pdiOnLoc,
+ /* RHS= */ decl->getLocation())) ||
+ (pdiSwitch.isOffRaised && IsBefore(/* LHS= */ pdiSwitch.pdiOffLoc,
+ /* RHS= */ decl->getLocation())))
+ break;
+#ifdef DEBUG
+ decl->dumpColor(); // <- Usefull for debug
+#endif
+ /// Stop if any error occurred
+ if (!declNodeVisitor.TraverseDecl(decl) ||
+ compilerInstance.getSourceManager().getDiagnostics().hasErrorOccurred())
+ return false;
+ }
+ return true;
+ }
+}
+
+class PDIPluginASTAction : public clang::ASTFrontendAction
+{
+public:
+ std::unique_ptr
+ CreateASTConsumer(clang::CompilerInstance &compilerInstance,
+ const llvm::StringRef fileName) override
+ {
+ clang::Preprocessor &PP = compilerInstance.getPreprocessor();
+ PP.AddPragmaHandler(new PDI::PragmaHandler());
+ return std::make_unique(compilerInstance);
+ }
+};
+
+void serializeIn(std::ostringstream &ostream)
+{
+ if (!PDI::structIdentifiers.empty())
+ ostream << "structs:\n";
+ DescribeStructs(ostream, PDI::structIdentifiers);
+ if (!PDI::typeIdentifiers.empty())
+ ostream << "data:\n";
+ DescribeTypes(ostream,
+ PDI::typeIdentifiers,
+ PDI::structIdentifiers);
+}
+
+void writeYML(const std::ostringstream &ostream,
+ const std::string &firstSourceFile)
+{
+ std::string outputFileName(firstSourceFile);
+ std::ofstream outputFile(outputFileName
+ .substr(0, outputFileName.find_last_of('.')) +
+ ".yml",
+ std::ios::trunc | std::ios::out);
+ outputFile << ostream.str();
+ outputFile.close();
+}
+
+// clang::tooling::runToolOnCode(std::make_unique(), "namespace n { namespace m { class C {}; } }");
+// std::unique_ptr AST(tooling::buildASTFromCode("auto x = 1 + 1;"));
+// TranslationUnitDecl *DC = AST->getASTContext().getTranslationUnitDecl();
+
+#if defined(SKBUILD)
+#include "pypdicbind.hpp"
+#elif defined(GOOGLE_TEST)
+#include "maintest.hpp"
+#else
+#include "main.hpp"
+#endif // SKBUILD
\ No newline at end of file
diff --git a/src/pdic/PDIDecls.hpp b/src/pdic/PDIDecls.hpp
new file mode 100644
index 0000000..f0356db
--- /dev/null
+++ b/src/pdic/PDIDecls.hpp
@@ -0,0 +1,115 @@
+/*
+ * File: PDIDecls.hpp
+ * Project: PDIC
+ * File Created: Wednesday, 21st July 2021 4:34:34 pm
+ * Author: kbarre (kevin.barre@epitech.eu)
+ * -----
+ * Last Modified: Thursday, 22nd July 2021 12:57:37 am
+ * Modified By: kbarre (kevin.barre@epitech.eu>)
+ * -----
+ * Licenses: EUPL
+ * -----
+ * Copyright 2021 - 2021 neudinger
+ */
+
+#if !defined(PDI_DECLS)
+#define PDI_DECLS
+#include "PDITools.hpp"
+#include "PDISerializer.hpp"
+
+namespace PDI
+{
+ static bool PragmaError = false;
+ static TypeMap typeIdentifiers;
+ static StructMap structIdentifiers;
+ static Switch pdiSwitch;
+
+ class PragmaHandler : public clang::PragmaHandler
+ {
+ public:
+ PragmaHandler() : clang::PragmaHandler() {}
+
+ void HandlePragma(clang::Preprocessor &PP,
+ clang::PragmaIntroducer Introducer,
+ clang::Token &PragmaTok) override;
+ };
+
+ // RecursiveASTVisitor does a pre-order depth-first traversal of the
+ // AST. We implement VisitFoo() methods for the types of nodes we are
+ // interested in.
+ class PDIDeclVisitor : public clang::RecursiveASTVisitor
+ {
+ private:
+ const clang::SourceManager &sourceManager;
+ template
+ TypeAttr EvalDecl(DECL nodeDecl)
+ {
+
+ TypeAttr curentId;
+ std::vector declTypes;
+ const std::string declString(nodeDecl->getType().getAsString());
+ const clang::TypeInfo typeInfo = nodeDecl->getASTContext().getTypeInfo(nodeDecl->getType());
+
+ if (declString.find("struct (") != std::string::npos)
+ RAISE("Anonymous struct without typedef not allowed", nodeDecl);
+
+ if (nodeDecl->getType()->template getAs()->isStructureType())
+ curentId.structId = reinterpret_cast(nodeDecl->getType()->template getAs());
+
+ curentId.sourceLoc = nodeDecl->getLocation();
+ curentId.name = nodeDecl->getNameAsString();
+ split(declString, declTypes);
+ curentId.type = (declTypes.size() > 1) ? *(--(--declTypes.cend())) : declTypes.back();
+ curentId.starsNbr = charLen(declString, '*');
+ extractBetweens(declTypes.back(), curentId.arraySizes);
+ for (const auto &attr : nodeDecl->getAttrs())
+ // llvm::outs() << attr->getSpelling() << "\n" // usefull in debug mode
+ if (attr->getKind() == clang::attr::Annotate)
+ curentId.pragma.load(/* attributes= */
+ (static_cast(attr))->getAnnotation().str());
+ if (curentId.starsNbr &&
+ curentId.pragma.arraySizes.size() >= curentId.starsNbr)
+ RAISE("Numbers of stars must be > in Pragma array", nodeDecl);
+
+ curentId.buffersize = typeInfo.Width / BYTE_SIZE;
+
+ return curentId;
+ }
+
+ public:
+ explicit PDIDeclVisitor(const clang::SourceManager &SM) : sourceManager(SM) {}
+ const bool VisitVarDecl(const clang::VarDecl *varDecl);
+ // Struct handler
+ const bool VisitRecordDecl(const clang::RecordDecl *recordDecl);
+ const bool VisitFieldDecl(const clang::FieldDecl *fieldDecl);
+ // This will add any alias to the existing structures
+ const bool VisitTypedefDecl(const clang::TypedefDecl *typedefDecl);
+ };
+
+ // An ASTConsumer is a client object that receives callbacks as the AST is
+ // built, and "consumes" it.
+ class ASTConsumerDeclConsumer : public clang::ASTConsumer
+ {
+ private:
+ PDIDeclVisitor declNodeVisitor;
+ clang::CompilerInstance &compilerInstance;
+
+ /// Return true If LHS is located before RHS
+ // constexpr
+ bool const IsBefore(const clang::SourceLocation &LHS,
+ const clang::SourceLocation RHS)
+ {
+ return compilerInstance.getSourceManager().isBeforeInTranslationUnit(LHS, RHS);
+ }
+
+ public:
+ explicit ASTConsumerDeclConsumer(clang::CompilerInstance &CI)
+ : declNodeVisitor(PDIDeclVisitor(CI.getSourceManager())),
+ compilerInstance(CI) {}
+
+ // Called by the parser for each top-level declaration group.
+ // Returns true to continue parsing, or false to abort parsing.
+ virtual bool HandleTopLevelDecl(clang::DeclGroupRef dg) override;
+ };
+}
+#endif // PDI_DECLS
diff --git a/src/pdic/PDISerializer.cpp b/src/pdic/PDISerializer.cpp
new file mode 100644
index 0000000..39a2d07
--- /dev/null
+++ b/src/pdic/PDISerializer.cpp
@@ -0,0 +1,119 @@
+/*
+ * File: PDISerializer.cpp
+ * Project: PDIC
+ * File Created: Wednesday, 21st July 2021 11:54:17 am
+ * Author: kbarre (kevin.barre@epitech.eu)
+ * -----
+ * Last Modified: Thursday, 22nd July 2021 12:57:43 am
+ * Modified By: kbarre (kevin.barre@epitech.eu>)
+ * -----
+ * Licenses: EUPL
+ * -----
+ * Copyright 2021 - 2021 neudinger
+ */
+
+#include "PDISerializer.hpp"
+
+void DescribeStruct(std::ostringstream &ostream,
+ const PDI::StructAttr &structIdentifier,
+ const PDI::StructMap &structIdentifiers,
+ const std::size_t extraSpaces)
+{
+ ostream << duplicateChar(' ', extraSpaces) << "type: record\n";
+ ostream << duplicateChar(' ', extraSpaces) << "name: " << structIdentifier.name << "\n";
+ if (!structIdentifier.alias.empty())
+ {
+ ostream << duplicateChar(' ', extraSpaces) << "alias: [";
+ std::copy(structIdentifier.alias.cbegin(), structIdentifier.alias.cend() - 1,
+ std::ostream_iterator(ostream, ", "));
+ ostream << structIdentifier.alias.back() << "]\n";
+ }
+ ostream << duplicateChar(' ', extraSpaces) << "fieldsize: " << structIdentifier.fieldSize << "\n";
+ ostream << duplicateChar(' ', extraSpaces) << "buffersize: " << structIdentifier.size.getQuantity() << "\n";
+ ostream << duplicateChar(' ', extraSpaces) << "packed: " << structIdentifier.packed << "\n";
+ ostream << duplicateChar(' ', extraSpaces) << "members:\n";
+ DescribeTypes(ostream,
+ structIdentifier.fields,
+ structIdentifiers,
+ extraSpaces + 1);
+}
+
+void DescribeStructs(std::ostringstream &ostream,
+ const PDI::StructMap &structIdentifiers,
+ const std::size_t extraSpaces)
+{
+ for (const auto &[structID, structIdentifier] : structIdentifiers)
+ {
+ ostream << duplicateChar(' ', extraSpaces) << structIdentifier.name << ":\n";
+ DescribeStruct(ostream,
+ structIdentifier,
+ structIdentifiers,
+ extraSpaces + 1);
+ }
+}
+
+void DescribeTypes(std::ostringstream &ostream,
+ const PDI::TypeMap &typeIdentifiers,
+ const PDI::StructMap &structIdentifiers,
+ const std::size_t extraSpaces)
+{
+ std::string typeRepr;
+ for (const auto &[typeIdentifierName, typeIdentifier] : typeIdentifiers)
+ {
+ pushCharsIn(ostream, ' ', extraSpaces);
+ ostream << typeIdentifier.name << ':';
+ typeRepr = typeIdentifier.type;
+
+ // Dont print offset multiple time
+ if (typeIdentifier.offset &&
+ !typeIdentifier.starsNbr && // PDI::describePointer print offset
+ typeIdentifier.arraySizes.empty() && // PDI::describeArray print offset
+ typeIdentifier.pragma.arraySizes.empty() // PDI::describeArray print offset
+ )
+ {
+ ostream << "\n";
+ pushCharsIn(ostream, ' ', extraSpaces + 1);
+ ostream << "offset: " << typeIdentifier.offset;
+ }
+ if (typeIdentifier.pragma.isNotEmpty())
+ {
+ if (!typeIdentifier.pragma.type.empty())
+ typeRepr = typeIdentifier.pragma.type;
+ if (!typeIdentifier.pragma.arraySizes.empty())
+ PDI::describePragmaArray(typeIdentifier, typeRepr);
+ if (typeIdentifier.starsNbr)
+ PDI::describePointer(typeIdentifier, typeRepr);
+ if (!typeIdentifier.arraySizes.empty())
+ PDI::describeArray(typeIdentifier.arraySizes, typeRepr, typeIdentifier.offset);
+ if (typeRepr == typeIdentifier.pragma.type)
+ typeRepr = "\n" +
+ duplicateChar(' ', extraSpaces + 1) + "type: " + typeRepr;
+ ostream << typeRepr;
+ }
+ else
+ {
+ if (typeIdentifier.starsNbr)
+ PDI::describePointer(typeIdentifier, typeRepr);
+ if (!typeIdentifier.arraySizes.empty())
+ PDI::describeArray(typeIdentifier.arraySizes, typeRepr);
+ if (typeIdentifier.structId)
+ {
+ ostream << "\n";
+ DescribeStruct(ostream,
+ wrapMap(structIdentifiers).get(typeIdentifier.structId, PDI::StructAttr()),
+ structIdentifiers,
+ extraSpaces + 1);
+ typeRepr.clear();
+ }
+ else if (typeIdentifier.type == typeRepr)
+ {
+ pushCharsIn(ostream, ' ', extraSpaces);
+ typeRepr = "\n" +
+ duplicateChar(' ', extraSpaces + 1) + "type: " + typeRepr;
+ }
+ ostream << typeRepr;
+ }
+ ostream << "\n";
+ typeRepr.clear();
+ }
+}
\ No newline at end of file
diff --git a/src/pdic/PDISerializer.hpp b/src/pdic/PDISerializer.hpp
new file mode 100644
index 0000000..defeda1
--- /dev/null
+++ b/src/pdic/PDISerializer.hpp
@@ -0,0 +1,50 @@
+/*
+ * File: PDISerializer.hpp
+ * Project: PDIC
+ * File Created: Wednesday, 21st July 2021 11:55:12 am
+ * Author: kbarre (kevin.barre@epitech.eu)
+ * -----
+ * Last Modified: Thursday, 22nd July 2021 12:57:51 am
+ * Modified By: kbarre (kevin.barre@epitech.eu>)
+ * -----
+ * Licenses: EUPL
+ * -----
+ * Copyright 2021 - 2021 neudinger
+ */
+
+#if !defined(PDI_SERIALIZER)
+#define PDI_SERIALIZER
+#include "PDITools.hpp"
+
+void DescribeStructs(std::ostringstream &ostream,
+ const PDI::StructMap &structIdentifiers,
+ const std::size_t extraSpaces = 1);
+
+void DescribeStruct(std::ostringstream &ostream,
+ const PDI::StructAttr &structIdentifier,
+ const PDI::StructMap &structIdentifiers,
+ const std::size_t extraSpaces = 1);
+
+void DescribeTypes(std::ostringstream &ostream,
+ const PDI::TypeMap &typeIdentifiers,
+ const PDI::StructMap &structIdentifiers,
+ const std::size_t extraSpaces = 1);
+
+inline void pushCharsIn(std::ostringstream &ostream,
+ const char &c,
+ const std::size_t &nb = 1) noexcept
+{
+ for (size_t i = 0; i < nb; i++)
+ ostream << c;
+}
+
+inline std::string duplicateChar(const char &c,
+ const std::size_t &nb = 1) noexcept
+{
+ std::ostringstream stream;
+ for (size_t i = 0; i < nb; i++)
+ stream << c;
+ return stream.str();
+}
+
+#endif // PDI_SERIALIZER
diff --git a/src/pdic/PDITools.cpp b/src/pdic/PDITools.cpp
new file mode 100644
index 0000000..09b5b49
--- /dev/null
+++ b/src/pdic/PDITools.cpp
@@ -0,0 +1,217 @@
+/*
+ * File: PDITools.cpp
+ * Project: PDIC
+ * File Created: Wednesday, 12th May 2021 3:23:04 pm
+ * Author: kbarre (kevin.barre@epitech.eu)
+ * -----
+ * Last Modified: Thursday, 22nd July 2021 12:58:00 am
+ * Modified By: kbarre (kevin.barre@epitech.eu>)
+ * -----
+ * Licenses: EUPL
+ * -----
+ * Copyright 2021 - 2021 neudinger
+ */
+
+#include "PDITools.hpp"
+
+namespace PDI
+{
+ static inline bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }
+ // trim from start (in place)
+ static inline std::string <rim(std::string &str)
+ {
+ str.erase(str.begin(),
+ std::find_if(
+ str.begin(), str.end(),
+ [](const uint8_t &ch) -> bool
+ {
+ return !std::isspace(ch);
+ }));
+ return str;
+ }
+
+ // trim from end (in place)
+ static inline std::string &rtrim(std::string &str)
+ {
+ str.erase(std::find_if(
+ str.rbegin(), str.rend(),
+ [](const uint8_t &ch) -> bool
+ {
+ return !std::isspace(ch);
+ })
+ .base(),
+ str.end());
+ return str;
+ }
+
+ // trim from both ends (in place)
+ static inline std::string &trim(std::string &str)
+ {
+ return rtrim(ltrim(str));
+ }
+
+ std::string &clean(std::string &str)
+ {
+ trim(str);
+ std::string::iterator new_end(std::unique(str.begin(), str.end(), BothAreSpaces));
+ str.erase(new_end, str.end());
+ return str;
+ }
+
+ void split(const std::string &str,
+ std::vector &out,
+ const char &delim)
+ {
+ size_t start;
+ size_t end = 0;
+ while ((start = str.find_first_not_of(delim, end)) != std::string::npos)
+ {
+ end = str.find(delim, start);
+ out.push_back(str.substr(start, end - start));
+ }
+ }
+
+ uint8_t charLen(const std::string &declstring, const char &elem)
+ {
+ if (declstring.find(elem) != std::string::npos)
+ return (declstring.find_last_of(elem) - declstring.find_first_of(elem) + 1);
+ return 0;
+ }
+
+ // Extract all values between [] and [][]...[] and add to container
+ void extractBetweens(const std::string &str,
+ std::vector &container,
+ const std::string delims)
+ {
+ assert(delims.length() == 2 ? true : false);
+ std::size_t side_left, side_right = 0;
+ while ((side_left = str.find(delims[0], side_right)) != std::string::npos)
+ {
+ side_right = str.find(delims[1], side_left);
+ container.push_back(str.substr(side_left + 1, (side_right - (side_left + 1))));
+ }
+ }
+
+ void describePointer(const TypeAttr &typeIdentifier,
+ uint8_t &starsNbr,
+ const std::string &typeRepr,
+ std::ostringstream &ostream)
+ {
+ ostream << " { type: pointer, subtype: ";
+ if (--starsNbr)
+ describePointer(typeIdentifier, starsNbr, typeRepr, ostream);
+ else
+ ostream << typeRepr;
+ ostream << " }";
+ }
+
+ void describePointer(const TypeAttr &typeIdentifier,
+ std::string &typeRepr)
+ {
+ uint8_t starsNbr;
+ std::ostringstream ostream;
+ if (__builtin_sub_overflow(typeIdentifier.starsNbr, typeIdentifier.pragma.arraySizes.size(), &starsNbr))
+ {
+ llvm::errs() << "cannot describe Pointer of"
+ << typeIdentifier.type
+ << " " << typeIdentifier.name << " \n";
+ return;
+ }
+ ostream << " { type: pointer, subtype: ";
+ if (--starsNbr)
+ describePointer(typeIdentifier, starsNbr, typeRepr, ostream);
+ else
+ ostream << typeRepr;
+ if (typeIdentifier.offset)
+ ostream << ", offset: " << typeIdentifier.offset;
+ ostream << " }";
+ typeRepr = ostream.str();
+ }
+
+ void describeArray(const std::vector &arrays,
+ std::string &typeRepr,
+ const uint64_t offset)
+ {
+ std::ostringstream ostream;
+ const std::size_t arrayLengh = arrays.size();
+
+ ostream << " { type: array, subtype: "
+ << typeRepr
+ << ", size: " << (arrayLengh > 1 ? "[" : "");
+
+ std::copy(arrays.cbegin(), arrays.cend() - 1,
+ std::ostream_iterator(ostream, ", "));
+ ostream << arrays.back() << (arrayLengh > 1 ? "]" : "");
+ if (offset)
+ ostream << ", offset: " << offset;
+ ostream << " }";
+
+ typeRepr = ostream.str();
+ }
+
+ void describePragmaArray(const TypeAttr &typeIdentifier,
+ std::string &typeRepr)
+ {
+ describeArray(typeIdentifier.pragma.arraySizes, typeRepr, typeIdentifier.offset);
+ }
+
+ std::map
+ stringToMap(const std::string &str)
+ {
+ std::map pragmaParamsMap;
+ std::vector pragmaParamsList;
+ std::vector pragmaParamsVect;
+ split(str, pragmaParamsList, ';');
+ for (const auto &pragma : pragmaParamsList)
+ {
+ split(pragma, pragmaParamsVect, ':');
+ if (pragmaParamsVect.size() == 2)
+ pragmaParamsMap[pragmaParamsVect[0]] = pragmaParamsVect[1];
+ pragmaParamsVect.clear();
+ }
+ return pragmaParamsMap;
+ }
+
+ void PragmaIdentifiers::load(const std::string &attributes)
+ {
+ auto annotAttr = stringToMap(attributes);
+ this->type = wrapMap(annotAttr).get(/* key= */ "type",
+ /* default_val= */ this->type);
+ extractBetweens(annotAttr["size"], /* &container */ this->arraySizes);
+ }
+
+ const bool Switch::isRaised(const std::ostringstream &stringStream,
+ const clang::SourceLocation &sourceLocation)
+ {
+ if (stringStream.str() == "\"on")
+ {
+ this->isOffRaised = false;
+ this->isOnRaised = true;
+ this->pdiOnLoc = sourceLocation;
+ }
+ else if (stringStream.str() == "\"off")
+ {
+ this->isOffRaised = true;
+ this->pdiOffLoc = sourceLocation;
+ }
+ else
+ return false;
+ return true;
+ }
+
+}
+
+const std::string get_file_contents(const char *filename)
+{
+ std::string contents;
+ std::FILE *fp = std::fopen(filename, "r");
+ if (fp)
+ {
+ std::fseek(fp, SEEK_SET, SEEK_END);
+ contents.resize(std::ftell(fp));
+ std::rewind(fp);
+ std::fread(&contents[0], 1, contents.size(), fp);
+ std::fclose(fp);
+ }
+ return (contents);
+}
\ No newline at end of file
diff --git a/src/pdic/PDITools.hpp b/src/pdic/PDITools.hpp
new file mode 100644
index 0000000..fc34700
--- /dev/null
+++ b/src/pdic/PDITools.hpp
@@ -0,0 +1,162 @@
+/*
+ * File: PDITools.hpp
+ * Project: PDIC
+ * File Created: Wednesday, 12th May 2021 3:23:04 pm
+ * Author: kbarre (kevin.barre@epitech.eu)
+ * -----
+ * Last Modified: Thursday, 22nd July 2021 12:58:12 am
+ * Modified By: kbarre (kevin.barre@epitech.eu>)
+ * -----
+ * Licenses: EUPL
+ * -----
+ * Copyright 2021 - 2021 neudinger
+ */
+
+#if !defined(PDI_TOOLS)
+#define PDI_TOOLS
+
+#include
+#include