Compare commits

..

6 commits
v1.0.0 ... main

Author SHA1 Message Date
lohhiiccc
6d84e93750 fix: dead link 2026-01-12 18:09:10 +01:00
lohhiiccc
8fddcd4fa3 docs: update function reference links to use anchor fragments in headers 2026-01-12 17:42:40 +01:00
lohhiiccc
444d1fc956 docs: add documentation to each .h.md file 2026-01-12 17:01:58 +01:00
lohhiiccc
20be391329 docs: add documentation to each .c.md file 2026-01-12 16:22:13 +01:00
lohhiiccc
80f7a1b9b6 feat(build): add build instructions in README and convert sources to .c.md format
- Add detailed build and bootstrap instructions to README.md.
 - Convert all source and header files from .c/.h to .c.md/.h.md.
 - Add bootstrap.sh script for automated building across version history.
 - Update Makefile and sources.mk to reflect new markdown-based source organization.
2026-01-12 14:54:49 +01:00
lohhiiccc
2cf16ff109 fix: add --output 2026-01-12 12:16:52 +01:00
45 changed files with 1413 additions and 475 deletions

View file

@ -1,32 +1,48 @@
NAME = c-md NAME = c-md
VERSION = 1.0.0 VERSION = 2.0.0
TEST_BIN= c-md.test
.DEFAULT_GOAL := all .DEFAULT_GOAL := all
TEST_BIN= c-md.test
CMD = ./$(NAME)
MAKEFLAGS += --no-print-directory MAKEFLAGS += --no-print-directory
include sources.mk include sources.mk
CC = clang CC = clang
CPPFLAGS = -std=c99 -I includes CPPFLAGS = -std=c99
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
OBJ_DIR = .build GEN_SRCS = $(MD_SRCS:$(SRC_DIR)/%.c.md=$(BUILD_DIR)/srcs/%.c)
GEN_HDRS = $(MD_HDRS:$(INC_DIR)/%.h.md=$(BUILD_DIR)/$(INC_DIR)/%.h)
OBJS = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) OBJS = $(GEN_SRCS:$(BUILD_DIR)/srcs/%.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): $(OBJS) $(NAME): $(GEN_HDRS) $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(CC) $(LDFLAGS) -o $@ $(OBJS)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(BUILD_DIR)/srcs/%.c: $(SRC_DIR)/%.c.md
@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) -MMD -MP -c $< -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) -I $(BUILD_DIR)/$(INC_DIR) -MMD -MP -c $< -o $@
-include $(DEPS) -include $(DEPS)
@ -37,13 +53,12 @@ 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) $(TEST_LDFLAGS) $^ -o $@ $(CC) $(CPPFLAGS) $(CFLAGS) -I $(BUILD_DIR)/$(INC_DIR) $(TEST_LDFLAGS) $^ -o $@
.PHONY: clean .PHONY: clean
clean: clean:
$(RM) -r $(OBJ_DIR) $(RM) -r $(BUILD_DIR)
.PHONY: fclean .PHONY: fclean
fclean: clean fclean: clean
@ -53,4 +68,3 @@ fclean: clean
.PHONY: re .PHONY: re
re: fclean re: fclean
$(MAKE) all $(MAKE) all

View file

@ -106,6 +106,35 @@ 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
@ -117,7 +146,7 @@ source lines (`.c.md`) and output lines (`.c`). This enables:
## Status ## Status
**v1.0.0** - Initial stable release **v2.0.0** - Initial stable release self-hosted.
## License ## License

103
bootstrap.sh Executable file
View file

@ -0,0 +1,103 @@
#!/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."

View file

@ -1,21 +0,0 @@
#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

44
includes/cli.h.md Normal file
View file

@ -0,0 +1,44 @@
# 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
```

View file

@ -1,19 +0,0 @@
#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

View file

@ -0,0 +1,26 @@
# 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
```

View file

@ -1,37 +0,0 @@
#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

View file

@ -0,0 +1,66 @@
# 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
```

View file

@ -1,19 +0,0 @@
#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

40
includes/io.h.md Normal file
View file

@ -0,0 +1,40 @@
# 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
```

View file

@ -1,35 +0,0 @@
#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

72
includes/map.h.md Normal file
View file

@ -0,0 +1,72 @@
# 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
```

View file

@ -1,11 +1,23 @@
# 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
```

View file

@ -1,22 +0,0 @@
#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

51
includes/utils.h.md Normal file
View file

@ -0,0 +1,51 @@
# 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
```

View file

@ -1,10 +0,0 @@
#ifndef VALIDATOR_H
# define VALIDATOR_H
# include <stdint.h>
# include "cli.h"
int8_t
validator_validate_args(t_args *args);
#endif

23
includes/validator.h.md Normal file
View file

@ -0,0 +1,23 @@
# 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
```

View file

@ -1,21 +1,31 @@
SRC_DIR = srcs SRC_DIR = srcs
SRCS = $(SRC_DIR)/main.c \ MD_SRCS = $(SRC_DIR)/main.c.md \
$(SRC_DIR)/io/streams.c \ $(SRC_DIR)/io/streams.c.md \
$(SRC_DIR)/utils/io/read_line.c \ $(SRC_DIR)/utils/io/read_line.c.md \
$(SRC_DIR)/utils/string/starts_with.c \ $(SRC_DIR)/utils/string/starts_with.c.md \
$(SRC_DIR)/utils/string/extract_fence_ext.c \ $(SRC_DIR)/utils/string/extract_fence_ext.c.md \
$(SRC_DIR)/utils/string/extract_file_ext.c \ $(SRC_DIR)/utils/string/extract_file_ext.c.md \
$(SRC_DIR)/utils/string/infer_ext_from_filename.c \ $(SRC_DIR)/utils/string/infer_ext_from_filename.c.md \
$(SRC_DIR)/transpile/state.c \ $(SRC_DIR)/transpile/state.c.md \
$(SRC_DIR)/transpile/fence.c \ $(SRC_DIR)/transpile/fence.c.md \
$(SRC_DIR)/transpile/code.c \ $(SRC_DIR)/transpile/code.c.md \
$(SRC_DIR)/transpile/core.c \ $(SRC_DIR)/transpile/core.c.md \
$(SRC_DIR)/map/core.c \ $(SRC_DIR)/map/core.c.md \
$(SRC_DIR)/map/io.c \ $(SRC_DIR)/map/io.c.md \
$(SRC_DIR)/cli/cli.c \ $(SRC_DIR)/cli/cli.c.md \
$(SRC_DIR)/cli/help.c \ $(SRC_DIR)/cli/help.c.md \
$(SRC_DIR)/validator/validator.c $(SRC_DIR)/validator/validator.c.md
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 \

View file

@ -1,17 +1,39 @@
# 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);
@ -19,7 +41,12 @@ 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},
@ -28,15 +55,36 @@ 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)
{ {
@ -53,7 +101,16 @@ 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)
{ {
@ -63,7 +120,19 @@ 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)
{ {
@ -78,34 +147,55 @@ 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;
} }
```

View file

@ -1,7 +1,23 @@
# 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)
{ {
@ -19,3 +35,4 @@ 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);
} }
```

View file

@ -1,32 +0,0 @@
#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);
}

70
srcs/io/streams.c.md Normal file
View file

@ -0,0 +1,70 @@
# 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);
}
```

View file

@ -1,14 +1,33 @@
# 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)
{ {
@ -33,7 +52,17 @@ 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)
{ {
@ -43,7 +72,13 @@ 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)
{ {
@ -65,3 +100,4 @@ run(t_args *args)
io_close(&io); io_close(&io);
return (ret); return (ret);
} }
```

View file

@ -1,55 +0,0 @@
#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);
}

115
srcs/map/core.c.md Normal file
View file

@ -0,0 +1,115 @@
# 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);
}
```

View file

@ -1,55 +0,0 @@
#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 Normal file
View file

@ -0,0 +1,117 @@
# 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);
}
```

View file

@ -1,12 +0,0 @@
#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);
}

39
srcs/transpile/code.c.md Normal file
View file

@ -0,0 +1,39 @@
# 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);
}
```

View file

@ -1,38 +0,0 @@
#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);
}

86
srcs/transpile/core.c.md Normal file
View file

@ -0,0 +1,86 @@
# 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);
}

View file

@ -1,10 +1,34 @@
# 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)
{ {
@ -31,7 +55,16 @@ 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)
{ {
@ -48,3 +81,4 @@ handle_fence_close(t_state *s)
} }
return (0); return (0);
} }
```

View file

@ -1,16 +0,0 @@
#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;
}

41
srcs/transpile/state.c.md Normal file
View file

@ -0,0 +1,41 @@
# 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;
}
```

View file

@ -1,24 +0,0 @@
#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);
}

View file

@ -0,0 +1,57 @@
# 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);
}
```

View file

@ -1,9 +1,38 @@
# 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)
{ {
@ -30,3 +59,4 @@ extract_fence_ext(const char *fence)
ext[len] = '\0'; ext[len] = '\0';
return (ext); return (ext);
} }
```

View file

@ -1,14 +0,0 @@
#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);
}

View file

@ -0,0 +1,42 @@
# 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);
}
```

View file

@ -1,7 +1,30 @@
# 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)
{ {
@ -35,3 +58,4 @@ infer_ext_from_filename(const char *path)
ext_buffer[ext_len] = '\0'; ext_buffer[ext_len] = '\0';
return (ext_buffer); return (ext_buffer);
} }
```

View file

@ -1,13 +0,0 @@
#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));
}

View file

@ -0,0 +1,40 @@
# 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));
}
```

View file

@ -1,22 +0,0 @@
#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);
}

View file

@ -0,0 +1,54 @@
# 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);
}
```