feat: c-md transpiler v0.0.1
This commit is contained in:
parent
f4e51df5e8
commit
8c0ed3462f
28 changed files with 791 additions and 10 deletions
2
Makefile
2
Makefile
|
|
@ -33,7 +33,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
|||
test: $(TEST_BIN)
|
||||
./$(TEST_BIN)
|
||||
|
||||
$(TEST_BIN): $(TESTS) $(filter %.o,$(OBJS))
|
||||
$(TEST_BIN): $(TESTS) $(filter-out $(OBJ_DIR)/main.o,$(OBJS))
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $^ -o $@
|
||||
|
||||
|
|
|
|||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
11
includes/transpile.h
Normal file
11
includes/transpile.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef TRANSPILE_H
|
||||
# define TRANSPILE_H
|
||||
|
||||
# include <stdint.h>
|
||||
# include <stdio.h>
|
||||
# include "map.h"
|
||||
|
||||
int8_t
|
||||
transpile(FILE *in, FILE *out, const char *ext, t_map *map);
|
||||
|
||||
#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
|
||||
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
|
||||
23
sources.mk
23
sources.mk
|
|
@ -1,6 +1,25 @@
|
|||
|
||||
SRC_DIR = srcs
|
||||
SRCS = $(SRC_DIR)/main.c
|
||||
SRCS = $(SRC_DIR)/main.c \
|
||||
$(SRC_DIR)/io/streams.c \
|
||||
$(SRC_DIR)/utils/io/read_line.c \
|
||||
$(SRC_DIR)/utils/string/starts_with.c \
|
||||
$(SRC_DIR)/utils/string/extract_fence_ext.c \
|
||||
$(SRC_DIR)/utils/string/extract_file_ext.c \
|
||||
$(SRC_DIR)/utils/string/infer_ext_from_filename.c \
|
||||
$(SRC_DIR)/transpile/state.c \
|
||||
$(SRC_DIR)/transpile/fence.c \
|
||||
$(SRC_DIR)/transpile/code.c \
|
||||
$(SRC_DIR)/transpile/core.c \
|
||||
$(SRC_DIR)/map/core.c \
|
||||
$(SRC_DIR)/map/io.c \
|
||||
$(SRC_DIR)/cli/cli.c \
|
||||
$(SRC_DIR)/cli/help.c \
|
||||
$(SRC_DIR)/validator/validator.c
|
||||
|
||||
TESTS_DIR = tests
|
||||
TESTS= $(TESTS_DIR)/test_main.c
|
||||
TESTS = $(TESTS_DIR)/test_utils.c \
|
||||
$(TESTS_DIR)/test_map.c \
|
||||
$(TESTS_DIR)/test_transpile.c \
|
||||
$(TESTS_DIR)/test_cli.c \
|
||||
$(TESTS_DIR)/test_integration.c
|
||||
|
|
|
|||
111
srcs/cli/cli.c
Normal file
111
srcs/cli/cli.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#include <stddef.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cli.h"
|
||||
|
||||
typedef void (*t_handler)(t_args *, const char *);
|
||||
|
||||
typedef struct s_opt
|
||||
{
|
||||
int8_t short_opt;
|
||||
t_handler handler;
|
||||
} t_opt;
|
||||
|
||||
static void handle_help(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_output(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 void init_args(t_args *args);
|
||||
|
||||
static const t_opt g_opts[] = {
|
||||
{'h', handle_help},
|
||||
{'e', handle_ext},
|
||||
{'i', handle_input},
|
||||
{'o', handle_output},
|
||||
{'m', handle_map},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static struct option g_long_opts[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"ext", required_argument, NULL, 'e'},
|
||||
{"input", required_argument, NULL, 'i'},
|
||||
{"map", required_argument, NULL, 'm'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
int8_t
|
||||
cli_parse(t_args *args, int32_t argc, char **argv)
|
||||
{
|
||||
int32_t opt;
|
||||
t_handler handler;
|
||||
|
||||
init_args(args);
|
||||
while (-1 != (opt = getopt_long(argc, argv, "he:i:o:m:", g_long_opts, NULL)))
|
||||
{
|
||||
handler = find_handler((int8_t)opt);
|
||||
if (NULL == handler)
|
||||
return (-1);
|
||||
handler(args, optarg);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
init_args(t_args *args)
|
||||
{
|
||||
args->ext = NULL;
|
||||
args->input = NULL;
|
||||
args->output = NULL;
|
||||
args->map_path = NULL;
|
||||
args->show_help = 0;
|
||||
}
|
||||
|
||||
static t_handler
|
||||
find_handler(int8_t opt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
i = 0;
|
||||
while (0 != g_opts[i].short_opt)
|
||||
{
|
||||
if (opt == g_opts[i].short_opt)
|
||||
return (g_opts[i].handler);
|
||||
i++;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_help(t_args *args, const char *value)
|
||||
{
|
||||
(void)value;
|
||||
args->show_help = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_ext(t_args *args, const char *value)
|
||||
{
|
||||
args->ext = value;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_input(t_args *args, const char *value)
|
||||
{
|
||||
args->input = value;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_output(t_args *args, const char *value)
|
||||
{
|
||||
args->output = value;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_map(t_args *args, const char *value)
|
||||
{
|
||||
args->map_path = value;
|
||||
}
|
||||
21
srcs/cli/help.c
Normal file
21
srcs/cli/help.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "cli.h"
|
||||
|
||||
void
|
||||
cli_print_help(const char *progname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [OPTIONS]\n\n", progname);
|
||||
fprintf(stderr, "Extract code blocks from literate markdown files.\n\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, " -h, --help Show this help\n");
|
||||
fprintf(stderr, " -e, --ext EXT Extension to extract (c, h, py, etc.)\n");
|
||||
fprintf(stderr, " Required for stdin, optional for files\n");
|
||||
fprintf(stderr, " -i, --input FILE Input file (default: stdin)\n");
|
||||
fprintf(stderr, " -o, --output FILE Output file (default: stdout)\n");
|
||||
fprintf(stderr, " -m, --map FILE Generate line mapping file\n\n");
|
||||
fprintf(stderr, "Examples:\n");
|
||||
fprintf(stderr, " %s -e c < input.md > output.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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
65
srcs/main.c
65
srcs/main.c
|
|
@ -1,6 +1,67 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "cli.h"
|
||||
#include "validator.h"
|
||||
#include "transpile.h"
|
||||
#include "map.h"
|
||||
#include "io.h"
|
||||
|
||||
static int8_t run(t_args *args);
|
||||
static void print_error(int8_t code, const char *progname);
|
||||
|
||||
int
|
||||
main()
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
t_args args;
|
||||
int8_t validation_code;
|
||||
|
||||
if (0 != cli_parse(&args, (int32_t)argc, argv))
|
||||
{
|
||||
cli_print_help(argv[0]);
|
||||
return (1);
|
||||
}
|
||||
if (args.show_help)
|
||||
{
|
||||
cli_print_help(argv[0]);
|
||||
return (0);
|
||||
}
|
||||
validation_code = validator_validate_args(&args);
|
||||
if (0 != validation_code)
|
||||
{
|
||||
print_error(validation_code, argv[0]);
|
||||
return (1);
|
||||
}
|
||||
return (run(&args));
|
||||
}
|
||||
|
||||
static void
|
||||
print_error(int8_t code, const char *progname)
|
||||
{
|
||||
if (1 == code)
|
||||
fprintf(stderr, "Error: -e required when reading from stdin\n");
|
||||
else if (2 == code)
|
||||
fprintf(stderr, "Error: -e required (cannot infer from filename)\n");
|
||||
cli_print_help(progname);
|
||||
}
|
||||
|
||||
static int8_t
|
||||
run(t_args *args)
|
||||
{
|
||||
t_io io;
|
||||
t_map map;
|
||||
int8_t ret;
|
||||
|
||||
if (0 != io_open(&io, args->input, args->output))
|
||||
return (1);
|
||||
map_init(&map);
|
||||
ret = transpile(io.in, io.out, args->ext, &map);
|
||||
if (0 == ret && NULL != args->map_path)
|
||||
{
|
||||
ret = map_write(&map, args->map_path,
|
||||
(NULL != args->input) ? args->input : "stdin",
|
||||
(NULL != args->output) ? args->output : "stdout");
|
||||
}
|
||||
map_free(&map);
|
||||
io_close(&io);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
50
srcs/transpile/fence.c
Normal file
50
srcs/transpile/fence.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "internal/transpile_internal.h"
|
||||
#include "utils.h"
|
||||
|
||||
int8_t
|
||||
handle_fence_open(t_state *s, char *line)
|
||||
{
|
||||
char *block_ext;
|
||||
|
||||
block_ext = extract_fence_ext(line);
|
||||
if (NULL == block_ext)
|
||||
return (0);
|
||||
if (0 != strcmp(block_ext, s->ext))
|
||||
{
|
||||
free(block_ext);
|
||||
return (0);
|
||||
}
|
||||
free(block_ext);
|
||||
if (0 == s->first_block)
|
||||
{
|
||||
if (0 > fprintf(s->out, "\n"))
|
||||
return (1);
|
||||
s->dst_line++;
|
||||
}
|
||||
s->first_block = 0;
|
||||
s->in_block = 1;
|
||||
s->block_src_start = s->src_line + 1;
|
||||
s->block_dst_start = s->dst_line + 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int8_t
|
||||
handle_fence_close(t_state *s)
|
||||
{
|
||||
uint32_t src_end;
|
||||
uint32_t dst_end;
|
||||
|
||||
s->in_block = 0;
|
||||
src_end = s->src_line - 1;
|
||||
dst_end = s->dst_line;
|
||||
if (s->block_src_start <= src_end)
|
||||
{
|
||||
map_add(s->map, s->block_src_start, src_end,
|
||||
s->block_dst_start, dst_end);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
32
srcs/utils/string/extract_fence_ext.c
Normal file
32
srcs/utils/string/extract_fence_ext.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
char *
|
||||
extract_fence_ext(const char *fence)
|
||||
{
|
||||
const char *start;
|
||||
const char *end;
|
||||
size_t len;
|
||||
char *ext;
|
||||
|
||||
if (0 != strncmp(fence, "```", 3))
|
||||
return (NULL);
|
||||
start = fence + 3;
|
||||
while (' ' == *start || '\t' == *start)
|
||||
start++;
|
||||
if ('\n' == *start || '\0' == *start)
|
||||
return (NULL);
|
||||
end = start;
|
||||
while ('\n' != *end && '\0' != *end && ' ' != *end && '\t' != *end)
|
||||
end++;
|
||||
len = (size_t)(end - start);
|
||||
ext = malloc(len + 1);
|
||||
if (NULL == ext)
|
||||
return (NULL);
|
||||
memcpy(ext, start, len);
|
||||
ext[len] = '\0';
|
||||
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);
|
||||
}
|
||||
37
srcs/utils/string/infer_ext_from_filename.c
Normal file
37
srcs/utils/string/infer_ext_from_filename.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
const char *
|
||||
infer_ext_from_filename(const char *path)
|
||||
{
|
||||
static char ext_buffer[32];
|
||||
const char *md_ext;
|
||||
const char *before_md;
|
||||
const char *dot;
|
||||
size_t len;
|
||||
size_t ext_len;
|
||||
|
||||
if (NULL == path)
|
||||
return (NULL);
|
||||
len = strlen(path);
|
||||
if (len < 6)
|
||||
return (NULL);
|
||||
md_ext = path + len - 3;
|
||||
if (0 != strcmp(md_ext, ".md"))
|
||||
return (NULL);
|
||||
before_md = md_ext - 1;
|
||||
while (before_md > path && '.' != *before_md)
|
||||
before_md--;
|
||||
if (before_md == path || '.' != *before_md)
|
||||
return (NULL);
|
||||
dot = before_md;
|
||||
if (dot + 1 >= md_ext)
|
||||
return (NULL);
|
||||
ext_len = md_ext - (dot + 1);
|
||||
if (ext_len >= sizeof(ext_buffer))
|
||||
return (NULL);
|
||||
memcpy(ext_buffer, dot + 1, ext_len);
|
||||
ext_buffer[ext_len] = '\0';
|
||||
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));
|
||||
}
|
||||
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,5 +0,0 @@
|
|||
#include <criterion/criterion.h>
|
||||
|
||||
Test(dummy, always_pass) {
|
||||
cr_assert(0, "Hello, world!");
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue