Compare commits
No commits in common. "main" and "v1.0.0" have entirely different histories.
45 changed files with 474 additions and 1412 deletions
40
Makefile
40
Makefile
|
|
@ -1,48 +1,32 @@
|
||||||
NAME = c-md
|
NAME = c-md
|
||||||
VERSION = 2.0.0
|
VERSION = 1.0.0
|
||||||
.DEFAULT_GOAL := all
|
|
||||||
|
|
||||||
TEST_BIN= c-md.test
|
TEST_BIN= c-md.test
|
||||||
CMD = ./$(NAME)
|
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
MAKEFLAGS += --no-print-directory
|
MAKEFLAGS += --no-print-directory
|
||||||
include sources.mk
|
include sources.mk
|
||||||
|
|
||||||
CC = clang
|
CC = clang
|
||||||
CPPFLAGS = -std=c99
|
CPPFLAGS = -std=c99 -I includes
|
||||||
CFLAGS = -Wall -Wextra -Werror -pipe
|
CFLAGS = -Wall -Wextra -Werror -pipe
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
TEST_LDFLAGS = -lcriterion
|
TEST_LDFLAGS = -lcriterion
|
||||||
|
|
||||||
BUILD_DIR = .build
|
|
||||||
OBJ_DIR = $(BUILD_DIR)/objs
|
|
||||||
MAP_DIR = $(BUILD_DIR)/maps
|
|
||||||
|
|
||||||
GEN_SRCS = $(MD_SRCS:$(SRC_DIR)/%.c.md=$(BUILD_DIR)/srcs/%.c)
|
OBJ_DIR = .build
|
||||||
GEN_HDRS = $(MD_HDRS:$(INC_DIR)/%.h.md=$(BUILD_DIR)/$(INC_DIR)/%.h)
|
|
||||||
|
|
||||||
OBJS = $(GEN_SRCS:$(BUILD_DIR)/srcs/%.c=$(OBJ_DIR)/%.o)
|
OBJS = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
|
||||||
DEPS = $(OBJS:.o=.d)
|
DEPS = $(OBJS:.o=.d)
|
||||||
|
|
||||||
.SECONDARY: $(GEN_SRCS) $(GEN_HDRS)
|
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: $(NAME)
|
all: $(NAME)
|
||||||
|
|
||||||
$(NAME): $(GEN_HDRS) $(OBJS)
|
$(NAME): $(OBJS)
|
||||||
$(CC) $(LDFLAGS) -o $@ $(OBJS)
|
$(CC) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
$(BUILD_DIR)/srcs/%.c: $(SRC_DIR)/%.c.md
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||||
@mkdir -p $(dir $@) $(dir $(MAP_DIR)/$*.map)
|
|
||||||
$(CMD) -i $< -o $@ -m $(MAP_DIR)/$*.map
|
|
||||||
|
|
||||||
$(BUILD_DIR)/$(INC_DIR)/%.h: $(INC_DIR)/%.h.md
|
|
||||||
@mkdir -p $(dir $@) $(dir $(MAP_DIR)/$*.h.map)
|
|
||||||
$(CMD) -e c -i $< -o $@ -m $(MAP_DIR)/$*.h.map
|
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(BUILD_DIR)/srcs/%.c $(GEN_HDRS)
|
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) -I $(BUILD_DIR)/$(INC_DIR) -MMD -MP -c $< -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@
|
||||||
|
|
||||||
-include $(DEPS)
|
-include $(DEPS)
|
||||||
|
|
||||||
|
|
@ -53,12 +37,13 @@ test: $(TEST_BIN)
|
||||||
|
|
||||||
$(TEST_BIN): $(TESTS) $(filter-out $(OBJ_DIR)/main.o,$(OBJS))
|
$(TEST_BIN): $(TESTS) $(filter-out $(OBJ_DIR)/main.o,$(OBJS))
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
$(CC) $(CPPFLAGS) $(CFLAGS) -I $(BUILD_DIR)/$(INC_DIR) $(TEST_LDFLAGS) $^ -o $@
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(TEST_LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(RM) -r $(BUILD_DIR)
|
$(RM) -r $(OBJ_DIR)
|
||||||
|
|
||||||
.PHONY: fclean
|
.PHONY: fclean
|
||||||
fclean: clean
|
fclean: clean
|
||||||
|
|
@ -68,3 +53,4 @@ fclean: clean
|
||||||
.PHONY: re
|
.PHONY: re
|
||||||
re: fclean
|
re: fclean
|
||||||
$(MAKE) all
|
$(MAKE) all
|
||||||
|
|
||||||
|
|
|
||||||
31
README.md
31
README.md
|
|
@ -106,35 +106,6 @@ For file `main.c.md` with `-e c`:
|
||||||
|
|
||||||
Multiple matching code blocks are concatenated with a blank line separator.
|
Multiple matching code blocks are concatenated with a blank line separator.
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
c-md is self-hosted
|
|
||||||
([dogfooding](https://en.wikipedia.org/wiki/Self-hosting_(compilers))). The
|
|
||||||
source code is written in `.c.md` format and requires c-md itself to build.
|
|
||||||
|
|
||||||
### First Build (Bootstrap)
|
|
||||||
|
|
||||||
After cloning or after `make fclean`, run the bootstrap script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./bootstrap.sh
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
The bootstrap script builds c-md by traversing major version tags,
|
|
||||||
starting from v1.0.0 (plain C sources) up to the current version.
|
|
||||||
|
|
||||||
### Regular Build
|
|
||||||
|
|
||||||
Once c-md is available:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make # build from .c.md sources
|
|
||||||
make clean # remove build artifacts
|
|
||||||
make fclean # remove everything including binary
|
|
||||||
make re # rebuild from scratch
|
|
||||||
```
|
|
||||||
|
|
||||||
## Line Mapping
|
## Line Mapping
|
||||||
|
|
||||||
The transpiler generates `.map` files that track the correspondence between
|
The transpiler generates `.map` files that track the correspondence between
|
||||||
|
|
@ -146,7 +117,7 @@ source lines (`.c.md`) and output lines (`.c`). This enables:
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
**v2.0.0** - Initial stable release self-hosted.
|
**v1.0.0** - Initial stable release
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
103
bootstrap.sh
103
bootstrap.sh
|
|
@ -1,103 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
# bootstrap.sh - Build c-md by traversing major version tags
|
|
||||||
#
|
|
||||||
# This script builds c-md from scratch by going through each major version
|
|
||||||
# tag in order. Each version is built using the binary from the previous
|
|
||||||
# version, starting from v1.0.0 which uses plain C sources.
|
|
||||||
#
|
|
||||||
# Use this script after a fresh clone or after 'make fclean'.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
TMP_BIN="/tmp/c-md-bootstrap-$$"
|
|
||||||
CURRENT=""
|
|
||||||
STASH_NEEDED=0
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
# Restore original branch if we switched
|
|
||||||
if [ -n "$CURRENT" ]; then
|
|
||||||
CURRENT_BRANCH=$(git branch --show-current)
|
|
||||||
if [ "$CURRENT_BRANCH" != "$CURRENT" ]; then
|
|
||||||
echo "Restoring original branch..."
|
|
||||||
git switch "$CURRENT" --quiet 2>/dev/null || git checkout "$CURRENT" --quiet 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Restore stashed changes
|
|
||||||
if [ "$STASH_NEEDED" -eq 1 ]; then
|
|
||||||
echo "Restoring stashed changes..."
|
|
||||||
git stash pop --quiet 2>/dev/null || echo "Warning: Could not restore stashed changes"
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f "$TMP_BIN"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap cleanup EXIT INT TERM
|
|
||||||
|
|
||||||
get_highest_major_tags() {
|
|
||||||
git tag -l 'v*' \
|
|
||||||
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
|
|
||||||
| sort -V \
|
|
||||||
| awk -F. '
|
|
||||||
{
|
|
||||||
m=substr($1, 2)+0;
|
|
||||||
tag = $0
|
|
||||||
tags[m] = tag # Overwrite; since input is sorted, last wins (highest)
|
|
||||||
} END {
|
|
||||||
for (m in tags) print tags[m]
|
|
||||||
}' \
|
|
||||||
| sort -V
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Bootstrapping c-md..."
|
|
||||||
|
|
||||||
CURRENT=$(git branch --show-current)
|
|
||||||
if [ -n "$(git status --porcelain)" ]; then
|
|
||||||
echo "Stashing local changes..."
|
|
||||||
git stash --include-untracked --quiet
|
|
||||||
STASH_NEEDED=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
TAGS=$(get_highest_major_tags)
|
|
||||||
|
|
||||||
if [ -z "$TAGS" ]; then
|
|
||||||
echo "No version tags found. Building current version from C sources..."
|
|
||||||
make --quiet
|
|
||||||
echo "Bootstrap complete. Binary ready at ./c-md"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Found major versions: $(echo $TAGS | tr '\n' ' ')"
|
|
||||||
|
|
||||||
for TAG in $TAGS; do
|
|
||||||
echo "Building $TAG..."
|
|
||||||
git switch --detach "$TAG" --quiet
|
|
||||||
|
|
||||||
if [ -f "$TMP_BIN" ]; then
|
|
||||||
cp "$TMP_BIN" ./c-md
|
|
||||||
fi
|
|
||||||
|
|
||||||
make --quiet
|
|
||||||
cp c-md "$TMP_BIN"
|
|
||||||
make fclean --quiet
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Restoring current branch..."
|
|
||||||
git switch "$CURRENT" --quiet
|
|
||||||
|
|
||||||
if [ "$STASH_NEEDED" -eq 1 ]; then
|
|
||||||
echo "Restoring stashed changes..."
|
|
||||||
git stash pop --quiet
|
|
||||||
STASH_NEEDED=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Building current version..."
|
|
||||||
cp "$TMP_BIN" ./c-md
|
|
||||||
make --quiet
|
|
||||||
cp c-md "$TMP_BIN"
|
|
||||||
make fclean --quiet
|
|
||||||
mv "$TMP_BIN" ./c-md
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Bootstrap complete. Binary ready at ./c-md"
|
|
||||||
echo "Run 'make' to rebuild from sources."
|
|
||||||
21
includes/cli.h
Normal file
21
includes/cli.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef CLI_H
|
||||||
|
# define CLI_H
|
||||||
|
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct s_args
|
||||||
|
{
|
||||||
|
const char *ext;
|
||||||
|
const char *input;
|
||||||
|
const char *output;
|
||||||
|
const char *map_path;
|
||||||
|
uint8_t show_help;
|
||||||
|
} t_args;
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
cli_parse(t_args *args, int32_t argc, char **argv);
|
||||||
|
|
||||||
|
void
|
||||||
|
cli_print_help(const char *progname);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
# cli.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef CLI_H
|
|
||||||
# define CLI_H
|
|
||||||
|
|
||||||
# include <stdint.h>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Types
|
|
||||||
|
|
||||||
### `t_args`
|
|
||||||
Struct to hold command-line arguments.
|
|
||||||
```c
|
|
||||||
typedef struct s_args
|
|
||||||
{
|
|
||||||
const char *ext;
|
|
||||||
const char *input;
|
|
||||||
const char *output;
|
|
||||||
const char *map_path;
|
|
||||||
uint8_t show_help;
|
|
||||||
} t_args;
|
|
||||||
```
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### [`cli_parse`](/srcs/cli/cli.c.md#cli_parse)
|
|
||||||
Parses command-line arguments and populates the t_args structure.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
cli_parse(t_args *args, int32_t argc, char **argv);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`cli_print_help`](/srcs/cli/help.c.md#cli_printhelp)
|
|
||||||
Prints help information for the command-line interface.
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
cli_print_help(const char *progname);
|
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
19
includes/internal/map_internal.h
Normal file
19
includes/internal/map_internal.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef MAP_INTERNAL_H
|
||||||
|
# define MAP_INTERNAL_H
|
||||||
|
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
# include "map.h"
|
||||||
|
|
||||||
|
# define MAP_INIT_CAP 16
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
map_grow(t_map *map);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
write_header(FILE *f, const char *source, const char *target);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
write_ranges(FILE *f, t_map *map);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
# map_internal.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef MAP_INTERNAL_H
|
|
||||||
# define MAP_INTERNAL_H
|
|
||||||
|
|
||||||
# include <stdio.h>
|
|
||||||
# include <stdint.h>
|
|
||||||
# include "map.h"
|
|
||||||
# define MAP_INIT_CAP 16 // Default initial capacity for the map
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### [`map_grow`](/srcs/map/core.c.md#map_grow)
|
|
||||||
Grows the map's capacity when needed.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
map_grow(t_map *map);
|
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
37
includes/internal/transpile_internal.h
Normal file
37
includes/internal/transpile_internal.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef TRANSPILE_INTERNAL_H
|
||||||
|
# define TRANSPILE_INTERNAL_H
|
||||||
|
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
# include "map.h"
|
||||||
|
|
||||||
|
typedef struct s_state
|
||||||
|
{
|
||||||
|
FILE *in;
|
||||||
|
FILE *out;
|
||||||
|
const char *ext;
|
||||||
|
t_map *map;
|
||||||
|
uint32_t src_line;
|
||||||
|
uint32_t dst_line;
|
||||||
|
uint32_t block_src_start;
|
||||||
|
uint32_t block_dst_start;
|
||||||
|
uint8_t in_block;
|
||||||
|
uint8_t first_block;
|
||||||
|
} t_state;
|
||||||
|
|
||||||
|
void
|
||||||
|
state_init(t_state *s, FILE *in, FILE *out, const char *ext, t_map *map);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
process_line(t_state *s, char *line);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
handle_fence_open(t_state *s, char *line);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
handle_fence_close(t_state *s);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
handle_code_line(t_state *s, char *line);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
# transpile_internal.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef TRANSPILE_INTERNAL_H
|
|
||||||
# define TRANSPILE_INTERNAL_H
|
|
||||||
|
|
||||||
# include <stdio.h>
|
|
||||||
# include <stdint.h>
|
|
||||||
# include "map.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Types
|
|
||||||
|
|
||||||
### `t_state`
|
|
||||||
Struct to hold the state of the transpilation process.
|
|
||||||
```c
|
|
||||||
typedef struct s_state
|
|
||||||
{
|
|
||||||
FILE *in;
|
|
||||||
FILE *out;
|
|
||||||
const char *ext;
|
|
||||||
t_map *map;
|
|
||||||
uint32_t src_line;
|
|
||||||
uint32_t dst_line;
|
|
||||||
uint32_t block_src_start;
|
|
||||||
uint32_t block_dst_start;
|
|
||||||
uint8_t in_block;
|
|
||||||
uint8_t first_block;
|
|
||||||
} t_state;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### [`state_init`](/srcs/transpile/state.c.md#state_init)
|
|
||||||
Initializes the transpilation state.
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
state_init(t_state *s, FILE *in, FILE *out, const char *ext, t_map *map);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`handle_fence_open`](/srcs/transpile/fence.c.md#handle_fence_open)
|
|
||||||
Handles the opening of a code fence in the input.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
handle_fence_open(t_state *s, char *line);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`handle_fence_close`](/srcs/transpile/fence.c.md#handle_fence_open)
|
|
||||||
Handles the closing of a code fence in the input.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
handle_fence_close(t_state *s);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`handle_code_line`](/srcs/transpile/code.c.md#handle_code_line)
|
|
||||||
Handles a regular line of code in the input.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
handle_code_line(t_state *s, char *line);
|
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
19
includes/io.h
Normal file
19
includes/io.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef IO_H
|
||||||
|
# define IO_H
|
||||||
|
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct s_io
|
||||||
|
{
|
||||||
|
FILE *in;
|
||||||
|
FILE *out;
|
||||||
|
} t_io;
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
io_open(t_io *io, const char *input_path, const char *output_path);
|
||||||
|
|
||||||
|
void
|
||||||
|
io_close(t_io *io);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
# io.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef IO_H
|
|
||||||
# define IO_H
|
|
||||||
|
|
||||||
# include <stdio.h>
|
|
||||||
# include <stdint.h>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Types
|
|
||||||
```c
|
|
||||||
typedef struct s_io
|
|
||||||
{
|
|
||||||
FILE *in;
|
|
||||||
FILE *out;
|
|
||||||
} t_io;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### [`io_open`](/srcs/io/streams.c.md#io_open)
|
|
||||||
Opens input and output streams based on provided file paths.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
io_open(t_io *io, const char *input_path, const char *output_path);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`io_close`](/srcs/io/streams.c.md#io_close)
|
|
||||||
Closes the input and output streams if they are not stdin or stdout.
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
io_close(t_io *io);
|
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
35
includes/map.h
Normal file
35
includes/map.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef MAP_H
|
||||||
|
# define MAP_H
|
||||||
|
|
||||||
|
# include <stddef.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct s_range
|
||||||
|
{
|
||||||
|
uint32_t src_start;
|
||||||
|
uint32_t src_end;
|
||||||
|
uint32_t dst_start;
|
||||||
|
uint32_t dst_end;
|
||||||
|
} t_range;
|
||||||
|
|
||||||
|
typedef struct s_map
|
||||||
|
{
|
||||||
|
t_range *ranges;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} t_map;
|
||||||
|
|
||||||
|
void
|
||||||
|
map_init(t_map *map);
|
||||||
|
|
||||||
|
void
|
||||||
|
map_add(t_map *map, uint32_t src_start, uint32_t src_end,
|
||||||
|
uint32_t dst_start, uint32_t dst_end);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
map_write(t_map *map, const char *path, const char *source, const char *target);
|
||||||
|
|
||||||
|
void
|
||||||
|
map_free(t_map *map);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
# map.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef MAP_H
|
|
||||||
# define MAP_H
|
|
||||||
|
|
||||||
# include <stddef.h>
|
|
||||||
# include <stdint.h>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Types
|
|
||||||
|
|
||||||
### `t_range`
|
|
||||||
A structure representing a mapping range between source and destination
|
|
||||||
addresses.
|
|
||||||
```c
|
|
||||||
typedef struct s_range
|
|
||||||
{
|
|
||||||
uint32_t src_start;
|
|
||||||
uint32_t src_end;
|
|
||||||
uint32_t dst_start;
|
|
||||||
uint32_t dst_end;
|
|
||||||
} t_range;
|
|
||||||
```
|
|
||||||
|
|
||||||
### `t_map`
|
|
||||||
A structure representing a collection of mapping ranges.
|
|
||||||
```c
|
|
||||||
typedef struct s_map
|
|
||||||
{
|
|
||||||
t_range *ranges;
|
|
||||||
size_t count;
|
|
||||||
size_t capacity;
|
|
||||||
} t_map;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### [`map_init`](/srcs/map/core.c.md#map_init)
|
|
||||||
Initialize a mapping structure.
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
map_init(t_map *map);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`map_add`](/srcs/map/core.c.md#map_add)
|
|
||||||
Add a new mapping range to the mapping structure.
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
map_add(t_map *map, uint32_t src_start, uint32_t src_end,
|
|
||||||
uint32_t dst_start, uint32_t dst_end);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`map_write`](/srcs/map/io.c.md#map_write)
|
|
||||||
Write the mapping information to a file.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
map_write(t_map *map, const char *path, const char *source, const char *target);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`map_free`](/srcs/map/core.c.md#map_free)
|
|
||||||
Free the resources associated with the mapping structure.
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
map_free(t_map *map);
|
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
|
|
@ -1,23 +1,11 @@
|
||||||
# transpile.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef TRANSPILE_H
|
#ifndef TRANSPILE_H
|
||||||
# define TRANSPILE_H
|
# define TRANSPILE_H
|
||||||
|
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include "map.h"
|
# include "map.h"
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
### [`transpile`](/srcs/transpile/core.c.md#transpile)
|
|
||||||
```c
|
|
||||||
int8_t
|
int8_t
|
||||||
transpile(FILE *in, FILE *out, const char *ext, t_map *map);
|
transpile(FILE *in, FILE *out, const char *ext, t_map *map);
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
#endif
|
||||||
```
|
|
||||||
22
includes/utils.h
Normal file
22
includes/utils.h
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef UTILS_H
|
||||||
|
# define UTILS_H
|
||||||
|
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
|
||||||
|
char *
|
||||||
|
read_line(FILE *f);
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
starts_with(const char *str, const char *prefix);
|
||||||
|
|
||||||
|
char *
|
||||||
|
extract_fence_ext(const char *fence);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
extract_file_ext(const char *path);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
infer_ext_from_filename(const char *path);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
# utils.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef UTILS_H
|
|
||||||
# define UTILS_H
|
|
||||||
|
|
||||||
# include <stdint.h>
|
|
||||||
# include <stdio.h>
|
|
||||||
```
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### [`read_line`](/srcs/utils/io/read_line.c.md#read_line)
|
|
||||||
Get a line from a file.
|
|
||||||
```c
|
|
||||||
char *
|
|
||||||
read_line(FILE *f);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`starts_with`](/srcs/utils/string/starts_with.c.md#starts_with)
|
|
||||||
Check if a string starts with a given prefix.
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
starts_with(const char *str, const char *prefix);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`extract_fence_ext`](/srcs/utils/string/extract_fence_ext.c.md#extract_fence_ext)
|
|
||||||
Extract the extension from a fence string.
|
|
||||||
```c
|
|
||||||
char *
|
|
||||||
extract_fence_ext(const char *fence);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`extract_file_ext`](/srcs/utils/string/extract_file_ext.c.md#extract_file_ext)
|
|
||||||
Extract the file extension from a file path.
|
|
||||||
```c
|
|
||||||
const char *
|
|
||||||
extract_file_ext(const char *path);
|
|
||||||
```
|
|
||||||
|
|
||||||
### [`infer_ext_from_filename`](/srcs/utils/string/infer_ext_from_filename.c.md#infer_ext_from_filename)
|
|
||||||
Infer the file extension from a filename.
|
|
||||||
```c
|
|
||||||
const char *
|
|
||||||
infer_ext_from_filename(const char *path);
|
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
10
includes/validator.h
Normal file
10
includes/validator.h
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef VALIDATOR_H
|
||||||
|
# define VALIDATOR_H
|
||||||
|
|
||||||
|
# include <stdint.h>
|
||||||
|
# include "cli.h"
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
validator_validate_args(t_args *args);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
# validator.h
|
|
||||||
|
|
||||||
## Include Guard
|
|
||||||
```c
|
|
||||||
#ifndef VALIDATOR_H
|
|
||||||
# define VALIDATOR_H
|
|
||||||
# include <stdint.h>
|
|
||||||
# include "cli.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
### [`validator_validate_args`](/srcs/validator/validator.c.md#validator_validate_args)
|
|
||||||
This function checks and validates the content of the `t_args` structure,
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
validator_validate_args(t_args *args);
|
|
||||||
```
|
|
||||||
|
|
||||||
## End Guard
|
|
||||||
```c
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
42
sources.mk
42
sources.mk
|
|
@ -1,31 +1,21 @@
|
||||||
|
|
||||||
SRC_DIR = srcs
|
SRC_DIR = srcs
|
||||||
MD_SRCS = $(SRC_DIR)/main.c.md \
|
SRCS = $(SRC_DIR)/main.c \
|
||||||
$(SRC_DIR)/io/streams.c.md \
|
$(SRC_DIR)/io/streams.c \
|
||||||
$(SRC_DIR)/utils/io/read_line.c.md \
|
$(SRC_DIR)/utils/io/read_line.c \
|
||||||
$(SRC_DIR)/utils/string/starts_with.c.md \
|
$(SRC_DIR)/utils/string/starts_with.c \
|
||||||
$(SRC_DIR)/utils/string/extract_fence_ext.c.md \
|
$(SRC_DIR)/utils/string/extract_fence_ext.c \
|
||||||
$(SRC_DIR)/utils/string/extract_file_ext.c.md \
|
$(SRC_DIR)/utils/string/extract_file_ext.c \
|
||||||
$(SRC_DIR)/utils/string/infer_ext_from_filename.c.md \
|
$(SRC_DIR)/utils/string/infer_ext_from_filename.c \
|
||||||
$(SRC_DIR)/transpile/state.c.md \
|
$(SRC_DIR)/transpile/state.c \
|
||||||
$(SRC_DIR)/transpile/fence.c.md \
|
$(SRC_DIR)/transpile/fence.c \
|
||||||
$(SRC_DIR)/transpile/code.c.md \
|
$(SRC_DIR)/transpile/code.c \
|
||||||
$(SRC_DIR)/transpile/core.c.md \
|
$(SRC_DIR)/transpile/core.c \
|
||||||
$(SRC_DIR)/map/core.c.md \
|
$(SRC_DIR)/map/core.c \
|
||||||
$(SRC_DIR)/map/io.c.md \
|
$(SRC_DIR)/map/io.c \
|
||||||
$(SRC_DIR)/cli/cli.c.md \
|
$(SRC_DIR)/cli/cli.c \
|
||||||
$(SRC_DIR)/cli/help.c.md \
|
$(SRC_DIR)/cli/help.c \
|
||||||
$(SRC_DIR)/validator/validator.c.md
|
$(SRC_DIR)/validator/validator.c
|
||||||
|
|
||||||
INC_DIR = includes
|
|
||||||
MD_HDRS = $(INC_DIR)/cli.h.md \
|
|
||||||
$(INC_DIR)/io.h.md \
|
|
||||||
$(INC_DIR)/map.h.md \
|
|
||||||
$(INC_DIR)/transpile.h.md \
|
|
||||||
$(INC_DIR)/utils.h.md \
|
|
||||||
$(INC_DIR)/validator.h.md \
|
|
||||||
$(INC_DIR)/internal/map_internal.h.md \
|
|
||||||
$(INC_DIR)/internal/transpile_internal.h.md
|
|
||||||
|
|
||||||
TESTS_DIR = tests
|
TESTS_DIR = tests
|
||||||
TESTS = $(TESTS_DIR)/test_integration.c \
|
TESTS = $(TESTS_DIR)/test_integration.c \
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,17 @@
|
||||||
# cli.c
|
|
||||||
The command-line interface (CLI) parser for the c-md transpiler.
|
|
||||||
Handles parsing command-line arguments and populating the t_args structure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
### Includes
|
|
||||||
```c
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Structs and Type Definitions
|
|
||||||
|
|
||||||
Function pointer type for option handlers.
|
|
||||||
```c
|
|
||||||
typedef void (*t_handler)(t_args *, const char *);
|
typedef void (*t_handler)(t_args *, const char *);
|
||||||
```
|
|
||||||
|
|
||||||
Struct to map short options to their handlers.
|
|
||||||
```c
|
|
||||||
typedef struct s_opt
|
typedef struct s_opt
|
||||||
{
|
{
|
||||||
int8_t short_opt;
|
int8_t short_opt;
|
||||||
t_handler handler;
|
t_handler handler;
|
||||||
} t_opt;
|
} t_opt;
|
||||||
```
|
|
||||||
|
|
||||||
### Forward Declarations
|
|
||||||
```c
|
|
||||||
static void handle_help(t_args *args, const char *value);
|
static void handle_help(t_args *args, const char *value);
|
||||||
static void handle_ext(t_args *args, const char *value);
|
static void handle_ext(t_args *args, const char *value);
|
||||||
static void handle_input(t_args *args, const char *value);
|
static void handle_input(t_args *args, const char *value);
|
||||||
|
|
@ -41,12 +19,7 @@ static void handle_output(t_args *args, const char *value);
|
||||||
static void handle_map(t_args *args, const char *value);
|
static void handle_map(t_args *args, const char *value);
|
||||||
static t_handler find_handler(int8_t opt);
|
static t_handler find_handler(int8_t opt);
|
||||||
static void init_args(t_args *args);
|
static void init_args(t_args *args);
|
||||||
```
|
|
||||||
|
|
||||||
### Static Variables
|
|
||||||
|
|
||||||
Initialize the mapping of options to their handlers.
|
|
||||||
```c
|
|
||||||
static const t_opt g_opts[] = {
|
static const t_opt g_opts[] = {
|
||||||
{'h', handle_help},
|
{'h', handle_help},
|
||||||
{'e', handle_ext},
|
{'e', handle_ext},
|
||||||
|
|
@ -55,36 +28,15 @@ static const t_opt g_opts[] = {
|
||||||
{'m', handle_map},
|
{'m', handle_map},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
};
|
};
|
||||||
```
|
|
||||||
|
|
||||||
Initialize the long options for getopt_long.
|
|
||||||
See `man getopt` for details.
|
|
||||||
```c
|
|
||||||
static struct option g_long_opts[] = {
|
static struct option g_long_opts[] = {
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
{"ext", required_argument, NULL, 'e'},
|
{"ext", required_argument, NULL, 'e'},
|
||||||
{"input", required_argument, NULL, 'i'},
|
{"input", required_argument, NULL, 'i'},
|
||||||
{"output", required_argument, NULL, 'o'},
|
|
||||||
{"map", required_argument, NULL, 'm'},
|
{"map", required_argument, NULL, 'm'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
```
|
|
||||||
|
|
||||||
### Function Definitions
|
|
||||||
|
|
||||||
### `cli_parse`
|
|
||||||
Parses command-line arguments and populates the t_args structure.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `args`: Pointer to the t_args structure to populate.
|
|
||||||
- `argc`: Argument count.
|
|
||||||
- `argv`: argv.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Returns 0 on success, or -1 on failure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
int8_t
|
||||||
cli_parse(t_args *args, int32_t argc, char **argv)
|
cli_parse(t_args *args, int32_t argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
@ -101,16 +53,7 @@ cli_parse(t_args *args, int32_t argc, char **argv)
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `init_args`
|
|
||||||
Initializes the t_args structure with default values.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `args`: Pointer to the t_args structure to initialize.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
static void
|
static void
|
||||||
init_args(t_args *args)
|
init_args(t_args *args)
|
||||||
{
|
{
|
||||||
|
|
@ -120,19 +63,7 @@ init_args(t_args *args)
|
||||||
args->map_path = NULL;
|
args->map_path = NULL;
|
||||||
args->show_help = 0;
|
args->show_help = 0;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `find_handler`
|
|
||||||
Finds the handler function for a given option.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `opt`: The short option character.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Returns the corresponding handler function, or NULL if not found.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
static t_handler
|
static t_handler
|
||||||
find_handler(int8_t opt)
|
find_handler(int8_t opt)
|
||||||
{
|
{
|
||||||
|
|
@ -147,55 +78,34 @@ find_handler(int8_t opt)
|
||||||
}
|
}
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `handle_help`
|
|
||||||
Sets the show_help flag in t_args.
|
|
||||||
```c
|
|
||||||
static void
|
static void
|
||||||
handle_help(t_args *args, const char *value)
|
handle_help(t_args *args, const char *value)
|
||||||
{
|
{
|
||||||
(void)value;
|
(void)value;
|
||||||
args->show_help = 1;
|
args->show_help = 1;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `handle_ext`
|
|
||||||
Sets the file extension in t_args.
|
|
||||||
```c
|
|
||||||
static void
|
static void
|
||||||
handle_ext(t_args *args, const char *value)
|
handle_ext(t_args *args, const char *value)
|
||||||
{
|
{
|
||||||
args->ext = value;
|
args->ext = value;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `handle_input`
|
|
||||||
Sets the input file path in t_args.
|
|
||||||
```c
|
|
||||||
static void
|
static void
|
||||||
handle_input(t_args *args, const char *value)
|
handle_input(t_args *args, const char *value)
|
||||||
{
|
{
|
||||||
args->input = value;
|
args->input = value;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `handle_output`
|
|
||||||
Sets the output file path in t_args.
|
|
||||||
```c
|
|
||||||
static void
|
static void
|
||||||
handle_output(t_args *args, const char *value)
|
handle_output(t_args *args, const char *value)
|
||||||
{
|
{
|
||||||
args->output = value;
|
args->output = value;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `handle_map`
|
|
||||||
Sets the mapping file path in t_args.
|
|
||||||
```c
|
|
||||||
static void
|
static void
|
||||||
handle_map(t_args *args, const char *value)
|
handle_map(t_args *args, const char *value)
|
||||||
{
|
{
|
||||||
args->map_path = value;
|
args->map_path = value;
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
@ -1,23 +1,7 @@
|
||||||
# help.c
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
```
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
### `cli_print_help`
|
|
||||||
Prints the help message for the command-line interface.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `progname`: Name of the program.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
void
|
void
|
||||||
cli_print_help(const char *progname)
|
cli_print_help(const char *progname)
|
||||||
{
|
{
|
||||||
|
|
@ -35,4 +19,3 @@ cli_print_help(const char *progname)
|
||||||
fprintf(stderr, " %s -i main.c.md -o main.c\n", progname);
|
fprintf(stderr, " %s -i main.c.md -o main.c\n", progname);
|
||||||
fprintf(stderr, " %s -e h -i file.md -o file.h -m file.map\n", progname);
|
fprintf(stderr, " %s -e h -i file.md -o file.h -m file.map\n", progname);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
32
srcs/io/streams.c
Normal file
32
srcs/io/streams.c
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
io_open(t_io *io, const char *input_path, const char *output_path)
|
||||||
|
{
|
||||||
|
io->in = (NULL != input_path) ? fopen(input_path, "r") : stdin;
|
||||||
|
if (NULL == io->in)
|
||||||
|
{
|
||||||
|
perror(input_path);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
io->out = (NULL != output_path) ? fopen(output_path, "w") : stdout;
|
||||||
|
if (NULL == io->out)
|
||||||
|
{
|
||||||
|
perror(output_path);
|
||||||
|
if (io->in != stdin)
|
||||||
|
fclose(io->in);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
io_close(t_io *io)
|
||||||
|
{
|
||||||
|
if (NULL != io->in && io->in != stdin)
|
||||||
|
fclose(io->in);
|
||||||
|
if (NULL != io->out && io->out != stdout)
|
||||||
|
fclose(io->out);
|
||||||
|
}
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
# streams.c
|
|
||||||
Funtions for handling input and output streams.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "io.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
|
|
||||||
### `io_open`
|
|
||||||
Opens input and output streams based on provided file paths.
|
|
||||||
if input_path is NULL, stdin is used.
|
|
||||||
if output_path is NULL, stdout is used.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `io`: Pointer to the t_io structure to hold the opened streams.
|
|
||||||
- `input_path`: Path to the input file, or NULL for stdin.
|
|
||||||
- `output_path`: Path to the output file, or NULL for stdout.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Returns 0 on success, or 1 on failure.
|
|
||||||
The caller is responsible for closing the streams using `io_close`.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
io_open(t_io *io, const char *input_path, const char *output_path)
|
|
||||||
{
|
|
||||||
io->in = (NULL != input_path) ? fopen(input_path, "r") : stdin;
|
|
||||||
if (NULL == io->in)
|
|
||||||
{
|
|
||||||
perror(input_path);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
io->out = (NULL != output_path) ? fopen(output_path, "w") : stdout;
|
|
||||||
if (NULL == io->out)
|
|
||||||
{
|
|
||||||
perror(output_path);
|
|
||||||
if (io->in != stdin)
|
|
||||||
fclose(io->in);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `io_close`
|
|
||||||
Closes the input and output streams if they are not stdin or stdout.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `io`: Pointer to the t_io structure containing the streams to close.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
io_close(t_io *io)
|
|
||||||
{
|
|
||||||
if (NULL != io->in && io->in != stdin)
|
|
||||||
fclose(io->in);
|
|
||||||
if (NULL != io->out && io->out != stdout)
|
|
||||||
fclose(io->out);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -1,33 +1,14 @@
|
||||||
# main.c
|
|
||||||
|
|
||||||
Entry point of the c-md transpiler.
|
|
||||||
|
|
||||||
Parse command-line arguments, validate them, and run the transpilation process.
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
#include "validator.h"
|
#include "validator.h"
|
||||||
#include "transpile.h"
|
#include "transpile.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
```
|
|
||||||
|
|
||||||
## Forward Declarations
|
|
||||||
|
|
||||||
```c
|
|
||||||
static int8_t run(t_args *args);
|
static int8_t run(t_args *args);
|
||||||
static void print_error(int8_t code, const char *progname);
|
static void print_error(int8_t code, const char *progname);
|
||||||
```
|
|
||||||
|
|
||||||
## Main Function
|
|
||||||
|
|
||||||
Program entry point: parse arguments, validate, and run transpilation.
|
|
||||||
|
|
||||||
```c
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
@ -52,17 +33,7 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
return (run(&args));
|
return (run(&args));
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
## Print Error Function
|
|
||||||
|
|
||||||
print_error: Print error messages based on validation code.
|
|
||||||
|
|
||||||
error codes:
|
|
||||||
1. Missing -e when reading from stdin
|
|
||||||
2. Missing -e when filename does not imply extension
|
|
||||||
|
|
||||||
```c
|
|
||||||
static void
|
static void
|
||||||
print_error(int8_t code, const char *progname)
|
print_error(int8_t code, const char *progname)
|
||||||
{
|
{
|
||||||
|
|
@ -72,13 +43,7 @@ print_error(int8_t code, const char *progname)
|
||||||
fprintf(stderr, "Error: -e required (cannot infer from filename)\n");
|
fprintf(stderr, "Error: -e required (cannot infer from filename)\n");
|
||||||
cli_print_help(progname);
|
cli_print_help(progname);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
## Run Function
|
|
||||||
|
|
||||||
Run the transpilation process with given arguments.
|
|
||||||
|
|
||||||
```c
|
|
||||||
static int8_t
|
static int8_t
|
||||||
run(t_args *args)
|
run(t_args *args)
|
||||||
{
|
{
|
||||||
|
|
@ -100,4 +65,3 @@ run(t_args *args)
|
||||||
io_close(&io);
|
io_close(&io);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
55
srcs/map/core.c
Normal file
55
srcs/map/core.c
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
#include "internal/map_internal.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
map_init(t_map *map)
|
||||||
|
{
|
||||||
|
map->ranges = NULL;
|
||||||
|
map->count = 0;
|
||||||
|
map->capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
map_add(t_map *map, uint32_t src_start, uint32_t src_end,
|
||||||
|
uint32_t dst_start, uint32_t dst_end)
|
||||||
|
{
|
||||||
|
t_range *range;
|
||||||
|
|
||||||
|
if (map->count >= map->capacity)
|
||||||
|
{
|
||||||
|
if (0 != map_grow(map))
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
range = &map->ranges[map->count];
|
||||||
|
range->src_start = src_start;
|
||||||
|
range->src_end = src_end;
|
||||||
|
range->dst_start = dst_start;
|
||||||
|
range->dst_end = dst_end;
|
||||||
|
map->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
map_free(t_map *map)
|
||||||
|
{
|
||||||
|
free(map->ranges);
|
||||||
|
map->ranges = NULL;
|
||||||
|
map->count = 0;
|
||||||
|
map->capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
map_grow(t_map *map)
|
||||||
|
{
|
||||||
|
size_t new_cap;
|
||||||
|
t_range *new_ranges;
|
||||||
|
|
||||||
|
new_cap = (0 == map->capacity) ? MAP_INIT_CAP : map->capacity * 2;
|
||||||
|
new_ranges = realloc(map->ranges, new_cap * sizeof(t_range));
|
||||||
|
if (NULL == new_ranges)
|
||||||
|
return (1);
|
||||||
|
map->ranges = new_ranges;
|
||||||
|
map->capacity = new_cap;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
@ -1,115 +0,0 @@
|
||||||
# core.c
|
|
||||||
Core functions of the map feature.
|
|
||||||
Handles initialization, addition, freeing, and growing of the map structure.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "map.h"
|
|
||||||
#include "internal/map_internal.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
|
|
||||||
### `map_init`
|
|
||||||
Initializes the map structure.
|
|
||||||
Every map structure must be initialized before use.
|
|
||||||
They also must be freed with `map_free` when no longer needed.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `map`: Pointer to the map structure to initialize.
|
|
||||||
|
|
||||||
##### Implementation
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
map_init(t_map *map)
|
|
||||||
{
|
|
||||||
map->ranges = NULL;
|
|
||||||
map->count = 0;
|
|
||||||
map->capacity = 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `map_add`
|
|
||||||
Adds a new range to the map structure.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `map`: Pointer to the map structure.
|
|
||||||
- `src_start`: Start of the source range.
|
|
||||||
- `src_end`: End of the source range.
|
|
||||||
- `dst_start`: Start of the destination range.
|
|
||||||
- `dst_end`: End of the destination range.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
map_add(t_map *map, uint32_t src_start, uint32_t src_end,
|
|
||||||
uint32_t dst_start, uint32_t dst_end)
|
|
||||||
{
|
|
||||||
t_range *range;
|
|
||||||
|
|
||||||
if (map->count >= map->capacity)
|
|
||||||
{
|
|
||||||
if (0 != map_grow(map))
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
range = &map->ranges[map->count];
|
|
||||||
range->src_start = src_start;
|
|
||||||
range->src_end = src_end;
|
|
||||||
range->dst_start = dst_start;
|
|
||||||
range->dst_end = dst_end;
|
|
||||||
map->count++;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `map_free`
|
|
||||||
Frees the resources allocated with the map structure.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `map`: Pointer to the map structure to free.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
map_free(t_map *map)
|
|
||||||
{
|
|
||||||
free(map->ranges);
|
|
||||||
map->ranges = NULL;
|
|
||||||
map->count = 0;
|
|
||||||
map->capacity = 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `map_grow`
|
|
||||||
Grows the capacity of the map structure.
|
|
||||||
Multiplies the current capacity by 2, or sets it to an initial value if it's
|
|
||||||
zero.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `map`: Pointer to the map structure to grow.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Returns 0 on success, or 1 on memory allocation failure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
map_grow(t_map *map)
|
|
||||||
{
|
|
||||||
size_t new_cap;
|
|
||||||
t_range *new_ranges;
|
|
||||||
|
|
||||||
new_cap = (0 == map->capacity) ? MAP_INIT_CAP : map->capacity * 2;
|
|
||||||
new_ranges = realloc(map->ranges, new_cap * sizeof(t_range));
|
|
||||||
if (NULL == new_ranges)
|
|
||||||
return (1);
|
|
||||||
map->ranges = new_ranges;
|
|
||||||
map->capacity = new_cap;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
55
srcs/map/io.c
Normal file
55
srcs/map/io.c
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
#include "internal/map_internal.h"
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
write_header(FILE *f, const char *source, const char *target)
|
||||||
|
{
|
||||||
|
if (0 > fprintf(f, "C-MD MAP v1\n"))
|
||||||
|
return (1);
|
||||||
|
if (0 > fprintf(f, "source: %s\n", source))
|
||||||
|
return (1);
|
||||||
|
if (0 > fprintf(f, "target: %s\n", target))
|
||||||
|
return (1);
|
||||||
|
if (0 > fprintf(f, "---\n"))
|
||||||
|
return (1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
write_ranges(FILE *f, t_map *map)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
t_range *r;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < map->count)
|
||||||
|
{
|
||||||
|
r = &map->ranges[i];
|
||||||
|
if (0 > fprintf(f, "%u-%u:%u-%u\n",
|
||||||
|
r->src_start, r->src_end, r->dst_start, r->dst_end))
|
||||||
|
return (1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
map_write(t_map *map, const char *path, const char *source, const char *target)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int8_t ret;
|
||||||
|
|
||||||
|
f = fopen(path, "w");
|
||||||
|
if (NULL == f)
|
||||||
|
{
|
||||||
|
perror(path);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
ret = write_header(f, source, target);
|
||||||
|
if (0 == ret)
|
||||||
|
ret = write_ranges(f, map);
|
||||||
|
fclose(f);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
117
srcs/map/io.c.md
117
srcs/map/io.c.md
|
|
@ -1,117 +0,0 @@
|
||||||
# io.c
|
|
||||||
Input/output functions for c-md mapping files.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "map.h"
|
|
||||||
#include "internal/map_internal.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Forward Declarations
|
|
||||||
```c
|
|
||||||
static int8_t write_header(FILE *f, const char *source, const char *target);
|
|
||||||
static int8_t write_ranges(FILE *f, t_map *map);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
|
|
||||||
### `map_write`
|
|
||||||
Writes a c-md mapping file to the specified path.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `map`: Pointer to the mapping structure.
|
|
||||||
- `path`: Pointer to the output file path string.
|
|
||||||
- `source`: Pointer to the source file name string.
|
|
||||||
- `target`: Pointer to the target file name string.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Return 0 on success, or 1 on failure.
|
|
||||||
|
|
||||||
##### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
map_write(t_map *map, const char *path, const char *source, const char *target)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
int8_t ret;
|
|
||||||
|
|
||||||
f = fopen(path, "w");
|
|
||||||
if (NULL == f)
|
|
||||||
{
|
|
||||||
perror(path);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
ret = write_header(f, source, target);
|
|
||||||
if (0 == ret)
|
|
||||||
ret = write_ranges(f, map);
|
|
||||||
fclose(f);
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `write_header`
|
|
||||||
Writes the header of a c-md mapping file. (v1 format)
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `f`: Pointer to the output file.
|
|
||||||
- `source`: Pointer to the source file name string.
|
|
||||||
- `target`: Pointer to the target file name string.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Return 0 on success, or 1 on failure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
write_header(FILE *f, const char *source, const char *target)
|
|
||||||
{
|
|
||||||
if (0 > fprintf(f, "C-MD MAP v1\n"))
|
|
||||||
return (1);
|
|
||||||
if (0 > fprintf(f, "source: %s\n", source))
|
|
||||||
return (1);
|
|
||||||
if (0 > fprintf(f, "target: %s\n", target))
|
|
||||||
return (1);
|
|
||||||
if (0 > fprintf(f, "---\n"))
|
|
||||||
return (1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `write_ranges`
|
|
||||||
Writes the ranges of a c-md mapping file.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `f`: Pointer to the output file.
|
|
||||||
- `map`: Pointer to the mapping structure.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Return 0 on success, or 1 on failure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
write_ranges(FILE *f, t_map *map)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
t_range *r;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (i < map->count)
|
|
||||||
{
|
|
||||||
r = &map->ranges[i];
|
|
||||||
if (0 > fprintf(f, "%u-%u:%u-%u\n",
|
|
||||||
r->src_start, r->src_end, r->dst_start, r->dst_end))
|
|
||||||
return (1);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
12
srcs/transpile/code.c
Normal file
12
srcs/transpile/code.c
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "internal/transpile_internal.h"
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
handle_code_line(t_state *s, char *line)
|
||||||
|
{
|
||||||
|
if (0 > fputs(line, s->out))
|
||||||
|
return (1);
|
||||||
|
s->dst_line++;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
# code.c
|
|
||||||
Handle a single line of code by writing it to the output file and updating the
|
|
||||||
state.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "internal/transpile_internal.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
|
|
||||||
### `handle_code_line`
|
|
||||||
Handle a single line of code by writing it to the output file and updating the
|
|
||||||
state.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `s`: Pointer to the current state structure.
|
|
||||||
- `line`: Pointer to the line of code to be handled.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Return 0 on success, or 1 on failure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
handle_code_line(t_state *s, char *line)
|
|
||||||
{
|
|
||||||
if (0 > fputs(line, s->out))
|
|
||||||
return (1);
|
|
||||||
s->dst_line++;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
38
srcs/transpile/core.c
Normal file
38
srcs/transpile/core.c
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "transpile.h"
|
||||||
|
#include "internal/transpile_internal.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
process_line(t_state *s, char *line)
|
||||||
|
{
|
||||||
|
s->src_line++;
|
||||||
|
if (0 == s->in_block && starts_with(line, "```"))
|
||||||
|
return (handle_fence_open(s, line));
|
||||||
|
if (1 == s->in_block && starts_with(line, "```"))
|
||||||
|
return (handle_fence_close(s));
|
||||||
|
if (1 == s->in_block)
|
||||||
|
return (handle_code_line(s, line));
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
transpile(FILE *in, FILE *out, const char *ext, t_map *map)
|
||||||
|
{
|
||||||
|
t_state s;
|
||||||
|
char *line;
|
||||||
|
int8_t ret;
|
||||||
|
|
||||||
|
state_init(&s, in, out, ext, map);
|
||||||
|
ret = 0;
|
||||||
|
line = read_line(in);
|
||||||
|
while (NULL != line && 0 == ret)
|
||||||
|
{
|
||||||
|
ret = process_line(&s, line);
|
||||||
|
free(line);
|
||||||
|
line = read_line(in);
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
# core.c
|
|
||||||
Core funtion of the transpiler.
|
|
||||||
Handles reading lines and processing them according to the current state.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "transpile.h"
|
|
||||||
#include "internal/transpile_internal.h"
|
|
||||||
#include "utils.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Forward Declarations
|
|
||||||
|
|
||||||
```c
|
|
||||||
static int8_t process_line(t_state *s, char *line);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
|
|
||||||
### `transpile`
|
|
||||||
Transpiles input from a file to an output file based on the specified extension
|
|
||||||
and mapping.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `in`: Pointer to the input file.
|
|
||||||
- `out`: Pointer to the output file.
|
|
||||||
- `ext`: Pointer to the file extension string.
|
|
||||||
- `map`: Pointer to the mapping structure.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Return 0 on success, or a non-zero error code on failure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
transpile(FILE *in, FILE *out, const char *ext, t_map *map)
|
|
||||||
{
|
|
||||||
t_state s;
|
|
||||||
char *line;
|
|
||||||
int8_t ret;
|
|
||||||
|
|
||||||
state_init(&s, in, out, ext, map);
|
|
||||||
ret = 0;
|
|
||||||
line = read_line(in);
|
|
||||||
while (NULL != line && 0 == ret)
|
|
||||||
{
|
|
||||||
ret = process_line(&s, line);
|
|
||||||
free(line);
|
|
||||||
line = read_line(in);
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `process_line`
|
|
||||||
Processes a single line of input based on the current state.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `s`: Pointer to the current state structure.
|
|
||||||
- `line`: Pointer to the line of text to process.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Return 0 on success, or a non-zero error code on failure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
static int8_t
|
|
||||||
process_line(t_state *s, char *line)
|
|
||||||
{
|
|
||||||
s->src_line++;
|
|
||||||
if (0 == s->in_block && starts_with(line, "```"))
|
|
||||||
return (handle_fence_open(s, line));
|
|
||||||
if (1 == s->in_block && starts_with(line, "```"))
|
|
||||||
return (handle_fence_close(s));
|
|
||||||
if (1 == s->in_block)
|
|
||||||
return (handle_code_line(s, line));
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,34 +1,10 @@
|
||||||
# fence.c
|
|
||||||
Handles opening and closing of fenced code blocks in the transpilation process.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "internal/transpile_internal.h"
|
#include "internal/transpile_internal.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
|
|
||||||
### `handle_fence_open`
|
|
||||||
Handles the opening of a fenced code block.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `s`: Pointer to the current transpilation state.
|
|
||||||
- `line`: Pointer to the current line being processed.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Returns `0` on success, `1` on error.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
int8_t
|
||||||
handle_fence_open(t_state *s, char *line)
|
handle_fence_open(t_state *s, char *line)
|
||||||
{
|
{
|
||||||
|
|
@ -55,16 +31,7 @@ handle_fence_open(t_state *s, char *line)
|
||||||
s->block_dst_start = s->dst_line + 1;
|
s->block_dst_start = s->dst_line + 1;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### `handle_fence_close`
|
|
||||||
Handles the closing of a fenced code block.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `s`: Pointer to the current transpilation state.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
int8_t
|
||||||
handle_fence_close(t_state *s)
|
handle_fence_close(t_state *s)
|
||||||
{
|
{
|
||||||
|
|
@ -81,4 +48,3 @@ handle_fence_close(t_state *s)
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
16
srcs/transpile/state.c
Normal file
16
srcs/transpile/state.c
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include "internal/transpile_internal.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
state_init(t_state *s, FILE *in, FILE *out, const char *ext, t_map *map)
|
||||||
|
{
|
||||||
|
s->in = in;
|
||||||
|
s->out = out;
|
||||||
|
s->ext = ext;
|
||||||
|
s->map = map;
|
||||||
|
s->src_line = 0;
|
||||||
|
s->dst_line = 0;
|
||||||
|
s->block_src_start = 0;
|
||||||
|
s->block_dst_start = 0;
|
||||||
|
s->in_block = 0;
|
||||||
|
s->first_block = 1;
|
||||||
|
}
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
# state.c
|
|
||||||
|
|
||||||
Initialize the transpilation state structure.
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include "internal/transpile_internal.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Description
|
|
||||||
### `state_init`
|
|
||||||
|
|
||||||
Initialize the transpilation state structure.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `s`: Pointer to the state structure to initialize.
|
|
||||||
- `in`: Input file pointer.
|
|
||||||
- `out`: Output file pointer.
|
|
||||||
- `ext`: Pointer to the extracted code fence extension string.
|
|
||||||
- `map`: Pointer to the mapping structure.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
|
|
||||||
```c
|
|
||||||
void
|
|
||||||
state_init(t_state *s, FILE *in, FILE *out, const char *ext, t_map *map)
|
|
||||||
{
|
|
||||||
s->in = in;
|
|
||||||
s->out = out;
|
|
||||||
s->ext = ext;
|
|
||||||
s->map = map;
|
|
||||||
s->src_line = 0;
|
|
||||||
s->dst_line = 0;
|
|
||||||
s->block_src_start = 0;
|
|
||||||
s->block_dst_start = 0;
|
|
||||||
s->in_block = 0;
|
|
||||||
s->first_block = 1;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
24
srcs/utils/io/read_line.c
Normal file
24
srcs/utils/io/read_line.c
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
char *
|
||||||
|
read_line(FILE *f)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
size_t len;
|
||||||
|
ssize_t read;
|
||||||
|
|
||||||
|
line = NULL;
|
||||||
|
len = 0;
|
||||||
|
read = getline(&line, &len, f);
|
||||||
|
if (-1 == read)
|
||||||
|
{
|
||||||
|
free(line);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (line);
|
||||||
|
}
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
# read_line.c
|
|
||||||
|
|
||||||
Get a line from a file.
|
|
||||||
depends on POSIX getline
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
|
|
||||||
```c
|
|
||||||
#define _POSIX_C_SOURCE 200809L
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Description
|
|
||||||
|
|
||||||
### `read_line`
|
|
||||||
|
|
||||||
Get a line from a file.
|
|
||||||
|
|
||||||
#### Parameter
|
|
||||||
- `f`: Pointer to a `FILE` object representing the input file.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
|
|
||||||
Returns a pointer to the read line (dynamically allocated) or `NULL` on failure
|
|
||||||
or end of file.
|
|
||||||
|
|
||||||
Return value must be freed by the caller.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
|
|
||||||
```c
|
|
||||||
char *
|
|
||||||
read_line(FILE *f)
|
|
||||||
{
|
|
||||||
char *line;
|
|
||||||
size_t len;
|
|
||||||
ssize_t read;
|
|
||||||
|
|
||||||
line = NULL;
|
|
||||||
len = 0;
|
|
||||||
read = getline(&line, &len, f);
|
|
||||||
if (-1 == read)
|
|
||||||
{
|
|
||||||
free(line);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
return (line);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -1,38 +1,9 @@
|
||||||
# extract_fence_ext.c
|
|
||||||
|
|
||||||
Extract the extension from a markdown code fence.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Description
|
|
||||||
|
|
||||||
### `extract_fence_ext`
|
|
||||||
Extracts the extension from a markdown code fence string.
|
|
||||||
|
|
||||||
#### Parameter
|
|
||||||
- `fence`: Pointer to a null-terminated string representing the code fence.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
|
|
||||||
Returns a dynamically allocated string containing the extracted extension, or
|
|
||||||
`NULL` if no extension is found or if the input is not a valid code fence.
|
|
||||||
|
|
||||||
Return value must be freed by the caller.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
|
|
||||||
```c
|
|
||||||
char *
|
char *
|
||||||
extract_fence_ext(const char *fence)
|
extract_fence_ext(const char *fence)
|
||||||
{
|
{
|
||||||
|
|
@ -59,4 +30,3 @@ extract_fence_ext(const char *fence)
|
||||||
ext[len] = '\0';
|
ext[len] = '\0';
|
||||||
return (ext);
|
return (ext);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
14
srcs/utils/string/extract_file_ext.c
Normal file
14
srcs/utils/string/extract_file_ext.c
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
const char *
|
||||||
|
extract_file_ext(const char *path)
|
||||||
|
{
|
||||||
|
const char *dot;
|
||||||
|
|
||||||
|
dot = strrchr(path, '.');
|
||||||
|
if (NULL == dot || dot == path)
|
||||||
|
return (NULL);
|
||||||
|
return (dot + 1);
|
||||||
|
}
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
# extract_file_ext.c
|
|
||||||
|
|
||||||
Get the file extension from a given file path.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Description
|
|
||||||
|
|
||||||
### `extract_file_ext`
|
|
||||||
Get the file extension from a given file path.
|
|
||||||
|
|
||||||
#### Parameter
|
|
||||||
- `path`: The file path string.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
|
|
||||||
Returns a pointer to the file extension within the path string, or `NULL` if
|
|
||||||
no extension is found.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
|
|
||||||
```c
|
|
||||||
const char *
|
|
||||||
extract_file_ext(const char *path)
|
|
||||||
{
|
|
||||||
const char *dot;
|
|
||||||
|
|
||||||
dot = strrchr(path, '.');
|
|
||||||
if (NULL == dot || dot == path)
|
|
||||||
return (NULL);
|
|
||||||
return (dot + 1);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -1,30 +1,7 @@
|
||||||
# infer_ext_from_filename.c
|
|
||||||
Infer file extension from filename ending with .md
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Descriptions
|
|
||||||
|
|
||||||
### `infer_ext_from_filename`
|
|
||||||
Infer the file extension from a filename that ends with `.md`.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `path`: Pointer to the filename string.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
Returns a pointer to a static buffer containing the inferred extension, or
|
|
||||||
`NULL` if no valid
|
|
||||||
|
|
||||||
```c
|
|
||||||
const char *
|
const char *
|
||||||
infer_ext_from_filename(const char *path)
|
infer_ext_from_filename(const char *path)
|
||||||
{
|
{
|
||||||
|
|
@ -58,4 +35,3 @@ infer_ext_from_filename(const char *path)
|
||||||
ext_buffer[ext_len] = '\0';
|
ext_buffer[ext_len] = '\0';
|
||||||
return (ext_buffer);
|
return (ext_buffer);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
13
srcs/utils/string/starts_with.c
Normal file
13
srcs/utils/string/starts_with.c
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
starts_with(const char *str, const char *prefix)
|
||||||
|
{
|
||||||
|
size_t prefix_len;
|
||||||
|
|
||||||
|
prefix_len = strlen(prefix);
|
||||||
|
return (0 == strncmp(str, prefix, prefix_len));
|
||||||
|
}
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
# starts_with.c
|
|
||||||
|
|
||||||
Checks if a string starts with a given prefix.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
```
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Description
|
|
||||||
|
|
||||||
### `starts_with`
|
|
||||||
|
|
||||||
Checks if the string `str` starts with the substring `prefix`.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
- `str`: The main string to check.
|
|
||||||
- `prefix`: The prefix to look for at the start of `str`.
|
|
||||||
|
|
||||||
#### Return Value
|
|
||||||
- Returns `1` (true) if `str` starts with `prefix`.
|
|
||||||
- Returns `0` (false) otherwise.
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
starts_with(const char *str, const char *prefix)
|
|
||||||
{
|
|
||||||
size_t prefix_len;
|
|
||||||
|
|
||||||
prefix_len = strlen(prefix);
|
|
||||||
return (0 == strncmp(str, prefix, prefix_len));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
22
srcs/validator/validator.c
Normal file
22
srcs/validator/validator.c
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "validator.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
int8_t
|
||||||
|
validator_validate_args(t_args *args)
|
||||||
|
{
|
||||||
|
if (NULL == args->input)
|
||||||
|
{
|
||||||
|
if (NULL == args->ext)
|
||||||
|
return (1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (NULL == args->ext)
|
||||||
|
{
|
||||||
|
args->ext = infer_ext_from_filename(args->input);
|
||||||
|
if (NULL == args->ext)
|
||||||
|
return (2);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
# validator.c
|
|
||||||
|
|
||||||
Validate command-line arguments.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Includes
|
|
||||||
```c
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "validator.h"
|
|
||||||
#include "utils.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Function Description
|
|
||||||
|
|
||||||
### `validator_validate_args`
|
|
||||||
|
|
||||||
Checks and validates the content of the `t_args` structure, ensuring required
|
|
||||||
file input and extension arguments are consistent.
|
|
||||||
|
|
||||||
#### Parameter
|
|
||||||
- `args`: Pointer to a `t_args` structure containing command-line arguments.
|
|
||||||
|
|
||||||
#### Return Codes
|
|
||||||
|
|
||||||
| Code | Meaning |
|
|
||||||
|------|-----------------------------------------------------------------|
|
|
||||||
| 0 | Arguments are valid |
|
|
||||||
| 1 | Both input file and extension are missing |
|
|
||||||
| 2 | Extension is missing and cannot be inferred from input filename |
|
|
||||||
|
|
||||||
#### Implementation
|
|
||||||
```c
|
|
||||||
int8_t
|
|
||||||
validator_validate_args(t_args *args)
|
|
||||||
{
|
|
||||||
if (NULL == args->input)
|
|
||||||
{
|
|
||||||
if (NULL == args->ext)
|
|
||||||
return (1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
if (NULL == args->ext)
|
|
||||||
{
|
|
||||||
args->ext = infer_ext_from_filename(args->input);
|
|
||||||
if (NULL == args->ext)
|
|
||||||
return (2);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Loading…
Add table
Reference in a new issue