c-preprocessor/expand_line.c

249 lines
4.6 KiB
C

#include "expand_line.h"
#include "utils.h"
#include <string.h>
#include <stdlib.h>
#define DELIMS "\t []{}<>=+-*/%!&|^.,:;()\\"
char *_compute_expanded_line(void *def_map, char *line);
int _concat_expanded_token_to_line(void *def_map, char *token, char **line);
int _concat_delim_to_line(char *delim, int delim_size, char **line);
char *_get_expanded_token(void *def_map, char *token);
int _concat_delim_to_line(char *delim, int delim_size, char **line);
int _concat_expanded_token_to_line(void *def_map, char *token, char **line);
int _is_delim_at_str_start(char *token, char *str_start);
int _compute_delim_start(char *token, char *line);
int _compute_delim_end(char *token, char *line, char *line_copy);
int write_expanded_line(void *def_map, char *line, FILE *out)
{
char *exp_line;
int line_len;
int ret;
exp_line = get_expanded_line(def_map, line);
if (!exp_line)
return PP_FAILED;
line_len = strlen(exp_line);
ret = fprintf(out, "%s", exp_line);
free(exp_line);
if (ret < 0)
return PP_FAILED;
return ret == line_len ? PP_OK : PP_FAILED;
}
char *get_expanded_line(void *def_map, char *line)
{
char *exp_line;
char *prev_exp_line;
exp_line = NULL;
prev_exp_line = NULL;
exp_line = _compute_expanded_line(def_map, line);
if (!exp_line)
return NULL;
prev_exp_line = l_strdup(line);
if (!prev_exp_line)
goto free_and_exit;
while (strcmp(prev_exp_line, exp_line)) {
free(prev_exp_line);
prev_exp_line = exp_line;
exp_line = _compute_expanded_line(def_map, prev_exp_line);
if (!exp_line)
goto free_and_exit;
}
free(prev_exp_line);
return exp_line;
free_and_exit:
free(prev_exp_line);
free(exp_line);
return NULL;
}
char *_compute_expanded_line(void *def_map, char *line)
{
char *_line;
char *line_start;
char *line_copy;
char *token;
char *exp_line;
int delim_start;
int delim_end;
int ret;
int token_len;
_line = NULL;
line_copy = NULL;
exp_line = NULL;
_line = l_strdup(line);
if (!_line)
goto free_and_exit;
line_start = _line;
line_copy = l_strdup(_line);
if (!line_copy)
goto free_and_exit;
exp_line = calloc(1, sizeof(char));
if (!exp_line)
goto free_and_exit;
token = strtok(_line, DELIMS);
if (_is_delim_at_str_start(token, line_start)) {
ret = _concat_delim_to_line(
line_start,
token - line_start,
&exp_line
);
if (ret == PP_FAILED)
goto free_and_exit;
}
ret = _concat_expanded_token_to_line(def_map, token, &exp_line);
if (ret == PP_FAILED)
goto free_and_exit;
while (token) {
delim_start = _compute_delim_start(token, _line);
token = strtok(NULL, DELIMS);
delim_end = _compute_delim_end(token, _line, line_copy);
ret = _concat_delim_to_line(
line_copy + delim_start,
delim_end - delim_start,
&exp_line
);
if (ret == PP_FAILED)
goto free_and_exit;
if (token) {
token_len = strlen(token);
if (token[token_len - 1] == '\n')
token[token_len - 1] = 0x00;
_concat_expanded_token_to_line(
def_map,
token,
&exp_line
);
if (token[token_len - 1] == 0x00) {
token[token_len - 1] = '\n';
_concat_delim_to_line("\n", 1, &exp_line);
}
if (ret == PP_FAILED)
goto free_and_exit;
} else {
break;
}
}
free(line_copy);
free(_line);
return exp_line;
free_and_exit:
free(_line);
free(line_copy);
free(exp_line);
return NULL;
}
char *_get_expanded_token(void *def_map, char *token)
{
char *exp;
char *exp_copy;
int ret;
int token_len;
exp = NULL;
exp_copy = NULL;
ret = hashmap_get(def_map, token, &exp);
if (ret != MAP_OK) {
token_len = strlen(token);
exp_copy = calloc(token_len + 1, sizeof(char));
if (!exp_copy)
goto free_and_exit;
strcpy(exp_copy, token);
} else {
exp_copy = l_strdup(exp);
if (!exp_copy)
goto free_and_exit;
}
return exp_copy;
free_and_exit:
free(exp_copy);
return NULL;
}
int _concat_delim_to_line(char *delim, int delim_size, char **line)
{
char *_delim;
int ret;
_delim = NULL;
_delim = calloc(delim_size + 1, sizeof(char));
if (!_delim)
return PP_FAILED;
strncpy(_delim, delim, delim_size);
ret = a_strcat(line, _delim);
free(_delim);
return ret == -1 ? PP_FAILED : PP_OK;
}
int _concat_expanded_token_to_line(void *def_map, char *token, char **line)
{
char *exp;
int ret;
exp = _get_expanded_token(def_map, token);
if (!exp)
return PP_FAILED;
ret = a_strcat(line, exp);
free(exp);
return ret == -1 ? PP_FAILED : PP_OK;
}
int _is_delim_at_str_start(char *token, char *str_start)
{
return token - str_start;
}
int _compute_delim_start(char *token, char *line)
{
return token - line + strlen(token);
}
int _compute_delim_end(char *token, char *line, char *line_copy)
{
return token != NULL ? token - line : (int) strlen(line_copy);
}