Add mkfsdata.py
This commit is contained in:
parent
1f928b2338
commit
e9d20bd611
183
tools/mkfsdata.py
Executable file
183
tools/mkfsdata.py
Executable file
@ -0,0 +1,183 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
tools/mkfsdata.py
|
||||
|
||||
Copyright (c) 2024 Alexey Matveev
|
||||
|
||||
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 OWNER 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.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Iterator, List, Optional, TextIO, Tuple
|
||||
|
||||
|
||||
def get_files(dirname: Path) -> Iterator[Tuple[Path, str]]:
|
||||
"""
|
||||
Generator return files in the directory dirname
|
||||
"""
|
||||
for p in dirname.glob("**/*"):
|
||||
if p.is_file():
|
||||
relative_full_path = "/" + str(p.relative_to(dirname))
|
||||
yield p, relative_full_path
|
||||
|
||||
|
||||
def conver_c_name(prefix: str, r_full_path: str) -> str:
|
||||
"""
|
||||
Convert file name to C variable name
|
||||
"""
|
||||
return "{}{}".format(prefix, r_full_path.replace(".", "_").replace("/", "_"))
|
||||
|
||||
|
||||
def write_f_data(
|
||||
fd: TextIO,
|
||||
file: Path,
|
||||
r_full_path: str,
|
||||
is_add_progmem: bool = False,
|
||||
):
|
||||
"""
|
||||
Write file as hex dump
|
||||
|
||||
Args:
|
||||
file - source file
|
||||
is_add_progmem - add PROGMEM, for AVR
|
||||
"""
|
||||
rs_name = conver_c_name("data", r_full_path)
|
||||
st_progmem = "PROGMEM " if is_add_progmem else ""
|
||||
fd.write(
|
||||
f"static const unsigned char {rs_name}[] {st_progmem}=\n"
|
||||
"{\n"
|
||||
f" /* {r_full_path} */\n\n"
|
||||
)
|
||||
|
||||
# write file name
|
||||
result = " "
|
||||
for ch in r_full_path:
|
||||
result += "0x{0:02x}, ".format(ord(ch))
|
||||
result += "0x00,"
|
||||
fd.write(result)
|
||||
|
||||
# write file content
|
||||
with open(file, "rb") as f_data:
|
||||
for j, ch in enumerate(iter(lambda: f_data.read(1), b"")):
|
||||
if j % 10 == 0:
|
||||
fd.write("\n")
|
||||
fd.write(" ")
|
||||
fd.write("0x{0:02x}, ".format(ch[0]))
|
||||
fd.write("\n")
|
||||
|
||||
# End
|
||||
fd.write("};\n")
|
||||
|
||||
|
||||
def write_s_data(
|
||||
fd: TextIO,
|
||||
r_full_path: str,
|
||||
prev_file: Optional[str],
|
||||
is_replace_to_root: bool = False,
|
||||
):
|
||||
"""
|
||||
Write struct httpd_fsdata_file
|
||||
"""
|
||||
if is_replace_to_root:
|
||||
st_name = "g_httpdfs_root"
|
||||
else:
|
||||
st_name = conver_c_name("file", r_full_path)
|
||||
|
||||
if prev_file is None:
|
||||
st_prev_name = "NULL"
|
||||
else:
|
||||
st_prev_name = conver_c_name("file", prev_file)
|
||||
rs_name = conver_c_name("data", r_full_path)
|
||||
n_len = len(r_full_path) + 1
|
||||
fd.write(
|
||||
f"const struct httpd_fsdata_file {st_name}[] =\n"
|
||||
" {{"
|
||||
f"{st_prev_name}, {rs_name}, {rs_name} + {n_len}, "
|
||||
f"sizeof({rs_name}) - {n_len}"
|
||||
"}};\n\n"
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
||||
logger = logging.getLogger()
|
||||
|
||||
args = parser().parse_args()
|
||||
|
||||
# Get files
|
||||
files: List[Tuple[Path, str]] = []
|
||||
for file, r_full_path in get_files(args.dirname):
|
||||
logger.info(f"Adding file {r_full_path}")
|
||||
files.append((file, r_full_path))
|
||||
|
||||
with args.out.open("w") as fd:
|
||||
# write header
|
||||
fd.write(
|
||||
'#include "netutils/httpd.h"\n'
|
||||
"\n"
|
||||
"#ifndef NULL\n"
|
||||
" #define NULL 0\n"
|
||||
"#endif\n\n"
|
||||
)
|
||||
|
||||
# write content
|
||||
for file, r_full_path in files:
|
||||
write_f_data(fd, file, r_full_path, args.add_progmem)
|
||||
fd.write("\n") # Add empty line beetween files
|
||||
|
||||
# write list of files
|
||||
prev_file = None
|
||||
for j, (file, r_full_path) in enumerate(files):
|
||||
write_s_data(
|
||||
fd=fd,
|
||||
r_full_path=r_full_path,
|
||||
prev_file=prev_file,
|
||||
is_replace_to_root=j == len(files) - 1,
|
||||
)
|
||||
prev_file = r_full_path
|
||||
|
||||
# end
|
||||
fd.write(f"const int g_httpd_numfiles = {len(files)};\n")
|
||||
|
||||
|
||||
def parser() -> argparse.ArgumentParser:
|
||||
"""Create parser"""
|
||||
parser = argparse.ArgumentParser(description="Create C file with data for httpd")
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--dirname",
|
||||
default="httpd-fs",
|
||||
type=Path,
|
||||
help="Directory with files to add",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--out",
|
||||
default="httpd_fsdata.c",
|
||||
type=Path,
|
||||
help="Output C file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--add-progmem",
|
||||
action="store_true",
|
||||
help="Add PROGMEM to data",
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user