1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-24 16:55:36 +03:00

Adding RP2350 SDK and target framework (#13988)

* Adding RP2350 SDK and target framework

* Spacing

* Removing board definitions
This commit is contained in:
J Blackman 2024-10-23 10:02:48 +11:00 committed by GitHub
parent 462cb05930
commit 2dd6f95aad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
576 changed files with 435012 additions and 0 deletions

View file

@ -0,0 +1,46 @@
/**
* \defgroup pico_lwip pico_lwip
* \brief Integration/wrapper libraries for <a href="https://savannah.nongnu.org/projects/lwip/lwIP">lwIP</a>
* the documentation for which is <a href="https://www.nongnu.org/lwip/2_1_x/index.html">here</a>.
*
* The main \c \b pico_lwip library itself aggregates the lwIP RAW API: \c \b pico_lwip_core, \c \b pico_lwip_core4, \c \b pico_lwip_core6, \c \b pico_lwip_api, \c \b pico_lwip_netif, \c \b pico_lwip_sixlowpan and \c \b pico_lwip_ppp.
*
* If you wish to run in NO_SYS=1 mode, then you can link \c \b pico_lwip along with \ref pico_lwip_nosys.
*
* If you wish to run in NO_SYS=0 mode, then you can link \c \b pico_lwip with (for instance) \ref pico_lwip_freertos,
* and also link in pico_lwip_api for the additional blocking/thread-safe APIs.
*
* Additionally you must link in \ref pico_lwip_arch unless you provide your own compiler bindings for lwIP.
*
* Additional individual pieces of lwIP functionality are available à la cart, by linking any of the libraries below.
*
* The following libraries are provided that contain exactly the equivalent lwIP functionality groups:
*
* * \c \b pico_lwip_core -
* * \c \b pico_lwip_core4 -
* * \c \b pico_lwip_core6 -
* * \c \b pico_lwip_netif -
* * \c \b pico_lwip_sixlowpan -
* * \c \b pico_lwip_ppp -
* * \c \b pico_lwip_api -
*
* The following libraries are provided that contain exactly the equivalent lwIP application support:
*
* * \c \b pico_lwip_snmp -
* * \c \b pico_lwip_http -
* * \c \b pico_lwip_makefsdata -
* * \c \b pico_lwip_iperf -
* * \c \b pico_lwip_smtp -
* * \c \b pico_lwip_sntp -
* * \c \b pico_lwip_mdns -
* * \c \b pico_lwip_netbios -
* * \c \b pico_lwip_tftp -
* * \c \b pico_lwip_mbedtls -
* * \c \b pico_lwip_mqtt -
*
*/
/** \defgroup pico_lwip_arch pico_lwip_arch
* \ingroup pico_lwip
* \brief lwIP compiler adapters. This is not included by default in \c \b pico_lwip in case you wish to implement your own.
*/

View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
*
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#ifndef __CC_H__
#define __CC_H__
#include <sys/time.h>
#ifndef PICO_LWIP_CUSTOM_LOCK_TCPIP_CORE
#define PICO_LWIP_CUSTOM_LOCK_TCPIP_CORE 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if NO_SYS
// todo really we should just not allow SYS_LIGHTWEIGHT_PROT for nosys mode (it doesn't do anything anyway)
typedef int sys_prot_t;
#elif PICO_LWIP_CUSTOM_LOCK_TCPIP_CORE
void pico_lwip_custom_lock_tcpip_core(void);
void pico_lwip_custom_unlock_tcpip_core(void);
#define LOCK_TCPIP_CORE() pico_lwip_custom_lock_tcpip_core()
#define UNLOCK_TCPIP_CORE() pico_lwip_custom_unlock_tcpip_core()
#endif
/* define compiler specific symbols */
#if defined (__ICCARM__)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#define PACK_STRUCT_USE_INCLUDES
#elif defined (__CC_ARM)
#define PACK_STRUCT_BEGIN __packed
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#elif defined (__GNUC__)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#elif defined (__TASKING__)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_STRUCT
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x
#endif
#ifndef LWIP_PLATFORM_ASSERT
#include "pico.h"
#define LWIP_PLATFORM_ASSERT(x) panic(x)
#endif
#ifndef LWIP_RAND
#include "pico/rand.h"
// Use the pico_rand library which goes to reasonable lengths to try to provide good entropy
#define LWIP_RAND() get_rand_32()
#endif
#ifdef __cplusplus
}
#endif
#endif /* __CC_H__ */

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_LWIP_FREERTOS_H
#define _PICO_LWIP_FREERTOS_H
#include "pico.h"
#include "pico/async_context.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file pico/lwip_freertos.h
* \defgroup pico_lwip_freertos pico_lwip_freertos
* \ingroup pico_lwip
* \brief Glue library for integration lwIP in \c NO_SYS=0 mode with the SDK
*
* Simple \c init and \c deinit are all that is required to hook up lwIP (with full blocking API support) via an \ref async_context instance
*/
/*! \brief Initializes lwIP (NO_SYS=0 mode) support support for FreeRTOS using the provided async_context
* \ingroup pico_lwip_freertos
*
* If the initialization succeeds, \ref lwip_freertos_deinit() can be called to shutdown lwIP support
*
* \param context the async_context instance that provides the abstraction for handling asynchronous work. Note in general
* this would be an \ref async_context_freertos instance, though it doesn't have to be.
*
* \return true if the initialization succeeded
*/
bool lwip_freertos_init(async_context_t *context);
/*! \brief De-initialize lwIP (NO_SYS=0 mode) support for FreeRTOS
* \ingroup pico_lwip_freertos
*
* Note that since lwIP may only be initialized once, and doesn't itself provide a shutdown mechanism, lwIP
* itself may still consume resources.
*
* It is however safe to call \ref lwip_freertos_init again later.
*
* \param context the async_context the lwip_freertos support was added to via \ref lwip_freertos_init
*/
void lwip_freertos_deinit(async_context_t *context);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_LWIP_NOSYS_H
#define _PICO_LWIP_NOSYS_H
#include "pico.h"
#include "pico/async_context.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file pico/lwip_nosys.h
* \defgroup pico_lwip_nosys pico_lwip_nosys
* \ingroup pico_lwip
* \brief Glue library for integration lwIP in \c NO_SYS=1 mode with the SDK
*
* Simple \c init and \c deinit are all that is required to hook up lwIP via an \ref async_context instance.
*/
/*! \brief Initializes lwIP (NO_SYS=1 mode) support support using the provided async_context
* \ingroup pico_lwip_nosys
*
* If the initialization succeeds, \ref lwip_nosys_deinit() can be called to shutdown lwIP support
*
* \param context the async_context instance that provides the abstraction for handling asynchronous work.
* \return true if the initialization succeeded
*/
bool lwip_nosys_init(async_context_t *context);
/*! \brief De-initialize lwIP (NO_SYS=1 mode) support
* \ingroup pico_lwip_nosys
*
* Note that since lwIP may only be initialized once, and doesn't itself provide a shutdown mechanism, lwIP
* itself may still consume resources
*
* It is however safe to call \ref lwip_nosys_init again later.
*
* \param context the async_context the lwip_nosys support was added to via \ref lwip_nosys_init
*/
void lwip_nosys_deinit(async_context_t *context);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,181 @@
load("@pico-sdk//bazel:defs.bzl", "incompatible_with_config")
package(default_visibility = ["//visibility:public"])
# Some of the LWIP sys_arch.h and the lwip headers depend circularly on one
# another. Include them all in the same target.
cc_library(
name = "pico_lwip_headers",
hdrs = glob(["**/*.h"]),
includes = [
"contrib/ports/freertos/include/arch",
"src/include",
],
visibility = ["//visibility:private"],
deps = [
"@pico-sdk//bazel/config:PICO_LWIP_CONFIG",
"@pico-sdk//src/rp2_common/pico_lwip:pico_lwip_config",
],
)
cc_library(
name = "pico_lwip_core",
srcs = glob(["src/core/*.c"]),
target_compatible_with = incompatible_with_config(
"@pico-sdk//bazel/constraint:pico_lwip_config_unset",
),
deps = [
":pico_lwip_headers",
] + select({
"@pico-sdk//bazel/constraint:pico_freertos_unset": [],
"//conditions:default": [
":pico_lwip_contrib_freertos",
],
}),
)
cc_library(
name = "pico_lwip_core4",
srcs = glob(["src/core/ipv4/*.c"]),
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_core6",
srcs = glob(["src/core/ipv6/*.c"]),
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_api",
srcs = glob(["src/api/*.c"]),
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_netif",
srcs = [
"src/netif/bridgeif.c",
"src/netif/bridgeif_fdb.c",
"src/netif/ethernet.c",
"src/netif/slipif.c",
],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_sixlowpan",
srcs = [
"src/netif/lowpan6.c",
"src/netif/lowpan6_ble.c",
"src/netif/lowpan6_common.c",
"src/netif/zepif.c",
],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_ppp",
srcs = glob(["src/netif/ppp/*/*.c"]),
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_snmp",
srcs = glob(
["src/apps/snmp/*.c"],
# mbedtls is provided through pico_lwip_mbedtls.
exclude = ["*mbedtls.c"],
),
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_http",
srcs = glob(["src/apps/http/*.c"]),
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_makefsdata",
srcs = ["src/apps/http/makefsdata/makefsdata.c"],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_iperf",
srcs = ["src/apps/lwiperf/lwiperf.c"],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_smtp",
srcs = ["src/apps/smtp/smtp.c"],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_sntp",
srcs = ["src/apps/sntp/sntp.c"],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_mdns",
srcs = glob(["src/apps/mdns/*.c"]),
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_netbios",
srcs = ["src/apps/netbiosns/netbiosns.c"],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_tftp",
srcs = ["src/apps/tftp/tftp.c"],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_mbedtls",
srcs = [
"src/apps/altcp_tls/altcp_tls_mbedtls.c",
"src/apps/altcp_tls/altcp_tls_mbedtls_mem.c",
"src/apps/snmp/snmpv3_mbedtls.c",
],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip_mqttt",
srcs = ["src/apps/mqtt/mqtt.c"],
deps = [":pico_lwip_core"],
)
cc_library(
name = "pico_lwip",
deps = [
":pico_lwip_api",
":pico_lwip_core",
":pico_lwip_core4",
":pico_lwip_core6",
":pico_lwip_netif",
":pico_lwip_ppp",
":pico_lwip_sixlowpan",
],
)
cc_library(
name = "pico_lwip_contrib_freertos",
srcs = ["contrib/ports/freertos/sys_arch.c"],
includes = ["contrib/ports/freertos/include"],
target_compatible_with = incompatible_with_config(
"@pico-sdk//bazel/constraint:pico_freertos_unset",
),
deps = [
":pico_lwip_headers",
"@pico-sdk//bazel/config:PICO_FREERTOS_LIB",
],
)

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/async_context.h"
#include "pico/time.h"
#include "lwip/tcpip.h"
#include "lwip/timeouts.h"
#include "FreeRTOS.h"
#include "semphr.h"
#if NO_SYS
#error lwip_freertos_async_context_bindings requires NO_SYS=0
#endif
static async_context_t * volatile lwip_context;
// lwIP tcpip_task cannot be shutdown, so we block it when we are de-initialized.
static SemaphoreHandle_t tcpip_task_blocker;
static void tcpip_init_done(void *param) {
xSemaphoreGive((SemaphoreHandle_t)param);
}
bool lwip_freertos_init(async_context_t *context) {
assert(!lwip_context);
lwip_context = context;
static bool done_lwip_init;
if (!done_lwip_init) {
done_lwip_init = true;
SemaphoreHandle_t init_sem = xSemaphoreCreateBinary();
tcpip_task_blocker = xSemaphoreCreateBinary();
tcpip_init(tcpip_init_done, init_sem);
xSemaphoreTake(init_sem, portMAX_DELAY);
vSemaphoreDelete(init_sem);
} else {
xSemaphoreGive(tcpip_task_blocker);
}
return true;
}
static uint32_t clear_lwip_context(__unused void *param) {
lwip_context = NULL;
return 0;
}
void lwip_freertos_deinit(__unused async_context_t *context) {
// clear the lwip context under lock as lwIP may still be running in tcpip_task
async_context_execute_sync(context, clear_lwip_context, NULL);
}
void pico_lwip_custom_lock_tcpip_core(void) {
while (!lwip_context) {
xSemaphoreTake(tcpip_task_blocker, portMAX_DELAY);
}
async_context_acquire_lock_blocking(lwip_context);
}
void pico_lwip_custom_unlock_tcpip_core(void) {
async_context_release_lock(lwip_context);
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/async_context.h"
#include <lwip/init.h>
#include "lwip/timeouts.h"
static void update_next_timeout(async_context_t *context, async_when_pending_worker_t *worker);
static void lwip_timeout_reached(async_context_t *context, async_at_time_worker_t *worker);
static async_when_pending_worker_t always_pending_update_timeout_worker = {
.do_work = update_next_timeout
};
static async_at_time_worker_t lwip_timeout_worker = {
.do_work = lwip_timeout_reached,
};
static void lwip_timeout_reached(__unused async_context_t *context, __unused async_at_time_worker_t *worker) {
assert(worker == &lwip_timeout_worker);
sys_check_timeouts();
}
static void update_next_timeout(async_context_t *context, async_when_pending_worker_t *worker) {
assert(worker == &always_pending_update_timeout_worker);
// we want to run on every execution of the helper to re-reflect any changes
// to the underlying lwIP timers which may have happened in the interim
// (note that worker will be called on every outermost exit of the async_context
// lock, and lwIP timers should not be modified whilst not holding the lock.
worker->work_pending = true;
uint32_t sleep_ms = sys_timeouts_sleeptime();
if (sleep_ms == SYS_TIMEOUTS_SLEEPTIME_INFINITE) {
lwip_timeout_worker.next_time = at_the_end_of_time;
} else {
lwip_timeout_worker.next_time = make_timeout_time_ms(sleep_ms);
}
async_context_add_at_time_worker(context, &lwip_timeout_worker);
}
bool lwip_nosys_init(async_context_t *context) {
static bool done_lwip_init;
if (!done_lwip_init) {
lwip_init();
done_lwip_init = true;
}
// we want the worker to be called on every async helper run (starting with the next)
always_pending_update_timeout_worker.work_pending = true;
async_context_add_when_pending_worker(context, &always_pending_update_timeout_worker);
return true;
}
void lwip_nosys_deinit(async_context_t *context) {
async_context_remove_at_time_worker(context, &lwip_timeout_worker);
async_context_remove_when_pending_worker(context, &always_pending_update_timeout_worker);
}
#if NO_SYS
/* lwip has provision for using a mutex, when applicable */
sys_prot_t sys_arch_protect(void) {
return 0;
}
void sys_arch_unprotect(__unused sys_prot_t pval) {
}
/* lwip needs a millisecond time source, and the TinyUSB board support code has one available */
uint32_t sys_now(void) {
return to_ms_since_boot(get_absolute_time());
}
#endif

View file

@ -0,0 +1,159 @@
#!/usr/bin/env python3
import argparse
import mimetypes
from pathlib import Path
import re
response_types = {
200: "HTTP/1.0 200 OK",
400: "HTTP/1.0 400 Bad Request",
404: "HTTP/1.0 404 File not found",
501: "HTTP/1.0 501 Not Implemented",
}
PAYLOAD_ALIGNMENT = 4
HTTPD_SERVER_AGENT = "lwIP/2.2.0d (http://savannah.nongnu.org/projects/lwip)"
LWIP_HTTPD_SSI_EXTENSIONS = [".shtml", ".shtm", ".ssi", ".xml", ".json"]
def process_file(input_dir, file):
results = []
# Check content type
content_type, _ = mimetypes.guess_type(file)
if content_type is None:
content_type = "application/octet-stream"
# file name
data = f"/{file.relative_to(input_dir)}\x00"
comment = f"\"/{file.relative_to(input_dir)}\" ({len(data)} chars)"
while(len(data) % PAYLOAD_ALIGNMENT != 0):
data += "\x00"
results.append({'data': bytes(data, "utf-8"), 'comment': comment});
# Header
response_type = 200
for response_id in response_types:
if file.name.startswith(f"{response_id}."):
response_type = response_id
break
data = f"{response_types[response_type]}\r\n"
comment = f"\"{response_types[response_type]}\" ({len(data)} chars)"
results.append({'data': bytes(data, "utf-8"), 'comment': comment});
# user agent
data = f"Server: {HTTPD_SERVER_AGENT}\r\n"
comment = f"\"Server: {HTTPD_SERVER_AGENT}\" ({len(data)} chars)"
results.append({'data': bytes(data, "utf-8"), 'comment': comment});
if file.suffix not in LWIP_HTTPD_SSI_EXTENSIONS:
# content length
file_size = file.stat().st_size
data = f"Content-Length: {file_size}\r\n"
comment = f"\"Content-Length: {file_size}\" ({len(data)} chars)"
results.append({'data': bytes(data, "utf-8"), 'comment': comment});
# content type
data = f"Content-Type: {content_type}\r\n\r\n"
comment = f"\"Content-Type: {content_type}\" ({len(data)} chars)"
results.append({'data': bytes(data, "utf-8"), 'comment': comment});
# file contents
data = file.read_bytes()
comment = f"raw file data ({len(data)} bytes)"
results.append({'data': data, 'comment': comment});
return results;
def process_file_list(fd, input):
data = []
fd.write("#include \"lwip/apps/fs.h\"\n")
fd.write("\n")
# generate the page contents
input_dir = None
for name in input:
file = Path(name)
if not file.is_file():
raise RuntimeError(f"File not found: {name}")
# Take the input directory from the first file
if input_dir is None:
input_dir = file.parent
results = process_file(input_dir, file)
# make a variable name
var_name = str(file.relative_to(input_dir))
var_name = re.sub(r"\W+", "_", var_name, flags=re.ASCII)
# Add a suffix if the variable name is used already
if any(d["data_var"] == f"data_{var_name}" for d in data):
var_name += f"_{len(data)}"
data_var = f"data_{var_name}"
file_var = f"file_{var_name}"
# variable containing the raw data
fd.write(f"static const unsigned char {data_var}[] = {{\n")
for entry in results:
fd.write(f"\n /* {entry['comment']} */\n")
byte_count = 0;
for b in entry['data']:
if byte_count % 16 == 0:
fd.write(" ")
byte_count += 1
fd.write(f"0x{b:02x},")
if byte_count % 16 == 0:
fd.write("\n")
if byte_count % 16 != 0:
fd.write("\n")
fd.write(f"}};\n\n")
# set the flags
flags = "FS_FILE_FLAGS_HEADER_INCLUDED"
if file.suffix not in LWIP_HTTPD_SSI_EXTENSIONS:
flags += " | FS_FILE_FLAGS_HEADER_PERSISTENT"
else:
flags += " | FS_FILE_FLAGS_SSI"
# add variable details to the list
data.append({'data_var': data_var, 'file_var': file_var, 'name_size': len(results[0]['data']), 'flags': flags})
# generate the page details
last_var = "NULL"
for entry in data:
fd.write(f"const struct fsdata_file {entry['file_var']}[] = {{{{\n")
fd.write(f" {last_var},\n")
fd.write(f" {entry['data_var']},\n")
fd.write(f" {entry['data_var']} + {entry['name_size']},\n")
fd.write(f" sizeof({entry['data_var']}) - {entry['name_size']},\n")
fd.write(f" {entry['flags']},\n")
fd.write(f"}}}};\n\n")
last_var = entry['file_var']
fd.write(f"#define FS_ROOT {last_var}\n")
fd.write(f"#define FS_NUMFILES {len(data)}\n")
def run_tool():
parser = argparse.ArgumentParser(prog="makefsdata.py", description="Generates a source file for the lwip httpd server")
parser.add_argument(
"-i",
"--input",
help="input files to add as http content",
required=True,
nargs='+'
)
parser.add_argument(
"-o",
"--output",
help="name of the source file to generate",
required=True,
)
args = parser.parse_args()
print(args.input)
mimetypes.init()
for ext in [".shtml", ".shtm", ".ssi"]:
mimetypes.add_type("text/html", ext)
with open(args.output, "w") as fd:
process_file_list(fd, args.input)
if __name__ == "__main__":
run_tool()