BigWhoop/public_header.py

376 lines
No EOL
21 KiB
Python

#*================================================================================================*#
#| |#
#| /$$$$$$$ /$$ /$$ /$$ /$$ |#
#| | $$__ $$|__/ | $$ /$ | $$| $$ |#
#| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |#
#| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ |#
#| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ |#
#| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ |#
#| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ |#
#| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ |#
#| /$$ \ $$ | $$ |#
#| | $$$$$$/ | $$ |#
#| \______/ |__/ |#
#| |#
#| DESCRIPTION: |#
#| ------------ |#
#| |#
#| This file describes python script used to assemble the public header file for |#
#| the BigWhoop compression library. |#
#| |#
#| -------------------------------------------------------------------------------------------- |#
#| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart |#
#| |#
#| Redistribution and use in source and binary forms, with or without modification, are |#
#| permitted provided that the following conditions are met: |#
#| |#
#| (1) Redistributions of source code must retain the above copyright notice, this list of |#
#| conditions and the following disclaimer. |#
#| |#
#| (2) Redistributions in binary form must reproduce the above copyright notice, this list |#
#| of conditions and the following disclaimer in the documentation and/or other |#
#| materials provided with the distribution. |#
#| |#
#| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS |#
#| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |#
#| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |#
#| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |#
#| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |#
#| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |#
#| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |#
#| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |#
#| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |#
#| |#
#*================================================================================================*#
#**************************************************************************************************#
#| _ _ _ ___ ____ ____ ___ |#
#| | |\/| |__] | | |__/ | |#
#| | | | | |__| | \ | |#
#| |#
#**************************************************************************************************#
from argparse import ArgumentParser
from math import ceil, floor
from pathlib import Path
import os
import re
import sys
#-------------------------#
# DEFINE CONSTANTS: #
#-------------------------#
tab = " "
text_width = 100
deliminator = tab + "/*" + (text_width - 4 - len(tab)) * "=" + "*/\n"
ubox = tab + "/" + (text_width - 2 - len(tab)) * "*" + "\\\n"
lbox = tab + "\\" + (text_width - 2 - len(tab)) * "*" + "/\n"
sbox = "||"
#----------------------------------------------------------#
# Setup the argument parser for the public header script #
# and parse for the user defined OpenMP and Precision arg. #
#----------------------------------------------------------#
parser = ArgumentParser(description='Public Header Assembly Script')
parser.add_argument('-OMP', dest='OpenMP', action='store_const',
const=True, default=False,
help='OpenMP Parallelization')
parser.add_argument('-Single', dest='SinglePrecision', action='store_const',
const=True, default=False,
help='Compilation using Single Precision Encoder')
args = parser.parse_args()
#----------------------------------------------------------#
# Setup the paths to the source and destination. #
#----------------------------------------------------------#
current_path = Path().absolute()
source = current_path.joinpath('include/library/private')
destination = current_path.joinpath('include/library/public')
if os.path.isdir(destination) == False:
os.mkdir(destination)
header_files = [f for f in os.listdir(source) if os.path.isfile(os.path.join(source, f))]
header_files.remove('prim_types_double.h')
header_files.remove('prim_types_single.h')
print(header_files)
#----------------------------------------------------------#
# Create the I/O stream and write the bwc file header. #
#----------------------------------------------------------#
public_header = open(destination.joinpath('bwc.h'), 'w+')
public_header.write("/*================================================================================================*\\\n"
"|| ||\n"
"|| /$$$$$$$ /$$ /$$ /$$ /$$ ||\n"
"|| | $$__ $$|__/ | $$ /$ | $$| $$ ||\n"
"|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ ||\n"
"|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ ||\n"
"|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ ||\n"
"|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ ||\n"
"|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ ||\n"
"|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ ||\n"
"|| /$$ \ $$ | $$ ||\n"
"|| | $$$$$$/ | $$ ||\n"
"|| \______/ |__/ ||\n"
"|| ||\n"
"|| -------------------------------------------------------------------------------------------- ||\n"
"|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart ||\n"
"|| ||\n"
"|| Redistribution and use in source and binary forms, with or without modification, are ||\n"
"|| permitted provided that the following conditions are met: ||\n"
"|| ||\n"
"|| (1) Redistributions of source code must retain the above copyright notice, this list of ||\n"
"|| conditions and the following disclaimer. ||\n"
"|| ||\n"
"|| (2) Redistributions in binary form must reproduce the above copyright notice, this list ||\n"
"|| of conditions and the following disclaimer in the documentation and/or other ||\n"
"|| materials provided with the distribution. ||\n"
"|| ||\n"
"|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS ||\n"
"|| OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ||\n"
"|| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ||\n"
"|| COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ||\n"
"|| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ||\n"
"|| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ||\n"
"|| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR ||\n"
"|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, ||\n"
"|| EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ||\n"
"|| ||\n"
"\*================================================================================================*/\n"
"#ifndef BWC_H\n"
"#define BWC_H\n")
#----------------------------------------------------------#
# Generate the necessary includes for the bwc.h file. #
#----------------------------------------------------------#
title_length = 31
lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2)
rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2)
public_header.write(ubox + tab + sbox + lspaces * " " + "_ _ _ ____ _ _ _ ___ ____" + rspaces * " " + sbox + "\n" +
tab + sbox + lspaces * " " + "| |\ | | | | | | \ |___" + rspaces * " " + sbox + "\n" +
tab + sbox + lspaces * " " + "| | \| |___ |___ |__| |__/ |___" + rspaces * " " + sbox + "\n" +
tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox)
public_header.write(tab + "#include <stdio.h>\n" + tab + "#include <stdint.h>\n\n")
#----------------------------------------------------------#
# Ingest primitive type definitions from the corresponding #
# header files according to the user specified precision. #
#----------------------------------------------------------#
title_length = 62
lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2)
rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2)
public_header.write(ubox + tab + sbox + lspaces * " " + "___ ____ _ _ _ _ ___ _ _ _ ____ ___ _ _ ___ ____ ____" + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "|__] |__/ | |\/| | | | | | |___ | \_/ |__] |___ [__ " + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "| | \ | | | | | | \/ |___ | | | |___ ___]" + rspaces * " " + "||\n" +
tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox)
if(args.SinglePrecision == True):
file = "prim_types_single.h"
else:
file = "prim_types_double.h"
print_flag = False
with open(source.joinpath(file)) as f:
for line in f:
if("/*" in line and print_flag == 1):
break
if("typedef" in line or print_flag == 1):
print_flag = True
public_header.write(line)
f.close
#----------------------------------------------------------#
# Ingest Macros with 'BWC_' prefix from all header files. #
#----------------------------------------------------------#
title_length = 29
lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2)
rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2)
public_header.write(ubox + tab + sbox + lspaces * " " + "_ _ ____ ____ ____ ____ ____" + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "|\/| |__| | |__/ | | [__ " + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "| | | | |___ | \ |__| ___]" + rspaces * " " + "||\n" +
tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox)
with open(source.joinpath(file)) as f:
for line in f:
if("#define" in line):
if("MAXIMUM_NO_PASSES" in line or
"PREC_BIT" in line):
if("//" in line):
public_header.write((line.split('/', 1)[0]).rstrip() + '\n')
else:
public_header.write(line)
f.close
printFlg = False
buff = ""
brktCnt = 0
for file in header_files:
with open(source.joinpath(file)) as f:
for line in f:
if("BWC_" in line):
if("ifndef" in line):
next(f)
elif("#define" in line and line[len(line) - len(line.lstrip())] != "/"):
while True:
if("//" in line):
buff = buff + (line.split('/', 1)[0]).rstrip() + '\n'
else:
buff = buff + line
if("\\" not in line):
public_header.write(buff+"\n")
buff = ""
break
line = next(f)
f.close
public_header.write("\n")
#----------------------------------------------------------#
# Ingest enums with 'bwc_' prefix from all header files #
# excluding prim_types_****.h. #
#----------------------------------------------------------#
title_length = 42
lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2)
rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2)
public_header.write(ubox + tab + sbox + lspaces * " " + "____ ____ _ _ ____ ___ ____ _ _ ___ ____" + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "| | | |\ | [__ | |__| |\ | | [__ " + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "|___ |__| | \| ___] | | | | \| | ___]" + rspaces * " " + "||\n" +
tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox)
delimFlg = False
buff = ""
for file in header_files:
with open(source.joinpath(file)) as f:
for line in f:
if("typedef enum" in line):
while True:
buff = buff + (line.split('/', 1)[0]).rstrip() + '\n'
if("}" in line and ";" in line):
if("bwc_" in line):
if(delimFlg == True):
public_header.write(deliminator)
public_header.write(buff)
delimFlg = True
buff = ""
break
line = next(f)
f.close
#----------------------------------------------------------#
# Ingest derived types with 'bwc_' prefix from all header #
# files excluding prim_types_****.h. #
#----------------------------------------------------------#
title_length = 64
lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2)
rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2)
public_header.write("\n")
public_header.write(ubox + tab + sbox + lspaces * " " + "___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____" + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "| \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ " + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "|__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___]" + rspaces * " " + "||\n" +
tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox)
printFlg = False
delimFlg = False
preProcFlg = False
buff = ""
brktCnt = 0
for file in header_files:
with open(source.joinpath(file)) as f:
for line in f:
if("typedef struct" in line or
"typedef union" in line):
if("bwc_" in line):
printFlg = True
while True:
buff = buff + (line.split('/', 1)[0]).rstrip() + '\n'
if("{" in line):
brktCnt = brktCnt + 1
if("}" in line):
brktCnt = brktCnt - 1
if(brktCnt == 0):
if("bwc_" in line):
printFlg = True
break
line = next(f)
if (printFlg == True):
if(delimFlg == True):
public_header.write(deliminator)
public_header.write(buff)
delimFlg = True
buff = ""
f.close
#----------------------------------------------------------#
# Ingest public functions with 'bwc_' prefix from all #
# header files excluding prim_types_****.h. #
#----------------------------------------------------------#
title_length = 70
lspaces = ceil((text_width - 2*len(sbox) - title_length - len(tab))/2)
rspaces = floor((text_width - 2*len(sbox) - title_length - len(tab))/2)
public_header.write("\n" + ubox + tab + sbox + lspaces * " " + "___ _ _ ___ _ _ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____" + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "|__] | | |__] | | | |___ | | |\ | | | | | | |\ | [__ " + rspaces * " " + "||\n" +
tab + sbox + lspaces * " " + "| |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___]" + rspaces * " " + "||\n" +
tab + sbox + (text_width - 2*len(sbox) - len(tab)) * " " + "||\n" + lbox)
public_header.write(tab + "#ifdef __cplusplus\n" +
tab + tab + "extern \"C\" {\n" +
tab + "#endif\n\n")
files = os.listdir("include/library/private")
printFlg = False
ltab = 0
tmp = ""
buff = ""
for file in files:
with open(source.joinpath(file)) as f:
for line in f:
if("#if defined" in line):
line = next(f)
if("(" in line):
tmp = line[0:line.index('(')].strip()
tmp = tmp[tmp.rfind(' '):-1]
else:
tmp = ""
if("bwc_" in tmp and "!" not in line and "#if" not in line):
if("/*" in buff or "*/" in buff or "//" in buff):
buff = ""
if(print_flag == True):
buff = deliminator + buff
else:
print_flag = True
while True:
buff = buff + line[ltab:len(line)]
if(");" in line):
break
line = next(f)
public_header.write(buff)
buff = line
f.close
public_header.write("\n" + tab + "#ifdef __cplusplus\n" +
tab + tab + "}\n" +
tab + "#endif\n")
public_header.write("#endif")
public_header.close