commit
8c97f3bb8c
|
@ -0,0 +1,67 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
|
||||
#include "char_dyn_arr.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct char_dyn_arr *init_char_dyn_arr(int size)
|
||||
{
|
||||
struct char_dyn_arr *a;
|
||||
|
||||
a = NULL;
|
||||
|
||||
a = calloc(1, sizeof(struct char_dyn_arr));
|
||||
if (!a)
|
||||
goto free_and_exit;
|
||||
|
||||
a->data = calloc(size, sizeof(char *));
|
||||
if (!(a->data))
|
||||
goto free_and_exit;
|
||||
|
||||
a->used = 0;
|
||||
a->size = size;
|
||||
|
||||
return a;
|
||||
|
||||
free_and_exit:
|
||||
free(a);
|
||||
free(a->data);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int insert_char_dyn_arr(struct char_dyn_arr *a, char *e)
|
||||
{
|
||||
if (a->used == a->size) {
|
||||
a->size *= 2;
|
||||
a->data = realloc(a->data, a->size * sizeof(char *));
|
||||
if (!(a->data))
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
a->data[a->used++] = e;
|
||||
|
||||
return CHAR_DYN_ARR_OK;
|
||||
|
||||
free_and_exit:
|
||||
free(a);
|
||||
free(a->data);
|
||||
|
||||
return CHAR_DYN_ARR_FAILED;
|
||||
}
|
||||
|
||||
extern void free_char_dyn_arr(struct char_dyn_arr *a)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
if (a->data) {
|
||||
for (i = 0; i < a->used; i++)
|
||||
free(a->data[i]);
|
||||
}
|
||||
|
||||
free(a->data);
|
||||
free(a);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _char_dyn_arr
|
||||
#define _char_dyn_arr
|
||||
|
||||
#define CHAR_DYN_ARR_OK 0
|
||||
#define CHAR_DYN_ARR_FAILED -1
|
||||
|
||||
struct char_dyn_arr {
|
||||
char **data;
|
||||
int used;
|
||||
int size;
|
||||
};
|
||||
|
||||
extern struct char_dyn_arr *init_char_dyn_arr(int size);
|
||||
extern int insert_char_dyn_arr(struct char_dyn_arr *a, char *e);
|
||||
extern void free_char_dyn_arr(struct char_dyn_arr *a);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _pp_args
|
||||
#define _pp_args
|
||||
|
||||
#include "pp.h"
|
||||
#include "char_dyn_arr.h"
|
||||
|
||||
struct args {
|
||||
struct char_dyn_arr *inc_dirs;
|
||||
char *in_file;
|
||||
char *out_file;
|
||||
};
|
||||
|
||||
extern void pp_free_args(struct args *args);
|
||||
extern struct args *pp_parse_args(int argc, char **argv, string_map_t define_map);
|
||||
|
||||
#endif
|
|
@ -1,3 +1,5 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _pp_defines_h
|
||||
#define _pp_defines_h
|
||||
|
||||
|
@ -7,6 +9,7 @@
|
|||
#define PP_FAILED -3
|
||||
#define PP_OMEM -4
|
||||
#define PP_BAD_FILE_OP -5
|
||||
#define PP_BAD_ARGS -6
|
||||
|
||||
extern int pp_errno;
|
||||
|
||||
|
|
3
pp.c
3
pp.c
|
@ -264,6 +264,9 @@ int pp_create_file_without_defines(FILE *in, FILE *out)
|
|||
line = NULL;
|
||||
len = 0;
|
||||
|
||||
is_inside_multiline_define = 0;
|
||||
prev_is_inside_multiline_define = 0;
|
||||
|
||||
while ((read = getline(&line, &len, in)) != -1) {
|
||||
|
||||
stripped_line = strdup(line);
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
|
||||
#include "pp_args.h"
|
||||
#include "pp_defines.h"
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DEFINE_FLAG "-D"
|
||||
#define DEFINE_FLAG_SZ (sizeof(DEFINE_FLAG) - 1)
|
||||
|
||||
#define INCLUDE_FLAG "-I"
|
||||
#define INCLUDE_FLAG_SZ (sizeof(INCLUDE_FLAG) - 1)
|
||||
|
||||
#define OUTPUT_FLAG "-o"
|
||||
#define OUTPUT_FLAG_SZ (sizeof(OUTPUT_FLAG) - 1)
|
||||
|
||||
int _is_split_define_flag(char *flag)
|
||||
{
|
||||
return !strncmp(flag, DEFINE_FLAG, DEFINE_FLAG_SZ)
|
||||
&& strlen(flag) == DEFINE_FLAG_SZ;
|
||||
}
|
||||
|
||||
int _is_tied_define_flag(char *flag)
|
||||
{
|
||||
return !strncmp(flag, DEFINE_FLAG, DEFINE_FLAG_SZ)
|
||||
&& strlen(flag) != DEFINE_FLAG_SZ;
|
||||
}
|
||||
|
||||
int _is_include_flag(char *flag)
|
||||
{
|
||||
return !strncmp(flag, INCLUDE_FLAG, INCLUDE_FLAG_SZ);
|
||||
}
|
||||
|
||||
int _is_output_flag(char *flag)
|
||||
{
|
||||
return !strncmp(flag, OUTPUT_FLAG, OUTPUT_FLAG_SZ);
|
||||
}
|
||||
|
||||
int _is_in_out_file_arg(char *prev_flag)
|
||||
{
|
||||
return !_is_split_define_flag(prev_flag) && !_is_include_flag(prev_flag)
|
||||
&& !_is_output_flag(prev_flag);
|
||||
}
|
||||
|
||||
int _is_unrecognized_flag(char *flag)
|
||||
{
|
||||
return flag[0] == '-' && !_is_split_define_flag(flag)
|
||||
&& !_is_include_flag(flag) && !_is_output_flag(flag);
|
||||
}
|
||||
|
||||
int _calloc_and_check(char **p, int sz)
|
||||
{
|
||||
*p = calloc(sz, sizeof(char));
|
||||
if (!(*p)) {
|
||||
pp_errno = PP_OMEM;
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int _add_sym_mapp_to_map(string_map_t define_map, char *sym_mapp)
|
||||
{
|
||||
char *sym;
|
||||
char *mapp;
|
||||
char *eq_pos;
|
||||
|
||||
int sym_len;
|
||||
int mapp_len;
|
||||
|
||||
int ret;
|
||||
int res;
|
||||
|
||||
if (!strstr(sym_mapp, "=")) {
|
||||
res = hashmap_put(define_map, sym_mapp, "");
|
||||
if (res != MAP_OK)
|
||||
return PP_FAILED;
|
||||
else
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
sym = NULL;
|
||||
mapp = NULL;
|
||||
|
||||
eq_pos = strstr(sym_mapp, "=");
|
||||
sym_len = eq_pos - sym_mapp;
|
||||
|
||||
ret = _calloc_and_check(&sym, sym_len + 1);
|
||||
if (ret == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
|
||||
strncpy(sym, sym_mapp, sym_len);
|
||||
|
||||
eq_pos++;
|
||||
mapp_len = strlen(eq_pos);
|
||||
|
||||
ret = _calloc_and_check(&mapp, mapp_len + 1);
|
||||
if (ret == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
|
||||
strncpy(mapp, eq_pos, mapp_len);
|
||||
|
||||
ret = hashmap_put(define_map, sym, mapp);
|
||||
|
||||
if (ret == MAP_OK)
|
||||
return PP_OK;
|
||||
else
|
||||
return PP_FAILED;
|
||||
|
||||
free_and_exit:
|
||||
free(sym);
|
||||
free(mapp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct args *_create_struct_args(void)
|
||||
{
|
||||
struct args *ret;
|
||||
|
||||
ret = NULL;
|
||||
|
||||
ret = calloc(1, sizeof(struct args));
|
||||
if (!ret)
|
||||
goto free_and_exit;
|
||||
|
||||
ret->inc_dirs = init_char_dyn_arr(2);
|
||||
if (!(ret->inc_dirs))
|
||||
goto free_and_exit;
|
||||
|
||||
return ret;
|
||||
|
||||
free_and_exit:
|
||||
free_char_dyn_arr(ret->inc_dirs);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _collect_inc_dirs(struct args *args, char *inc_dir)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = insert_char_dyn_arr(args->inc_dirs, inc_dir);
|
||||
|
||||
if (res == CHAR_DYN_ARR_OK)
|
||||
return PP_OK;
|
||||
else
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
int _add_in_file_to_args(struct args *args, char *in_file)
|
||||
{
|
||||
char *alloc_in_file;
|
||||
|
||||
int in_file_len;
|
||||
int res;
|
||||
|
||||
in_file_len = strlen(in_file);
|
||||
res = _calloc_and_check(&alloc_in_file, in_file_len + 1);
|
||||
if (res == PP_FAILED)
|
||||
return PP_FAILED;
|
||||
|
||||
strncpy(alloc_in_file, in_file, in_file_len);
|
||||
|
||||
args->in_file = alloc_in_file;
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int _add_out_file_to_args(struct args *args, char *out_file)
|
||||
{
|
||||
char *alloc_out_file;
|
||||
|
||||
int out_file_len;
|
||||
int res;
|
||||
|
||||
out_file_len = strlen(out_file);
|
||||
res = _calloc_and_check(&alloc_out_file, out_file_len + 1);
|
||||
if (res == PP_FAILED)
|
||||
return PP_FAILED;
|
||||
|
||||
strncpy(alloc_out_file, out_file, out_file_len);
|
||||
|
||||
args->out_file = alloc_out_file;
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
struct args *pp_parse_args(int argc, char **argv, string_map_t define_map)
|
||||
{
|
||||
struct args *args;
|
||||
|
||||
char *sym_mapp;
|
||||
|
||||
int i;
|
||||
int in_file_found;
|
||||
int out_file_found;
|
||||
int is_flag;
|
||||
int res;
|
||||
|
||||
args = _create_struct_args();
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
in_file_found = 0;
|
||||
out_file_found = 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
is_flag = 0;
|
||||
|
||||
if (_is_unrecognized_flag(argv[i])) {
|
||||
pp_errno = PP_BAD_ARGS;
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
if (_is_split_define_flag(argv[i])) {
|
||||
if (i + 1 < argc) {
|
||||
res = _add_sym_mapp_to_map(define_map, argv[i + 1]);
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
is_flag = 1;
|
||||
} else {
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (_is_tied_define_flag(argv[i])) {
|
||||
sym_mapp = argv[i] + DEFINE_FLAG_SZ;
|
||||
|
||||
res = _add_sym_mapp_to_map(define_map, sym_mapp);
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
is_flag = 1;
|
||||
}
|
||||
|
||||
if (_is_include_flag(argv[i])) {
|
||||
if (i + 1 < argc) {
|
||||
res = _collect_inc_dirs(args, argv[i + 1]);
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
is_flag = 1;
|
||||
} else {
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (_is_output_flag(argv[i])) {
|
||||
if (i + 1 < argc) {
|
||||
res = _add_out_file_to_args(args, argv[i]);
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
is_flag = 1;
|
||||
} else {
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_flag && !in_file_found && i - 1 >= 0 && _is_in_out_file_arg(argv[i - 1])) {
|
||||
res = _add_in_file_to_args(args, argv[i]);
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
|
||||
in_file_found = 1;
|
||||
} else if (!is_flag && in_file_found && i - 1 >= 0 && _is_in_out_file_arg(argv[i - 1])) {
|
||||
if (out_file_found) {
|
||||
pp_errno = PP_BAD_ARGS;
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
res = _add_out_file_to_args(args, argv[i]);
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
out_file_found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
|
||||
free_and_exit:
|
||||
pp_free_args(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pp_free_args(struct args *args)
|
||||
{
|
||||
if (!args)
|
||||
return;
|
||||
|
||||
free_char_dyn_arr(args->inc_dirs);
|
||||
free(args->in_file);
|
||||
free(args->out_file);
|
||||
free(args);
|
||||
}
|
Loading…
Reference in New Issue