commit
d5b883d06a
|
@ -4,7 +4,7 @@ LIBRARY=none
|
|||
INCPATHS=include
|
||||
LIBPATHS=
|
||||
LDFLAGS=
|
||||
CCFLAGS=-c -Wall -g -Wextra -Werror -pedantic-errors
|
||||
CCFLAGS=-c -Wall -g -Wextra -Werror -pedantic-errors -std=c89
|
||||
CC=gcc
|
||||
CODING_STYLE_CHECKER=checkpatch_wrapper.sh
|
||||
|
||||
|
@ -13,10 +13,10 @@ OBJECTS=$(SOURCES:.c=.o)
|
|||
INCFLAGS=$(foreach TMP,$(INCPATHS),-I$(TMP))
|
||||
LIBFLAGS=$(foreach TMP,$(LIBPATHS),-L$(TMP))
|
||||
|
||||
all: $(SOURCES) $(OUTPUT)
|
||||
build: $(SOURCES) $(OUTPUT)
|
||||
|
||||
coding_style:
|
||||
./$(CODING_STYLE_CHECKER) $(SOURCES) $(INCPATHS)/*
|
||||
./$(CODING_STYLE_CHECKER)
|
||||
|
||||
$(OUTPUT): $(OBJECTS)
|
||||
$(CC) $(LIBFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
L=link
|
||||
OUTPUT=so-cpp
|
||||
SOURCES=expand_line.c hashmap.c line_handler.c pp.c pp_args.c pp_define.c pp_if.c pp_ifdef.c pp_inc.c so-cpp.c str_dyn_arr.c utils.c
|
||||
LIBRARY=none
|
||||
INCPATHS=include
|
||||
CCFLAGS=/c /Wall /Zi /W4 /MD /nologo /D_CRT_SECURE_NO_WARNINGS
|
||||
CC=cl
|
||||
CODING_STYLE_CHECKER=checkpatch_wrapper.exe
|
||||
|
||||
OBJECTS=$(SOURCES:.c=.obj)
|
||||
|
||||
INCFLAGS=/Iinclude
|
||||
|
||||
build: $(SOURCES) $(OUTPUT)
|
||||
|
||||
coding_style:
|
||||
./$(CODING_STYLE_CHECKER) $(SOURCES) $(INCPATHS)/*
|
||||
|
||||
$(OUTPUT): $(OBJECTS)
|
||||
$(L) /nologo /out:$(OUTPUT) $(OBJECTS)
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(INCFLAGS) $(CCFLAGS) *.c
|
||||
|
||||
clean:
|
||||
del /Q /F $(OUTPUT) $(OBJECTS)
|
|
@ -0,0 +1,17 @@
|
|||
.PHONY: all clean run pack build-pre build-post
|
||||
|
||||
all: build-pre run build-post
|
||||
|
||||
build-pre:
|
||||
|
||||
build-post:
|
||||
|
||||
run:
|
||||
@./run_all.sh
|
||||
|
||||
pack:
|
||||
zip -r run_test_lin.zip _test/ Makefile.checker \
|
||||
run_all.sh README
|
||||
|
||||
clean:
|
||||
rm -f *~
|
|
@ -0,0 +1 @@
|
|||
file passed through stdin
|
|
@ -0,0 +1 @@
|
|||
bad.file
|
|
@ -0,0 +1,10 @@
|
|||
#define ABC "10"
|
||||
#define BCD 20 + 4
|
||||
|
||||
int main() {
|
||||
printf("%s\n", ABC);
|
||||
int x = BCD + 20;
|
||||
printf("%x\n", x);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#define ABC 10
|
||||
#define ABCD 2
|
||||
#define BCD ABC + 15
|
||||
|
||||
int main() {
|
||||
printf("%d\n", ABC);
|
||||
int x = BCD + 20;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#define VAR0 1 \
|
||||
+ 2\
|
||||
+ 3\
|
||||
+ 4
|
||||
|
||||
int main() {
|
||||
int y = VAR0 + 1;
|
||||
printf("%d\n", VAR0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
int main() {
|
||||
#if 1
|
||||
printf("Yes!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
int main() {
|
||||
#if 0
|
||||
printf("No!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#define TEST 1
|
||||
|
||||
int main() {
|
||||
#if TEST
|
||||
printf("Yes!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#define TEST 0
|
||||
|
||||
int main() {
|
||||
#if TEST
|
||||
printf("Yes!\n");
|
||||
#endif
|
||||
return 0
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
int main() {
|
||||
#if 1
|
||||
printf("True!\n");
|
||||
#else
|
||||
printf("False!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
int main() {
|
||||
#if 0
|
||||
printf("True!\n");
|
||||
#else
|
||||
printf("False!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#define TEST 1
|
||||
|
||||
int main() {
|
||||
#if TEST
|
||||
printf("True!\n");
|
||||
#else
|
||||
printf("False!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
-X bad param
|
|
@ -0,0 +1,9 @@
|
|||
int main() {
|
||||
#if TEST
|
||||
printf("True!\n");
|
||||
#else
|
||||
printf("False!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
-D TEST=0
|
|
@ -0,0 +1,12 @@
|
|||
#define FALSE 0
|
||||
#define NOT 0
|
||||
#define TRUE 1
|
||||
|
||||
int main() {
|
||||
#if FALSE
|
||||
printf("False!\n");
|
||||
#elif NOT
|
||||
printf("True!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#define FALSE 0
|
||||
#define NOT 0
|
||||
#define TRUE 1
|
||||
|
||||
int main() {
|
||||
#if FALSE
|
||||
printf("False!\n");
|
||||
#elif TRUE
|
||||
printf("True!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#define FALSE 0
|
||||
#define NOT 0
|
||||
#define TRUE 1
|
||||
|
||||
int main() {
|
||||
#if FALSE
|
||||
printf("False!\n");
|
||||
#elif TRUE
|
||||
printf("True!\n");
|
||||
#else
|
||||
printf("Bad!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#define FALSE 0
|
||||
#define NOT 0
|
||||
#define TRUE 1
|
||||
|
||||
int main() {
|
||||
#if FALSE
|
||||
printf("False!\n");
|
||||
#elif NOT
|
||||
printf("True!\n");
|
||||
#else
|
||||
printf("Good!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#define VAR0 1
|
||||
#define TEST_IF 5
|
||||
|
||||
int main() {
|
||||
#if 0
|
||||
printf("No\n");
|
||||
#elif 0
|
||||
printf("Maybe\n");
|
||||
#elif VAR0
|
||||
printf("ABC\n");
|
||||
#else
|
||||
printf("Yes\n");
|
||||
#endif
|
||||
|
||||
#if TEST_IF
|
||||
printf("#defines working in #ifs\n");
|
||||
#endif
|
||||
|
||||
int y = VAR0 + 1;
|
||||
printf("%d\n", VAR0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
int main()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("DEBUG\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
int main()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("DEBUG\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
-DDEBUG
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef VAR0
|
||||
#define VAR0 1
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("VAR0 = %d\n", VAR0);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifdef VAR0
|
||||
#undef VAR0
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("VAR0 = %d\n", VAR0);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
-D VAR0
|
|
@ -0,0 +1 @@
|
|||
input error file
|
|
@ -0,0 +1 @@
|
|||
_test/inputs/test3.in test3.out test3.err
|
|
@ -0,0 +1,6 @@
|
|||
#include "no-file.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
_test/inputs/test30.in
|
|
@ -0,0 +1,5 @@
|
|||
int main()
|
||||
{
|
||||
printf("%d\n", VAR0 + VAR1);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
-D VAR0=0 -D VAR1=1
|
|
@ -0,0 +1 @@
|
|||
int var;
|
|
@ -0,0 +1,7 @@
|
|||
#include "test32.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("var = %d\n", var);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int var;
|
|
@ -0,0 +1,7 @@
|
|||
#include "test33.dir/test33.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("var = %d\n", var);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int var;
|
|
@ -0,0 +1,8 @@
|
|||
#include "test34.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("var = %d\n", var);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
-I _test/inputs/test34.dir
|
|
@ -0,0 +1 @@
|
|||
#define VAR 1
|
|
@ -0,0 +1 @@
|
|||
#define VAR 2
|
|
@ -0,0 +1 @@
|
|||
#define VAR 0
|
|
@ -0,0 +1,8 @@
|
|||
#include "test35.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("VAR = %d\n", VAR);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
-I _test/inputs/test35.dir -I _test/inputs/test35.dir/test35.subdir
|
|
@ -0,0 +1 @@
|
|||
#define VAR 1
|
|
@ -0,0 +1 @@
|
|||
#define VAR 2
|
|
@ -0,0 +1,8 @@
|
|||
#include "test36.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("VAR = %d\n", VAR);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
-I _test/inputs/test36.dir -I _test/inputs/test36.dir/test36.subdir
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _TEST_33_H_
|
||||
#define _TEST_33_H_
|
||||
|
||||
int var;
|
||||
|
||||
#endif /* TEST_33_H_ */
|
|
@ -0,0 +1,7 @@
|
|||
#include "test37.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("var = %d\n", var);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
#ifndef DEBUG_STR
|
||||
#define DEBUG_STR "debuging"
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#define debug fprintf(stderr, DEBUG_STR "\n")
|
||||
#else
|
||||
#define debug
|
||||
#endif
|
||||
|
||||
#endif /* _DEBUG_H_ */
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef _TEST38_H_
|
||||
#define _TEST38_H_
|
||||
|
||||
#ifdef CUSTOM_DBG
|
||||
#define DEBUG_STR CUSTOM_DBG
|
||||
#else
|
||||
#define DEBUG_STR "my debugging"
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#endif /* _TEST38_H_ */
|
|
@ -0,0 +1 @@
|
|||
-D DEBUG=1 -D CUSTOM_DBG=custom-debugging -I _test/inputs/test38.dir
|
|
@ -0,0 +1 @@
|
|||
file passed through standard input
|
|
@ -0,0 +1 @@
|
|||
file passed through parameter
|
|
@ -0,0 +1 @@
|
|||
file passed as output
|
|
@ -0,0 +1,8 @@
|
|||
#define VAR0 1
|
||||
|
||||
int main() {
|
||||
int y = VAR0 + 1;
|
||||
printf("%d\n", VAR0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
int main() {
|
||||
int y = VAR0 + 1;
|
||||
printf("%d\n", VAR0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
-D VAR0=1
|
|
@ -0,0 +1,10 @@
|
|||
#define VAR0 1
|
||||
|
||||
int main() {
|
||||
int y = VAR0 + 1;
|
||||
printf("%d\n", VAR0);
|
||||
#undef VAR0
|
||||
printf("%d\n", VAR0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,254 @@
|
|||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Tema1 Test Suite
|
||||
#
|
||||
# 2020, Operating Systems
|
||||
#
|
||||
|
||||
# ----------------- General declarations and util functions ------------------ #
|
||||
INPUT_DIR=_test/inputs
|
||||
REF_DIR=_test/ref
|
||||
OUT_DIR=_test/outputs
|
||||
EXEC_NAME=./so-cpp
|
||||
|
||||
max_points=95
|
||||
|
||||
TEST_LIB=_test/test_lib.sh
|
||||
|
||||
MEMCHECK=""
|
||||
CPP="cpp -P"
|
||||
[ $(uname -s) == "Linux" ]
|
||||
IS_LINUX=$?
|
||||
|
||||
if [ $IS_LINUX -eq 0 ]; then
|
||||
MEMCHECK="valgrind --leak-check=full \
|
||||
--show-reachable=yes \
|
||||
--vex-iropt-register-updates=allregs-at-mem-access \
|
||||
--show-leak-kinds=all \
|
||||
--error-exitcode=1 \
|
||||
$MEMCHECK_EXTRA \
|
||||
--log-file=_log "
|
||||
else
|
||||
MEMCHECK="drmemory -batch \
|
||||
-exit_code_if_errors 1 \
|
||||
-quiet \
|
||||
$MEMCHECK_EXTRA \
|
||||
-- "
|
||||
fi
|
||||
|
||||
|
||||
# load the lib functions
|
||||
if ! [ -e "$TEST_LIB" ]; then
|
||||
echo "Test library not found. Check \$TEST_LIB ($TEST_LIB)"
|
||||
exit 1
|
||||
fi
|
||||
source "$TEST_LIB"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
# ----------------- Init and cleanup tests ----------------------------------- #
|
||||
|
||||
init_test()
|
||||
{
|
||||
if ! [ -e "$EXEC_NAME" ]; then
|
||||
echo "$EXEC_NAME not found! Cannot run the test"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
unset malloc_limit
|
||||
unset calloc_limit
|
||||
unset realloc_limit
|
||||
|
||||
input_f=$INPUT_DIR"/test"$test_index".in"
|
||||
param_f=$INPUT_DIR"/test"$test_index".param"
|
||||
ref_f=$OUT_DIR"/test"$test_index".ref"
|
||||
out_f=$OUT_DIR"/test"$test_index".out"
|
||||
params="$(test -f $param_f && cat $param_f || echo "")"
|
||||
}
|
||||
|
||||
cleanup_test()
|
||||
{
|
||||
rm -f $out_f
|
||||
}
|
||||
|
||||
init_world()
|
||||
{
|
||||
print_header "Testing - SO Preprocessor"
|
||||
mkdir -p $OUT_DIR
|
||||
}
|
||||
|
||||
cleanup_world()
|
||||
{
|
||||
rm -rf $OUT_DIR &> /dev/null
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
# ----------------- Test Suite ----------------------------------------------- #
|
||||
|
||||
test_cpp()
|
||||
{
|
||||
init_test
|
||||
$CPP $params $input_f > $ref_f
|
||||
$MEMCHECK $EXEC_NAME $params $input_f > $out_f
|
||||
mem_res=$?
|
||||
basic_test compare $out_f $ref_f
|
||||
memory_test $mem_res
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
test_cpp_stdin()
|
||||
{
|
||||
init_test
|
||||
$CPP $params < $input_f > $ref_f
|
||||
$MEMCHECK $EXEC_NAME $params < $input_f > $out_f
|
||||
mem_res=$?
|
||||
basic_test compare $out_f $ref_f
|
||||
memory_test $mem_res
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
test_cpp_stdout()
|
||||
{
|
||||
init_test
|
||||
$CPP $params $input_f $ref_f
|
||||
$MEMCHECK $EXEC_NAME $params $input_f $out_f
|
||||
mem_res=$?
|
||||
basic_test compare $out_f $ref_f
|
||||
memory_test $mem_res
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
test_bad_params()
|
||||
{
|
||||
init_test
|
||||
$EXEC_NAME $params 2> /dev/null
|
||||
basic_test test $? -ne 0
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
run_until_success()
|
||||
{
|
||||
REF_CODE=12 # ENOMEM
|
||||
NR_RUNS=1000 # How many times to run
|
||||
|
||||
for ((i = 0; i < $NR_RUNS; i++)); do
|
||||
init_test
|
||||
export "$1_limit"=$i
|
||||
if [ $IS_LINUX -eq 0 ]; then
|
||||
LD_PRELOAD="./libso.so" $EXEC_NAME $params $input_f > $out_f
|
||||
else
|
||||
"./run.exe" "$EXEC_NAME $params $input_f" > $out_f
|
||||
fi
|
||||
|
||||
retcode=$?
|
||||
|
||||
# If there is no error then the output file must be checked
|
||||
if test $retcode -eq 0; then
|
||||
return $?
|
||||
fi
|
||||
|
||||
if test $retcode -ne $REF_CODE; then
|
||||
basic_test false
|
||||
return -1
|
||||
fi
|
||||
|
||||
if test $1 != "realloc"; then
|
||||
cleanup_test
|
||||
fi
|
||||
|
||||
done
|
||||
basic_test false
|
||||
return -1
|
||||
}
|
||||
|
||||
test_so_alloc()
|
||||
{
|
||||
if [ $IS_LINUX -eq 0 ]; then
|
||||
lines=$(find . -maxdepth 1 -name "libso.so" | wc -l)
|
||||
else
|
||||
lines=$(find . -maxdepth 1 -name "run.exe" | wc -l)
|
||||
fi
|
||||
|
||||
if [ $lines -eq 0 ]; then
|
||||
basic_test false
|
||||
else
|
||||
|
||||
init_test
|
||||
$CPP $input_f $params > $ref_f
|
||||
|
||||
run_until_success "malloc"
|
||||
if test $? -ne 0; then
|
||||
return
|
||||
fi
|
||||
|
||||
run_until_success "calloc"
|
||||
if test $? -ne 0; then
|
||||
return
|
||||
fi
|
||||
|
||||
run_until_success "realloc"
|
||||
|
||||
basic_test compare $out_f $ref_f
|
||||
|
||||
cleanup_test
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
test_fun_array=( \
|
||||
test_coding_style "Sources check" 5 0 \
|
||||
test_bad_params "Test bad input" 1 0 \
|
||||
test_bad_params "Test bad parameters" 1 0 \
|
||||
test_bad_params "Test multiple files" 1 0 \
|
||||
test_cpp_stdin "Test stdin file" 1 1 \
|
||||
test_cpp "Test simple file" 1 1 \
|
||||
test_cpp_stdout "Test simple out file" 1 1 \
|
||||
test_cpp "Test simple define" 2 1 \
|
||||
test_cpp "Test param define" 2 1 \
|
||||
test_cpp "Test simple define/undef" 2 1 \
|
||||
test_cpp "Test multiple defines" 2 1 \
|
||||
test_cpp "Test nested defines" 3 1 \
|
||||
test_cpp "Test multi-lines defines" 2 1 \
|
||||
test_cpp "Test simple if true" 1 1 \
|
||||
test_cpp "Test simple if false" 1 1 \
|
||||
test_cpp "Test define if true" 1 1 \
|
||||
test_cpp "Test define if false" 1 1 \
|
||||
test_cpp "Test simple if-else true" 1 1 \
|
||||
test_cpp "Test simple if-else false" 1 1 \
|
||||
test_cpp "Test define if-else true" 1 1 \
|
||||
test_cpp "Test define param if-else false" 1 1 \
|
||||
test_cpp "Test simple elif false" 1 1 \
|
||||
test_cpp "Test simple elif true" 1 1 \
|
||||
test_cpp "Test simple elif-else true" 1 1 \
|
||||
test_cpp "Test simple elif-else false" 1 1 \
|
||||
test_cpp "Test complex if-elif-else" 2 1 \
|
||||
test_cpp "Test simple ifdef false" 1 1 \
|
||||
test_cpp "Test simple ifdef true" 1 1 \
|
||||
test_cpp "Test simple ifndef" 1 1 \
|
||||
test_cpp "Test simple ifndef undef" 1 1 \
|
||||
test_bad_params "Test bad include" 1 0 \
|
||||
test_cpp "Test double define params" 1 1 \
|
||||
test_cpp "Test simple include" 2 1 \
|
||||
test_cpp "Test include directory" 1 1 \
|
||||
test_cpp "Test include param" 1 1 \
|
||||
test_cpp "Test include order" 1 1 \
|
||||
test_cpp "Test include order no main" 1 1 \
|
||||
test_cpp "Test include guard" 2 1 \
|
||||
test_so_alloc "Test everything" 10 0 \
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
# ----------------- Run test ------------------------------------------------- #
|
||||
|
||||
# first we check if we have everything defined
|
||||
check_tests
|
||||
|
||||
# run tests
|
||||
run_tests $@
|
||||
|
||||
exit 0
|
|
@ -0,0 +1,229 @@
|
|||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Tema1 Test Suite
|
||||
#
|
||||
# 2012-2018, Operating Systems
|
||||
#
|
||||
|
||||
# ----------------- General declarations and util functions ------------------ #
|
||||
|
||||
# Enable/disable exiting when program fails.
|
||||
EXIT_IF_FAIL=0
|
||||
# Enable/disable debug (1/0).
|
||||
DEBUG_=0
|
||||
# checkpatch.pl URL
|
||||
CHECKPATCH_URL="https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl"
|
||||
COMMON_IGNORE_FLAGS="
|
||||
SPLIT_STRING,SSCANF_TO_KSTRTO,NEW_TYPEDEFS,VOLATILE,INLINE,USE_FUNC,AVOID_EXTERNS,CONST_STRUCT,SPDX_LICENSE_TAG"
|
||||
LIN_IGNORE_FLAGS="$COMMON_IGNORE_FLAGS"
|
||||
WIN_IGNORE_FLAGS="$COMMON_IGNORE_FLAGS,DOS_LINE_ENDINGS"
|
||||
|
||||
if [ $(uname -s) == "Linux" ]; then
|
||||
CHECKPATCH_IGNORE_FLAGS=$LIN_IGNORE_FLAGS
|
||||
else
|
||||
CHECKPATCH_IGNORE_FLAGS=$WIN_IGNORE_FLAGS
|
||||
fi
|
||||
|
||||
CHECKPATCH_ARGS="
|
||||
--no-tree
|
||||
--no-summary
|
||||
--terse
|
||||
--ignore $CHECKPATCH_IGNORE_FLAGS
|
||||
--show-types"
|
||||
|
||||
DEBUG()
|
||||
{
|
||||
if test "x$DEBUG_" = "x1"; then
|
||||
$@ 1>&2
|
||||
fi
|
||||
}
|
||||
|
||||
print_header()
|
||||
{
|
||||
header="${1}"
|
||||
header_len=${#header}
|
||||
printf "\n"
|
||||
if [ $header_len -lt 71 ]; then
|
||||
padding=$(((71 - $header_len) / 2))
|
||||
for ((i = 0; i < $padding; i++)); do
|
||||
printf " "
|
||||
done
|
||||
fi
|
||||
printf "= %s =\n\n" "${header}"
|
||||
}
|
||||
|
||||
|
||||
test_do_fail()
|
||||
{
|
||||
printf "failed [ 0/%02d]\n" "$max_points"
|
||||
if test "x$EXIT_IF_FAIL" = "x1"; then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
test_do_pass()
|
||||
{
|
||||
printf "passed [%02d/%02d]\n" "$1" "$max_points"
|
||||
}
|
||||
|
||||
|
||||
DF=${DF:--BEbwu}
|
||||
|
||||
# Compares to files and prints the first 10
|
||||
# lines if the files differ
|
||||
function compare()
|
||||
{
|
||||
diff $DF $1 $2 > __result
|
||||
ret=$?
|
||||
if [ $ret != 0 ] ; then
|
||||
echo "$1 vs $2:"
|
||||
cat __result | head -n 10
|
||||
fi
|
||||
rm -f __result
|
||||
return $ret
|
||||
}
|
||||
|
||||
memory_test()
|
||||
{
|
||||
DEBUG echo "MEM TEST"
|
||||
|
||||
res=$1
|
||||
memcheck_description="$description - memcheck"
|
||||
printf "%02d) %s" "$test_index" "$memcheck_description"
|
||||
|
||||
for ((i = 0; i < 56 - ${#memcheck_description}; i++)); do
|
||||
printf "."
|
||||
done
|
||||
|
||||
if test $res -eq 0; then
|
||||
test_do_pass "$mem_points"
|
||||
else
|
||||
test_do_fail "$mem_poits"
|
||||
fi
|
||||
}
|
||||
|
||||
basic_test()
|
||||
{
|
||||
DEBUG echo "TEST: $@"
|
||||
$@
|
||||
res=$?
|
||||
printf "%02d) %s" "$test_index" "$description"
|
||||
|
||||
for ((i = 0; i < 56 - ${#description}; i++)); do
|
||||
printf "."
|
||||
done
|
||||
|
||||
if test $res -eq 0; then
|
||||
test_do_pass "$points"
|
||||
return 0
|
||||
else
|
||||
test_do_fail "$points"
|
||||
return -1
|
||||
fi
|
||||
}
|
||||
|
||||
check_source()
|
||||
{
|
||||
# check to see if we have checkpatch
|
||||
check_patch=$(which checkpatch.pl 2> /dev/null)
|
||||
if ! [ -x "$check_patch" ]; then
|
||||
echo "'checkpatch.pl' tool not found on your system."\
|
||||
"Skipping source check..."
|
||||
echo "Please download 'checkpatch.pl' from '$CHECKPATCH_URL'"\
|
||||
"and install it in your \$PATH."
|
||||
echo
|
||||
return
|
||||
fi
|
||||
|
||||
# try to find sources in the current directory
|
||||
src_files="$(find "${SRC_DIR:-.}" -type f -iregex \
|
||||
'.*\.\(c\|h\|cpp\|hpp\|cc\|hh\|cxx\|hxx\)')"
|
||||
if [ -z "$src_files" ]; then
|
||||
read -t 60 -e -p 'Please provide path to your sources: ' SRC_DIR
|
||||
if [ "$?" -ne "0" -o -z "$SRC_DIR" ]; then
|
||||
echo -e "No path provided! Skipping source check...\n"
|
||||
return
|
||||
fi
|
||||
if ! [ -e "$SRC_DIR" ]; then
|
||||
echo -e "File or directory '$SRC_DIR' does not exist. " \
|
||||
"Skipping source check...\n"
|
||||
return
|
||||
fi
|
||||
src_files="$(find "$SRC_DIR" -type f -iregex \
|
||||
'.*\.\(c\|h\|cpp\|hpp\|cc\|hh\|cxx\|hxx\)')"
|
||||
if [ -z "$src_files" ]; then
|
||||
echo -e "No sources found in '$SRC_DIR'. " \
|
||||
"Skipping source check...\n"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
# now we have sources in $SRC_DIR or .
|
||||
OUT=$(find "${SRC_DIR:-.}" -type f -iregex \
|
||||
'.*\.\(c\|h\|cpp\|hpp\|cc\|hh\|cxx\|hxx\)' | \
|
||||
xargs $check_patch $CHECKPATCH_ARGS -f 2>&1 | tail -n +2 | \
|
||||
sort -u -t":" -k4,4 | head -n 20)
|
||||
echo "$OUT"
|
||||
}
|
||||
|
||||
test_coding_style()
|
||||
{
|
||||
check_source
|
||||
[ -n "$src_files" -a -z "$OUT" ]
|
||||
basic_test [ $? -eq 0 ]
|
||||
}
|
||||
|
||||
check_tests()
|
||||
{
|
||||
# we need to have the test_fun_array defined
|
||||
if [ -z "$test_fun_array" ]; then
|
||||
echo "test_fun_array is not defined - don't know what to run" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# max_points
|
||||
if [ -z "$max_points" ]; then
|
||||
echo "max_points is not defined - don't the total number of points" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_tests()
|
||||
{
|
||||
if test $# -ne 1; then
|
||||
echo "Usage: $0 test_number | init | cleanup" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test_index=$1
|
||||
|
||||
if test $test_index == "init"; then
|
||||
init_world
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test $test_index == "cleanup"; then
|
||||
cleanup_world
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test $test_index == "check"; then
|
||||
check_source
|
||||
exit 0
|
||||
fi
|
||||
|
||||
arr_index=$(($test_index * 4))
|
||||
last_test=$((${#test_fun_array[@]} / 4))
|
||||
description=${test_fun_array[$(($arr_index + 1))]}
|
||||
|
||||
points=${test_fun_array[$(($arr_index + 2))]}
|
||||
mem_points=${test_fun_array[$(($arr_index + 3))]}
|
||||
|
||||
if test "$test_index" -gt "$last_test" -o "$arr_index" -lt 0; then
|
||||
echo "Error: Test index is out range (1 < test_index <= $last_test)." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run proper function
|
||||
${test_fun_array[$(($arr_index))]}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
#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);
|
||||
}
|
||||
|
28
hashmap.c
28
hashmap.c
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#include <hashmap.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -19,7 +19,7 @@ struct hashmap_map {
|
|||
struct hashmap_elem *data;
|
||||
};
|
||||
|
||||
string_map_t hashmap_new(void)
|
||||
void *hashmap_new(void)
|
||||
{
|
||||
struct hashmap_map *m;
|
||||
|
||||
|
@ -67,7 +67,8 @@ int _get_next_avail_pos(struct hashmap_map *m, char *key)
|
|||
if (!m->data[pos].in_use)
|
||||
return pos;
|
||||
|
||||
if (!strncmp(m->data[pos].key, key) && m->data[pos].in_use)
|
||||
if (!strncmp(m->data[pos].key, key, strlen(key))
|
||||
&& m->data[pos].in_use)
|
||||
return MAP_ALREADY_USED;
|
||||
|
||||
pos = (pos + 1) % m->max_size;
|
||||
|
@ -107,7 +108,7 @@ int _rehash(struct hashmap_map *m)
|
|||
return MAP_OK;
|
||||
}
|
||||
|
||||
int hashmap_put(string_map_t map, char *key, char *value)
|
||||
int hashmap_put(void *map, char *key, char *value)
|
||||
{
|
||||
int pos;
|
||||
struct hashmap_map *m;
|
||||
|
@ -127,7 +128,10 @@ int hashmap_put(string_map_t map, char *key, char *value)
|
|||
pos = _get_next_avail_pos(m, key);
|
||||
}
|
||||
|
||||
m->data[pos] = (struct hashmap_elem) {key, 1, value};
|
||||
m->data[pos].key = key;
|
||||
m->data[pos].in_use = 1;
|
||||
m->data[pos].val = value;
|
||||
|
||||
m->curr_size++;
|
||||
|
||||
return MAP_OK;
|
||||
|
@ -135,10 +139,11 @@ int hashmap_put(string_map_t map, char *key, char *value)
|
|||
|
||||
int _is_desired_pos(struct hashmap_map *m, char *key, int pos)
|
||||
{
|
||||
return m->data[pos].key && key && !strcmp(m->data[pos].key, key) && m->data[pos].in_use;
|
||||
return m->data[pos].key && key
|
||||
&& !strcmp(m->data[pos].key, key) && m->data[pos].in_use;
|
||||
}
|
||||
|
||||
int hashmap_get(string_map_t map, char *key, char **ret_val)
|
||||
int hashmap_get(void *map, char *key, char **ret_val)
|
||||
{
|
||||
int pos;
|
||||
int i;
|
||||
|
@ -165,7 +170,7 @@ int hashmap_get(string_map_t map, char *key, char **ret_val)
|
|||
return MAP_MISSING;
|
||||
}
|
||||
|
||||
int hashmap_del(string_map_t map, char *key)
|
||||
int hashmap_del(void *map, char *key)
|
||||
{
|
||||
int pos;
|
||||
int i;
|
||||
|
@ -197,14 +202,17 @@ int hashmap_del(string_map_t map, char *key)
|
|||
return MAP_MISSING;
|
||||
}
|
||||
|
||||
void hashmap_free(string_map_t map)
|
||||
void hashmap_free(void *map)
|
||||
{
|
||||
struct hashmap_map *m;
|
||||
int i;
|
||||
|
||||
m = (struct hashmap_map *) map;
|
||||
|
||||
for (i = 0; i < m->max_size; i++) {
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
for (i = 0; m->data && i < m->max_size; i++) {
|
||||
free(m->data[i].key);
|
||||
free(m->data[i].val);
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/* 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,11 @@
|
|||
#ifndef _expand_line_h
|
||||
#define _expand_line_h
|
||||
|
||||
#include "pp_defines.h"
|
||||
#include "hashmap.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int write_expanded_line(void *def_map, char *line, FILE *);
|
||||
extern char *get_expanded_line(void *def_map, char *line);
|
||||
|
||||
#endif
|
|
@ -10,13 +10,11 @@
|
|||
#define MAP_BAD_ARGS -4
|
||||
#define MAP_ALREADY_USED -5
|
||||
|
||||
typedef void *string_map_t;
|
||||
extern void *hashmap_new(void);
|
||||
extern void hashmap_free(void *map);
|
||||
|
||||
extern string_map_t hashmap_new(void);
|
||||
extern void hashmap_free(string_map_t map);
|
||||
|
||||
extern int hashmap_put(string_map_t map, char *key, char *val);
|
||||
extern int hashmap_get(string_map_t map, char *key, char **ret_val);
|
||||
extern int hashmap_del(string_map_t map, char *key);
|
||||
extern int hashmap_put(void *map, char *key, char *val);
|
||||
extern int hashmap_get(void *map, char *key, char **ret_val);
|
||||
extern int hashmap_del(void *map, char *key);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _line_handler_h
|
||||
#define _line_handler_h
|
||||
|
||||
#include "pp_defines.h"
|
||||
#include "hashmap.h"
|
||||
#include "str_dyn_arr.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int line_handler(
|
||||
char *line,
|
||||
void *def_map,
|
||||
const struct str_dyn_arr *inc_dirs,
|
||||
FILE*,
|
||||
FILE*
|
||||
);
|
||||
|
||||
#endif
|
|
@ -1,12 +1,11 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _pp_h
|
||||
#define _pp_h
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "char_dyn_arr.h"
|
||||
#include "str_dyn_arr.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int pp_start(string_map_t define_map, struct char_dyn_arr *inc_dirs, FILE *source, FILE *output);
|
||||
extern int pp_compute(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
FILE*in, FILE*);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
#define _pp_args
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "char_dyn_arr.h"
|
||||
#include "str_dyn_arr.h"
|
||||
|
||||
struct args {
|
||||
struct char_dyn_arr *inc_dirs;
|
||||
struct str_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);
|
||||
extern struct args *pp_parse_args(int argc, char **argv, void *def_map);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _pp_define_h
|
||||
#define _pp_define_h
|
||||
#ifndef _pp_define
|
||||
#define _pp_define
|
||||
|
||||
#include "pp_defines.h"
|
||||
#include "str_dyn_arr.h"
|
||||
#include "hashmap.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int pp_expand_defines(string_map_t define_map, FILE *source, FILE *output);
|
||||
|
||||
extern char *pp_strerr(int pp_errno);
|
||||
extern int collect_def(char *line, void *def_map, FILE *in);
|
||||
extern int apply_undef(char *line, void *def_map);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -13,6 +13,4 @@
|
|||
|
||||
#define PP_LINE_LEN 256
|
||||
|
||||
extern int pp_errno;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _pp_if_h
|
||||
#define _pp_if_h
|
||||
|
||||
#include "pp_defines.h"
|
||||
#include "hashmap.h"
|
||||
#include "str_dyn_arr.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int pp_expand_ifs(FILE *source, FILE *output);
|
||||
extern int expand_if(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
FILE*, FILE*);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _pp_ifdef_h
|
||||
#define _pp_ifdef_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pp_defines.h"
|
||||
#include "hashmap.h"
|
||||
#include "str_dyn_arr.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int pp_expand_ifdefs(string_map_t define_map, FILE *source, FILE *output);
|
||||
extern int expand_ifdef(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
FILE*, FILE*);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef _pp_inc_h
|
||||
#define _pp_inc_h
|
||||
|
||||
#include "pp_defines.h"
|
||||
#include "hashmap.h"
|
||||
#include "str_dyn_arr.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int expand_inc(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
FILE*, FILE*);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef _pp_line_id_h
|
||||
#define _pp_line_id_h
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define IF_LINE_START "#if "
|
||||
#define IF_LINE_START_SZ (sizeof(IF_LINE_START) - 1)
|
||||
#define IS_IF_LINE(line) (!strncmp(line, IF_LINE_START, IF_LINE_START_SZ))
|
||||
|
||||
#define ELSE_LINE_START "#else"
|
||||
#define ELSE_LINE_START_SZ (sizeof(ELSE_LINE_START) - 1)
|
||||
#define IS_ELSE_LINE(line) (!strncmp(line, ELSE_LINE_START, ELSE_LINE_START_SZ))
|
||||
|
||||
#define ELIF_LINE_START "#elif "
|
||||
#define ELIF_LINE_START_SZ (sizeof(ELIF_LINE_START) - 1)
|
||||
#define IS_ELIF_LINE(line) (!strncmp(line, ELIF_LINE_START, ELIF_LINE_START_SZ))
|
||||
|
||||
#define ENDIF_LINE_START "#endif"
|
||||
#define ENDIF_LINE_START_SZ (sizeof(ENDIF_LINE_START) - 1)
|
||||
#define IS_ENDIF_LINE(line) \
|
||||
(!strncmp(line, ENDIF_LINE_START, ENDIF_LINE_START_SZ))
|
||||
|
||||
#define DEF_LINE_START "#define"
|
||||
#define DEF_LINE_START_SZ (sizeof(DEF_LINE_START) - 1)
|
||||
#define IS_DEF_LINE(line) (!strncmp(line, DEF_LINE_START, DEF_LINE_START_SZ))
|
||||
|
||||
#define UNDEF_LINE_START "#undef"
|
||||
#define UNDEF_LINE_START_SZ (sizeof(UNDEF_LINE_START) - 1)
|
||||
#define IS_UNDEF_LINE(line) \
|
||||
(!strncmp(line, UNDEF_LINE_START, UNDEF_LINE_START_SZ))
|
||||
|
||||
#define IFDEF_LINE_START "#ifdef "
|
||||
#define IFDEF_LINE_START_SZ (sizeof(IFDEF_LINE_START) - 1)
|
||||
#define IS_IFDEF_LINE(line) \
|
||||
(!strncmp(line, IFDEF_LINE_START, IFDEF_LINE_START_SZ))
|
||||
|
||||
#define IFNDEF_LINE_START "#ifndef "
|
||||
#define IFNDEF_LINE_START_SZ (sizeof(IFNDEF_LINE_START) - 1)
|
||||
#define IS_IFNDEF_LINE(line) \
|
||||
(!strncmp(line, IFNDEF_LINE_START, IFNDEF_LINE_START_SZ))
|
||||
|
||||
#define INC_LINE_START "#include"
|
||||
#define INC_LINE_START_SZ (sizeof(INC_LINE_START) - 1)
|
||||
#define IS_INC_LINE(line) (!strncmp(line, INC_LINE_START, INC_LINE_START_SZ))
|
||||
|
||||
#define IS_IF_CURR_BRANCH_END(line) \
|
||||
(IS_ELSE_LINE(line) || IS_ELIF_LINE(line) || IS_ENDIF_LINE(line))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#ifndef _str_dyn_arr
|
||||
#define _str_dyn_arr
|
||||
|
||||
#define CHAR_DYN_ARR_OK 0
|
||||
#define CHAR_DYN_ARR_FAILED -1
|
||||
|
||||
struct str_dyn_arr {
|
||||
char **data;
|
||||
int used;
|
||||
int size;
|
||||
};
|
||||
|
||||
extern struct str_dyn_arr *init_str_dyn_arr(int size);
|
||||
extern int insert_str_dyn_arr(struct str_dyn_arr *a, char *e);
|
||||
extern void free_str_dyn_arr(struct str_dyn_arr *a);
|
||||
|
||||
#endif
|
||||
|
|
@ -3,7 +3,21 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
int write_line_to_file(FILE *f, char *line);
|
||||
#define SKIP_UNTIL_CURR_BRANCH_END 1
|
||||
#define SKIP_UNTIL_ENDIF_LINE 2
|
||||
|
||||
extern int write_line_to_file(FILE *out, char *line);
|
||||
extern char *l_strdup(char *str);
|
||||
|
||||
extern void strip_spaces_in_def(char *def);
|
||||
extern int a_strcat(char **dest, char *src);
|
||||
|
||||
extern int get_next_whitespace_idx(char *s);
|
||||
extern char *skip_word(char *s);
|
||||
|
||||
extern int is_cond_null(char *cond_line);
|
||||
|
||||
extern int skip_until(FILE *f, int until);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
#include "line_handler.h"
|
||||
#include "pp_define.h"
|
||||
#include "pp_line_id.h"
|
||||
#include "expand_line.h"
|
||||
#include "pp_if.h"
|
||||
#include "pp_ifdef.h"
|
||||
#include "pp_inc.h"
|
||||
|
||||
int line_handler(char *line, void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
FILE *source, FILE *out)
|
||||
{
|
||||
int ret;
|
||||
int line_len;
|
||||
|
||||
if (IS_DEF_LINE(line))
|
||||
return collect_def(line, def_map, source);
|
||||
|
||||
if (IS_UNDEF_LINE(line))
|
||||
return apply_undef(line, def_map);
|
||||
|
||||
if (IS_IF_LINE(line)) {
|
||||
line_len = strlen(line);
|
||||
|
||||
ret = fseek(source, -line_len, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
ret = expand_if(def_map, inc_dirs, source, out);
|
||||
if (ret == PP_FAILED)
|
||||
return ret;
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
if (IS_IFDEF_LINE(line) || IS_IFNDEF_LINE(line)) {
|
||||
line_len = strlen(line);
|
||||
|
||||
ret = fseek(source, -line_len, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
ret = expand_ifdef(def_map, inc_dirs, source, out);
|
||||
if (ret == PP_FAILED)
|
||||
return ret;
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
if (IS_INC_LINE(line)) {
|
||||
line_len = strlen(line);
|
||||
|
||||
ret = fseek(source, -line_len, SEEK_CUR);
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
ret = expand_inc(def_map, inc_dirs, source, out);
|
||||
if (ret == PP_FAILED)
|
||||
return ret;
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
if (IS_ENDIF_LINE(line))
|
||||
return PP_OK;
|
||||
|
||||
ret = write_expanded_line(def_map, line, out);
|
||||
if (ret == PP_FAILED)
|
||||
return ret;
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
39
pp.c
39
pp.c
|
@ -1,37 +1,28 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
|
||||
#include "pp.h"
|
||||
#include "pp_define.h"
|
||||
#include "pp_if.h"
|
||||
#include "pp_defines.h"
|
||||
#include "char_dyn_arr.h"
|
||||
#include "line_handler.h"
|
||||
|
||||
#define IF_TEMP_FILE "temp_if"
|
||||
#include <stdio.h>
|
||||
|
||||
int pp_start(string_map_t define_map, struct char_dyn_arr *inc_dirs, FILE *source, FILE *output)
|
||||
int pp_compute(void *def_map, const struct str_dyn_arr *inc_dirs, FILE *source,
|
||||
FILE *out)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
int read_lines;
|
||||
int ret;
|
||||
FILE *temp;
|
||||
|
||||
temp = fopen(IF_TEMP_FILE, "w+");
|
||||
if (!temp)
|
||||
return PP_FAILED;
|
||||
read_lines = 0;
|
||||
|
||||
ret = pp_expand_defines(define_map, source, temp);
|
||||
while (fgets(line, PP_LINE_LEN, source)) {
|
||||
read_lines++;
|
||||
|
||||
ret = line_handler(line, def_map, inc_dirs, source, out);
|
||||
if (ret == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
|
||||
ret = fseek(temp, 0, SEEK_SET);
|
||||
if (ret == -1) {
|
||||
ret = PP_FAILED;
|
||||
goto free_and_exit;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pp_expand_ifs(temp, output);
|
||||
if (ret == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
if (ferror(source) || !read_lines)
|
||||
return PP_FAILED;
|
||||
|
||||
free_and_exit:
|
||||
fclose(temp);
|
||||
return ret;
|
||||
return PP_OK;
|
||||
}
|
||||
|
|
56
pp_args.c
56
pp_args.c
|
@ -1,7 +1,8 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#include "pp_args.h"
|
||||
#include "pp_defines.h"
|
||||
#include "utils.h"
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -53,15 +54,13 @@ int _is_unrecognized_flag(char *flag)
|
|||
int _calloc_and_check(char **p, int sz)
|
||||
{
|
||||
*p = calloc(sz, sizeof(char));
|
||||
if (!(*p)) {
|
||||
pp_errno = PP_OMEM;
|
||||
if (!(*p))
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int _add_sym_mapp_to_map(string_map_t define_map, char *sym_mapp)
|
||||
int _add_sym_mapp_to_map(void *def_map, char *sym_mapp)
|
||||
{
|
||||
char *sym;
|
||||
char *mapp;
|
||||
|
@ -93,7 +92,7 @@ int _add_sym_mapp_to_map(string_map_t define_map, char *sym_mapp)
|
|||
|
||||
strncpy(sym, sym_mapp, sym_len);
|
||||
|
||||
res = hashmap_put(define_map, sym, mapp);
|
||||
res = hashmap_put(def_map, sym, mapp);
|
||||
|
||||
if (res != MAP_OK)
|
||||
return PP_FAILED;
|
||||
|
@ -119,7 +118,7 @@ int _add_sym_mapp_to_map(string_map_t define_map, char *sym_mapp)
|
|||
|
||||
strncpy(mapp, eq_pos, mapp_len);
|
||||
|
||||
ret = hashmap_put(define_map, sym, mapp);
|
||||
ret = hashmap_put(def_map, sym, mapp);
|
||||
|
||||
if (ret == MAP_OK)
|
||||
return PP_OK;
|
||||
|
@ -142,23 +141,29 @@ struct args *_create_struct_args(void)
|
|||
if (!ret)
|
||||
goto free_and_exit;
|
||||
|
||||
ret->inc_dirs = init_char_dyn_arr(2);
|
||||
ret->inc_dirs = init_str_dyn_arr(2);
|
||||
if (!(ret->inc_dirs))
|
||||
goto free_and_exit;
|
||||
|
||||
return ret;
|
||||
|
||||
free_and_exit:
|
||||
free_char_dyn_arr(ret->inc_dirs);
|
||||
if (ret)
|
||||
free_str_dyn_arr(ret->inc_dirs);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _collect_inc_dirs(struct args *args, char *inc_dir)
|
||||
{
|
||||
char *a_inc_dir;
|
||||
int res;
|
||||
|
||||
res = insert_char_dyn_arr(args->inc_dirs, inc_dir);
|
||||
a_inc_dir = l_strdup(inc_dir);
|
||||
if (!a_inc_dir)
|
||||
return PP_FAILED;
|
||||
|
||||
res = insert_str_dyn_arr(args->inc_dirs, a_inc_dir);
|
||||
|
||||
if (res == CHAR_DYN_ARR_OK)
|
||||
return PP_OK;
|
||||
|
@ -202,7 +207,7 @@ int _add_out_file_to_args(struct args *args, char *out_file)
|
|||
return PP_OK;
|
||||
}
|
||||
|
||||
struct args *pp_parse_args(int argc, char **argv, string_map_t define_map)
|
||||
struct args *pp_parse_args(int argc, char **argv, void *def_map)
|
||||
{
|
||||
struct args *args;
|
||||
|
||||
|
@ -224,14 +229,16 @@ struct args *pp_parse_args(int argc, char **argv, string_map_t define_map)
|
|||
for (i = 0; i < argc; i++) {
|
||||
is_flag = 0;
|
||||
|
||||
if (_is_unrecognized_flag(argv[i])) {
|
||||
pp_errno = PP_BAD_ARGS;
|
||||
if (_is_unrecognized_flag(argv[i]))
|
||||
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]);
|
||||
res = _add_sym_mapp_to_map(
|
||||
def_map,
|
||||
argv[i + 1]
|
||||
);
|
||||
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
is_flag = 1;
|
||||
|
@ -245,7 +252,7 @@ struct args *pp_parse_args(int argc, char **argv, string_map_t define_map)
|
|||
if (_is_tied_define_flag(argv[i])) {
|
||||
sym_mapp = argv[i] + DEFINE_FLAG_SZ;
|
||||
|
||||
res = _add_sym_mapp_to_map(define_map, sym_mapp);
|
||||
res = _add_sym_mapp_to_map(def_map, sym_mapp);
|
||||
if (res == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
is_flag = 1;
|
||||
|
@ -279,22 +286,26 @@ struct args *pp_parse_args(int argc, char **argv, string_map_t define_map)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!is_flag && !in_file_found && i - 1 >= 0 && _is_in_out_file_arg(argv[i - 1])) {
|
||||
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;
|
||||
|
||||
} else if (!is_flag && in_file_found && i - 1 >= 0
|
||||
&& _is_in_out_file_arg(argv[i - 1])) {
|
||||
|
||||
if (out_file_found)
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,8 +321,9 @@ void pp_free_args(struct args *args)
|
|||
if (!args)
|
||||
return;
|
||||
|
||||
free_char_dyn_arr(args->inc_dirs);
|
||||
free_str_dyn_arr(args->inc_dirs);
|
||||
free(args->in_file);
|
||||
free(args->out_file);
|
||||
free(args);
|
||||
}
|
||||
|
||||
|
|
703
pp_define.c
703
pp_define.c
|
@ -1,541 +1,86 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
|
||||
#include "pp_define.h"
|
||||
#include "pp_defines.h"
|
||||
#include "pp_ifdef.h"
|
||||
#include "line_handler.h"
|
||||
#include "pp_line_id.h"
|
||||
#include "utils.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DEFINE_LINE_START "#define"
|
||||
#define DEFINE_LINE_START_SZ (sizeof(DEFINE_LINE_START) - 1)
|
||||
|
||||
#define UNDEF_LINE_START "#undef"
|
||||
#define UNDEF_LINE_START_SZ (sizeof(UNDEF_LINE_START) - 1)
|
||||
int _collect_sym_mapp(void *def_map, char *def_line);
|
||||
char *_get_sym(char *def_line);
|
||||
char *_get_mapp(char *def_line);
|
||||
|
||||
#define IF_LINE_START "#if"
|
||||
#define IF_LINE_START_SZ (sizeof(IF_LINE_START) - 1)
|
||||
#define IS_IF_LINE(line) (!strncmp(line, IF_LINE_START, IF_LINE_START_SZ))
|
||||
|
||||
#define DELIMS "\t []{}<>=+-*/%!&|^.,:;()\\"
|
||||
|
||||
#define TEMP_PRECOMP "temp"
|
||||
#define TEMP_PRECOMP_1 "temp1"
|
||||
|
||||
int pp_errno = PP_OK;
|
||||
|
||||
int _is_define_line(char *line)
|
||||
int collect_def(char *line, void *def_map, FILE *source)
|
||||
{
|
||||
return !strncmp(line, DEFINE_LINE_START, DEFINE_LINE_START_SZ);
|
||||
}
|
||||
|
||||
int _is_undef_line(char *line)
|
||||
{
|
||||
return !strncmp(line, UNDEF_LINE_START, UNDEF_LINE_START_SZ);
|
||||
}
|
||||
|
||||
int _get_next_whitespace_index(char *str)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = 0;
|
||||
while (!isspace(*str)) {
|
||||
str++;
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void _strip_extra_spaces_in_define(char *str)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
int inside_quotes;
|
||||
|
||||
inside_quotes = 0;
|
||||
|
||||
for (i = x = 0; str[i]; i++) {
|
||||
if (i > 0 && str[i] == '\"' && str[i - 1] != '\\' && !inside_quotes)
|
||||
inside_quotes = 1;
|
||||
else if (i > 0 && str[i] == '\"' && str[i - 1] != '\\' && inside_quotes)
|
||||
inside_quotes = 0;
|
||||
|
||||
if (!inside_quotes && (!isspace(str[i]) || (i > 0 && !isspace(str[i - 1]))))
|
||||
str[x++] = str[i];
|
||||
else if (inside_quotes)
|
||||
x++;
|
||||
}
|
||||
|
||||
str[x] = 0x00;
|
||||
}
|
||||
|
||||
char *_skip_word(char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = str;
|
||||
while (!isspace(*s++));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
char *_get_symbol(char *define_line)
|
||||
{
|
||||
char *symbol;
|
||||
int symbol_end_index;
|
||||
|
||||
define_line = _skip_word(define_line);
|
||||
if (!(*define_line)) {
|
||||
pp_errno = PP_BAD_DEFINE_SYMBOL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symbol_end_index = _get_next_whitespace_index(define_line);
|
||||
|
||||
symbol = calloc(symbol_end_index + 1, sizeof(char));
|
||||
if (!symbol) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(symbol, define_line, symbol_end_index);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
char *_get_mapping(char *define_line)
|
||||
{
|
||||
char *mapping;
|
||||
|
||||
define_line = _skip_word(define_line);
|
||||
if (!(*define_line)) {
|
||||
pp_errno = PP_BAD_DEFINE_SYMBOL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
define_line = _skip_word(define_line);
|
||||
if (!(*define_line)) {
|
||||
pp_errno = PP_BAD_DEFINE_MAPPING;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mapping = calloc(strlen(define_line), sizeof(char));
|
||||
if (!mapping) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(mapping, define_line, strlen(define_line) - 1);
|
||||
return mapping;
|
||||
}
|
||||
|
||||
int _add_symbol_mapping_to_hashmap(string_map_t *map, char *define_line)
|
||||
{
|
||||
int ret;
|
||||
char *symbol;
|
||||
char *mapping;
|
||||
|
||||
symbol = _get_symbol(define_line);
|
||||
if (!symbol)
|
||||
return PP_FAILED;
|
||||
|
||||
mapping = _get_mapping(define_line);
|
||||
if (!mapping)
|
||||
return PP_FAILED;
|
||||
|
||||
ret = hashmap_put(map, symbol, mapping);
|
||||
if (ret == MAP_OMEM) {
|
||||
pp_errno = PP_OMEM;
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int _concat_str(char **str1, char *str2)
|
||||
{
|
||||
char *result;
|
||||
char *temp;
|
||||
int needed;
|
||||
|
||||
needed = strlen(*str1) + strlen(str2) + 1;
|
||||
result = calloc(needed, sizeof(char));
|
||||
if (!result) {
|
||||
pp_errno = PP_OMEM;
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
sprintf(result, "%s%s", *str1, str2);
|
||||
|
||||
temp = *str1;
|
||||
*str1 = result;
|
||||
|
||||
free(temp);
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
|
||||
int _collect_multiline_define(string_map_t *map, char *define_line, FILE *f)
|
||||
{
|
||||
char *define_multiline;
|
||||
|
||||
char *line;
|
||||
size_t len;
|
||||
ssize_t read;
|
||||
char *def_multiline;
|
||||
char read_line[PP_LINE_LEN + 1];
|
||||
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
_strip_extra_spaces_in_define(define_line);
|
||||
def_multiline = NULL;
|
||||
len = strlen(line);
|
||||
|
||||
if (define_line[strlen(define_line) - 2] != '\\') {
|
||||
ret = _add_symbol_mapping_to_hashmap(map, define_line);
|
||||
strip_spaces_in_def(line);
|
||||
|
||||
if (line[len - 2] != '\\') {
|
||||
ret = _collect_sym_mapp(def_map, line);
|
||||
if (ret == PP_FAILED) {
|
||||
ret = PP_FAILED;
|
||||
goto free_and_exit;
|
||||
}
|
||||
} else {
|
||||
define_multiline = strdup(define_line);
|
||||
if (!define_multiline)
|
||||
def_multiline = l_strdup(line);
|
||||
if (!def_multiline)
|
||||
return PP_FAILED;
|
||||
|
||||
line = NULL;
|
||||
len = 0;
|
||||
while (fgets(read_line, PP_LINE_LEN, source)) {
|
||||
strip_spaces_in_def(read_line);
|
||||
|
||||
while ((read = getline(&line, &len, f)) != -1) {
|
||||
_strip_extra_spaces_in_define(line);
|
||||
len = strlen(def_multiline);
|
||||
def_multiline[len - 2] = 0x00;
|
||||
|
||||
define_multiline[strlen(define_multiline) - 2] = 0x00;
|
||||
_concat_str(&define_multiline, line);
|
||||
ret = a_strcat(&def_multiline, read_line);
|
||||
if (ret == -1) {
|
||||
ret = PP_FAILED;
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
if (line[strlen(line) - 2] != '\\')
|
||||
|
||||
len = strlen(read_line);
|
||||
if (read_line[len - 2] != '\\')
|
||||
break;
|
||||
}
|
||||
|
||||
free(line);
|
||||
|
||||
ret = _add_symbol_mapping_to_hashmap(map, define_multiline);
|
||||
free(define_multiline);
|
||||
ret = _collect_sym_mapp(def_map, def_multiline);
|
||||
if (ret == PP_FAILED) {
|
||||
ret = PP_FAILED;
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pp_collect_defines(string_map_t map, FILE *f)
|
||||
{
|
||||
char *line;
|
||||
size_t len;
|
||||
ssize_t read;
|
||||
int ret;
|
||||
|
||||
ret = PP_OK;
|
||||
line = NULL;
|
||||
len = 0;
|
||||
|
||||
while ((read = getline(&line, &len, f)) != -1) {
|
||||
if (_is_define_line(line)) {
|
||||
ret = _collect_multiline_define(map, line, f);
|
||||
if (ret == PP_FAILED)
|
||||
goto free_resources_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
free_resources_and_exit:
|
||||
free(line);
|
||||
free_and_exit:
|
||||
free(def_multiline);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _is_inside_multiline_define(char *curr_line)
|
||||
{
|
||||
static int is_inside;
|
||||
|
||||
if (_is_define_line(curr_line))
|
||||
is_inside = 1;
|
||||
|
||||
if (is_inside && curr_line[strlen(curr_line) - 2] != '\\')
|
||||
is_inside = 0;
|
||||
|
||||
return is_inside;
|
||||
}
|
||||
|
||||
int _can_skip_multiline_define(int is_inside, int prev_is_inside)
|
||||
{
|
||||
return !(is_inside || (!is_inside && prev_is_inside));
|
||||
}
|
||||
|
||||
int pp_create_file_without_defines(FILE *in, FILE *out)
|
||||
{
|
||||
char *line;
|
||||
size_t len;
|
||||
ssize_t read;
|
||||
|
||||
char *stripped_line;
|
||||
|
||||
int is_inside_multiline_define;
|
||||
int prev_is_inside_multiline_define;
|
||||
|
||||
int fwritten_bytes;
|
||||
int ret;
|
||||
|
||||
ret = PP_OK;
|
||||
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);
|
||||
if (!stripped_line) {
|
||||
pp_errno = PP_OMEM;
|
||||
ret = PP_FAILED;
|
||||
goto free_resources_and_exit;
|
||||
}
|
||||
|
||||
prev_is_inside_multiline_define = is_inside_multiline_define;
|
||||
is_inside_multiline_define = _is_inside_multiline_define(stripped_line);
|
||||
|
||||
free(stripped_line);
|
||||
|
||||
if (!_is_define_line(line)) {
|
||||
if (_can_skip_multiline_define(is_inside_multiline_define, prev_is_inside_multiline_define)) {
|
||||
fwritten_bytes = fprintf(out, "%s", line);
|
||||
|
||||
if (fwritten_bytes < 0 || fwritten_bytes != read) {
|
||||
pp_errno = PP_BAD_FILE_OP;
|
||||
ret = PP_FAILED;
|
||||
goto free_resources_and_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_resources_and_exit:
|
||||
free(line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *_get_expanded_token(string_map_t map, char *token)
|
||||
{
|
||||
char *expanded;
|
||||
char *expanded_copy;
|
||||
int res;
|
||||
int size;
|
||||
|
||||
res = hashmap_get(map, token, &expanded);
|
||||
|
||||
if (res != MAP_OK) {
|
||||
size = strlen(token);
|
||||
|
||||
expanded_copy = calloc(size + 1, sizeof(char));
|
||||
if (!expanded_copy) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(expanded_copy, token);
|
||||
} else {
|
||||
expanded_copy = strdup(expanded);
|
||||
if (!expanded_copy) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return expanded_copy;
|
||||
}
|
||||
|
||||
int _concat_delim_to_line(char *delim, int delim_size, char **line)
|
||||
{
|
||||
char *d_delim;
|
||||
char res;
|
||||
|
||||
d_delim = calloc(delim_size + 1, sizeof(char));
|
||||
if (!d_delim) {
|
||||
pp_errno = PP_OMEM;
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
strncpy(d_delim, delim, delim_size);
|
||||
|
||||
res = _concat_str(line, d_delim);
|
||||
|
||||
free(d_delim);
|
||||
return res;
|
||||
}
|
||||
|
||||
int _concat_expanded_token_to_line(string_map_t map, char *token, char **line)
|
||||
{
|
||||
char *expanded;
|
||||
int res;
|
||||
|
||||
expanded = _get_expanded_token(map, token);
|
||||
if (!expanded) {
|
||||
pp_errno = PP_OMEM;
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
res = _concat_str(line, expanded);
|
||||
|
||||
free(expanded);
|
||||
return res;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
char *_compute_expanded_line(string_map_t map, char *line)
|
||||
{
|
||||
char *int_line;
|
||||
char *line_start;
|
||||
char *line_copy;
|
||||
char *token;
|
||||
char *expanded_line;
|
||||
|
||||
int delim_start;
|
||||
int delim_end;
|
||||
int res;
|
||||
int token_len;
|
||||
|
||||
int_line = strdup(line);
|
||||
if (!int_line) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line_start = int_line;
|
||||
|
||||
line_copy = strdup(int_line);
|
||||
if (!line_copy) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expanded_line = calloc(1, sizeof(char));
|
||||
if (!expanded_line) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = strtok(int_line, DELIMS);
|
||||
|
||||
if (_is_delim_at_str_start(token, line_start)) {
|
||||
res = _concat_delim_to_line(line_start, token - line_start, &expanded_line);
|
||||
if (res == PP_FAILED)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = _concat_expanded_token_to_line(map, token, &expanded_line);
|
||||
if (res == PP_FAILED)
|
||||
return NULL;
|
||||
|
||||
while (token) {
|
||||
delim_start = _compute_delim_start(token, int_line);
|
||||
token = strtok(NULL, DELIMS);
|
||||
delim_end = _compute_delim_end(token, int_line, line_copy);
|
||||
|
||||
res = _concat_delim_to_line(line_copy + delim_start, delim_end - delim_start, &expanded_line);
|
||||
if (res == PP_FAILED)
|
||||
return NULL;
|
||||
|
||||
if (token) {
|
||||
token_len = strlen(token);
|
||||
if (token[token_len - 1] == '\n')
|
||||
token[token_len - 1] = 0x00;
|
||||
|
||||
_concat_expanded_token_to_line(map, token, &expanded_line);
|
||||
|
||||
if (token[token_len - 1] == 0x00) {
|
||||
token[token_len - 1] = '\n';
|
||||
_concat_expanded_token_to_line(map, "\n", &expanded_line);
|
||||
}
|
||||
|
||||
if (res == PP_FAILED)
|
||||
return NULL;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(line_copy);
|
||||
free(int_line);
|
||||
return expanded_line;
|
||||
}
|
||||
|
||||
char *_get_expanded_line(string_map_t map, char *line)
|
||||
{
|
||||
char *expanded_line;
|
||||
char *prev_expanded_line;
|
||||
|
||||
expanded_line = _compute_expanded_line(map, line);
|
||||
if (!expanded_line)
|
||||
return NULL;
|
||||
|
||||
prev_expanded_line = strdup(line);
|
||||
if (!prev_expanded_line) {
|
||||
pp_errno = PP_OMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (strcmp(prev_expanded_line, expanded_line)) {
|
||||
free(prev_expanded_line);
|
||||
prev_expanded_line = expanded_line;
|
||||
|
||||
expanded_line = _compute_expanded_line(map, prev_expanded_line);
|
||||
if (!expanded_line)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(prev_expanded_line);
|
||||
return expanded_line;
|
||||
}
|
||||
|
||||
int _write_expanded_line(string_map_t map, char *line, FILE *out)
|
||||
{
|
||||
char *expanded_line;
|
||||
int line_size;
|
||||
int res;
|
||||
|
||||
expanded_line = _get_expanded_line(map, line);
|
||||
if (!expanded_line)
|
||||
return PP_FAILED;
|
||||
|
||||
line_size = strlen(expanded_line);
|
||||
|
||||
res = fprintf(out, "%s", expanded_line);
|
||||
if (res < 0) {
|
||||
pp_errno = PP_BAD_FILE_OP;
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
free(expanded_line);
|
||||
return res == line_size ? PP_OK : PP_FAILED;
|
||||
}
|
||||
|
||||
int _delete_sym_from_map(string_map_t *map, char *undef_line)
|
||||
int apply_undef(char *line, void *map)
|
||||
{
|
||||
char *sym;
|
||||
int sym_len;
|
||||
int res;
|
||||
|
||||
int ret;
|
||||
|
||||
sym = undef_line + UNDEF_LINE_START_SZ + 1;
|
||||
sym = line + UNDEF_LINE_START_SZ + 1;
|
||||
sym_len = strlen(sym);
|
||||
|
||||
sym[sym_len - 1] = 0x00;
|
||||
|
||||
res = hashmap_del(map, sym);
|
||||
if (res == MAP_BAD_ARGS) {
|
||||
ret = hashmap_del(map, sym);
|
||||
if (ret == MAP_BAD_ARGS) {
|
||||
ret = PP_FAILED;
|
||||
goto restore_undef_line_and_exit;
|
||||
}
|
||||
|
@ -547,98 +92,80 @@ restore_undef_line_and_exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int pp_write_expanded_defines_to_file(string_map_t map, FILE *in, FILE *out)
|
||||
{
|
||||
char *line;
|
||||
size_t len;
|
||||
ssize_t read;
|
||||
int ret;
|
||||
|
||||
ret = PP_OK;
|
||||
line = NULL;
|
||||
len = 0;
|
||||
|
||||
while ((read = getline(&line, &len, in)) != -1) {
|
||||
if (_is_undef_line(line)) {
|
||||
ret = _delete_sym_from_map(map, line);
|
||||
if (ret == PP_FAILED)
|
||||
goto free_resources_and_exit;
|
||||
|
||||
memcpy(line, "\n\x00", 2);
|
||||
}
|
||||
|
||||
ret = _write_expanded_line(map, line, out);
|
||||
if (ret == PP_FAILED)
|
||||
goto free_resources_and_exit;
|
||||
}
|
||||
|
||||
free_resources_and_exit:
|
||||
free(line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *pp_strerr(int pp_errno)
|
||||
{
|
||||
switch (pp_errno) {
|
||||
case PP_BAD_DEFINE_SYMBOL:
|
||||
return "bad define symbol";
|
||||
case PP_BAD_DEFINE_MAPPING:
|
||||
return "bad define mapping";
|
||||
default:
|
||||
return strerror(errno);
|
||||
}
|
||||
}
|
||||
|
||||
int pp_expand_defines(string_map_t define_map, FILE *source, FILE *output)
|
||||
int _collect_sym_mapp(void *def_map, char *def_line)
|
||||
{
|
||||
int ret;
|
||||
FILE *temp_precomp;
|
||||
FILE *temp_precomp_1;
|
||||
|
||||
ret = pp_collect_defines(define_map, source);
|
||||
if (ret != PP_OK)
|
||||
return ret;
|
||||
char *sym;
|
||||
char *mapp;
|
||||
|
||||
ret = fseek(source, 0, SEEK_SET);
|
||||
if (ret == -1) {
|
||||
ret = PP_FAILED;
|
||||
goto close_file_and_exit;
|
||||
sym = NULL;
|
||||
mapp = NULL;
|
||||
|
||||
sym = _get_sym(def_line);
|
||||
if (!sym)
|
||||
goto free_and_exit;
|
||||
|
||||
mapp = _get_mapp(def_line);
|
||||
if (!mapp) {
|
||||
mapp = calloc(1, sizeof(char));
|
||||
if (!mapp)
|
||||
goto free_and_exit;
|
||||
|
||||
a_strcat(&mapp, "");
|
||||
}
|
||||
|
||||
temp_precomp = fopen(TEMP_PRECOMP, "w+");
|
||||
if (!temp_precomp)
|
||||
ret = hashmap_put(def_map, sym, mapp);
|
||||
|
||||
if (ret == MAP_OMEM)
|
||||
goto free_and_exit;
|
||||
|
||||
return PP_OK;
|
||||
|
||||
free_and_exit:
|
||||
free(sym);
|
||||
free(mapp);
|
||||
return PP_FAILED;
|
||||
|
||||
temp_precomp_1 = fopen(TEMP_PRECOMP_1, "w+");
|
||||
if (!temp_precomp_1)
|
||||
return PP_FAILED;
|
||||
|
||||
ret = pp_create_file_without_defines(source, temp_precomp);
|
||||
if (ret != PP_OK)
|
||||
goto close_file_and_exit;
|
||||
|
||||
fseek(temp_precomp, 0, SEEK_SET);
|
||||
if (ret == -1) {
|
||||
ret = PP_FAILED;
|
||||
goto close_file_and_exit;
|
||||
}
|
||||
|
||||
ret = pp_expand_ifdefs(define_map, temp_precomp, temp_precomp_1);
|
||||
if (ret != PP_OK)
|
||||
goto close_file_and_exit;
|
||||
|
||||
fseek(temp_precomp_1, 0, SEEK_SET);
|
||||
|
||||
ret = pp_write_expanded_defines_to_file(define_map, temp_precomp_1, output);
|
||||
if (ret != PP_OK)
|
||||
goto close_file_and_exit;
|
||||
|
||||
ret = PP_OK;
|
||||
|
||||
close_file_and_exit:
|
||||
fclose(temp_precomp);
|
||||
fclose(temp_precomp_1);
|
||||
remove(TEMP_PRECOMP);
|
||||
remove(TEMP_PRECOMP_1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *_get_sym(char *def_line)
|
||||
{
|
||||
char *sym;
|
||||
int sym_end_index;
|
||||
|
||||
def_line = skip_word(def_line);
|
||||
if (!(*def_line))
|
||||
return NULL;
|
||||
|
||||
sym_end_index = get_next_whitespace_idx(def_line);
|
||||
|
||||
sym = calloc(sym_end_index + 1, sizeof(char));
|
||||
if (!sym)
|
||||
return NULL;
|
||||
|
||||
strncpy(sym, def_line, sym_end_index);
|
||||
return sym;
|
||||
}
|
||||
|
||||
char *_get_mapp(char *def_line)
|
||||
{
|
||||
char *mapp;
|
||||
int mapp_len;
|
||||
|
||||
def_line = skip_word(def_line);
|
||||
if (!(*def_line))
|
||||
return NULL;
|
||||
|
||||
def_line = skip_word(def_line);
|
||||
if (!(*def_line))
|
||||
return NULL;
|
||||
|
||||
mapp_len = strlen(def_line) - 1;
|
||||
|
||||
mapp = calloc(strlen(def_line) + 1, sizeof(char));
|
||||
if (!mapp)
|
||||
return NULL;
|
||||
|
||||
strncpy(mapp, def_line, mapp_len);
|
||||
return mapp;
|
||||
}
|
||||
|
|
145
pp_if.c
145
pp_if.c
|
@ -1,72 +1,17 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
|
||||
#include "pp_if.h"
|
||||
#include "pp_defines.h"
|
||||
#include "pp_line_id.h"
|
||||
#include "line_handler.h"
|
||||
#include "utils.h"
|
||||
#include <string.h>
|
||||
#include "expand_line.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define IF_LINE_START "#if "
|
||||
#define IF_LINE_START_SZ (sizeof(IF_LINE_START) - 1)
|
||||
#define IS_IF_LINE(line) (!strncmp(line, IF_LINE_START, IF_LINE_START_SZ))
|
||||
|
||||
#define ELSE_LINE_START "#else"
|
||||
#define ELSE_LINE_START_SZ (sizeof(ELSE_LINE_START) - 1)
|
||||
#define IS_ELSE_LINE(line) (!strncmp(line, ELSE_LINE_START, ELSE_LINE_START_SZ))
|
||||
|
||||
#define ELIF_LINE_START "#elif "
|
||||
#define ELIF_LINE_START_SZ (sizeof(ELIF_LINE_START) - 1)
|
||||
#define IS_ELIF_LINE(line) (!strncmp(line, ELIF_LINE_START, ELIF_LINE_START_SZ))
|
||||
|
||||
#define ENDIF_LINE_START "#endif"
|
||||
#define ENDIF_LINE_START_SZ (sizeof(ENDIF_LINE_START) - 1)
|
||||
#define IS_ENDIF_LINE(line) (!strncmp(line, ENDIF_LINE_START, ENDIF_LINE_START_SZ))
|
||||
|
||||
#define IS_CURR_BRANCH_END(line) (IS_ELSE_LINE(line) || IS_ELIF_LINE(line) || IS_ENDIF_LINE(line))
|
||||
|
||||
#define SKIP_UNTIL_CURR_BRANCH_END 1
|
||||
#define SKIP_UNTIL_ENDIF_LINE 2
|
||||
|
||||
int _is_cond_null(char *cond_line)
|
||||
{
|
||||
char *cond;
|
||||
|
||||
if (!strncmp(cond_line, IF_LINE_START, IF_LINE_START_SZ))
|
||||
cond = cond_line + IF_LINE_START_SZ;
|
||||
else if (!strncmp(cond_line, ELIF_LINE_START, ELIF_LINE_START_SZ))
|
||||
cond = cond_line + ELIF_LINE_START_SZ;
|
||||
|
||||
return cond[0] == '0'; // de schimbat
|
||||
}
|
||||
|
||||
int _skip_until(FILE *f, int until)
|
||||
int expand_if(void *def_map, const struct str_dyn_arr *inc_dirs, FILE *source,
|
||||
FILE *out)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
char *exp_line;
|
||||
|
||||
int line_len;
|
||||
int res;
|
||||
|
||||
while (fgets(line, PP_LINE_LEN, f)) {
|
||||
if (until == SKIP_UNTIL_CURR_BRANCH_END && IS_CURR_BRANCH_END(line))
|
||||
break;
|
||||
|
||||
if (until == SKIP_UNTIL_ENDIF_LINE && IS_ENDIF_LINE(line))
|
||||
break;
|
||||
}
|
||||
|
||||
line_len = strlen(line);
|
||||
res = fseek(f, -line_len, SEEK_CUR);
|
||||
|
||||
if (res == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int _expand_if(FILE *source, FILE *output)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
|
||||
int res;
|
||||
int ret;
|
||||
int line_len;
|
||||
int if_en;
|
||||
int else_en;
|
||||
|
@ -79,68 +24,62 @@ int _expand_if(FILE *source, FILE *output)
|
|||
break;
|
||||
|
||||
if (if_en && (IS_ELSE_LINE(line) || IS_ELIF_LINE(line))) {
|
||||
res = _skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
||||
if (res == PP_FAILED)
|
||||
return res;
|
||||
ret = skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
if_en = 0;
|
||||
}
|
||||
|
||||
if (if_en || else_en) {
|
||||
res = write_line_to_file(output, line);
|
||||
if (res == -1)
|
||||
return res;
|
||||
ret = line_handler(
|
||||
line,
|
||||
def_map,
|
||||
inc_dirs,
|
||||
source,
|
||||
out
|
||||
);
|
||||
|
||||
if (ret == PP_FAILED)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IS_IF_LINE(line) || IS_ELIF_LINE(line)) {
|
||||
if (_is_cond_null(line)) {
|
||||
res = _skip_until(source, SKIP_UNTIL_CURR_BRANCH_END);
|
||||
if (res == PP_FAILED)
|
||||
return res;
|
||||
exp_line = get_expanded_line(def_map, line);
|
||||
|
||||
if (!exp_line)
|
||||
return PP_FAILED;
|
||||
|
||||
if (is_cond_null(exp_line)) {
|
||||
ret = skip_until(
|
||||
source,
|
||||
SKIP_UNTIL_CURR_BRANCH_END
|
||||
);
|
||||
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
fgets(line, PP_LINE_LEN, source);
|
||||
if (IS_ELSE_LINE(line)) {
|
||||
else_en = 1;
|
||||
} else {
|
||||
line_len = strlen(line);
|
||||
res = fseek(source, -line_len, SEEK_CUR);
|
||||
ret = fseek(
|
||||
source,
|
||||
-line_len,
|
||||
SEEK_CUR
|
||||
);
|
||||
|
||||
if (res == -1)
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
}
|
||||
} else {
|
||||
if_en = 1;
|
||||
}
|
||||
|
||||
free(exp_line);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int pp_expand_ifs(FILE *source, FILE *output)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
|
||||
int res;
|
||||
int line_len;
|
||||
|
||||
while (fgets(line, PP_LINE_LEN, source)) {
|
||||
if (IS_IF_LINE(line)) {
|
||||
line_len = strlen(line);
|
||||
|
||||
res = fseek(source, -line_len, SEEK_CUR);
|
||||
if (res == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
_expand_if(source, output);
|
||||
} else {
|
||||
res = write_line_to_file(output, line);
|
||||
if (res == -1)
|
||||
return PP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
213
pp_ifdef.c
213
pp_ifdef.c
|
@ -1,89 +1,20 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
|
||||
#include "pp_ifdef.h"
|
||||
#include "pp_defines.h"
|
||||
#include "expand_line.h"
|
||||
#include "utils.h"
|
||||
#include "hashmap.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pp_line_id.h"
|
||||
#include "line_handler.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define IFDEF_LINE_START "#ifdef "
|
||||
#define IFDEF_LINE_START_SZ (sizeof(IFDEF_LINE_START) - 1)
|
||||
#define IS_IFDEF_LINE(line) (!strncmp(line, IFDEF_LINE_START, IFDEF_LINE_START_SZ))
|
||||
int _is_sym_defined(void *def_map, char *ifdef_line);
|
||||
|
||||
#define ELSE_LINE_START "#else"
|
||||
#define ELSE_LINE_START_SZ (sizeof(ELSE_LINE_START) - 1)
|
||||
#define IS_ELSE_LINE(line) (!strncmp(line, ELSE_LINE_START, ELSE_LINE_START_SZ))
|
||||
|
||||
#define IFNDEF_LINE_START "#ifndef "
|
||||
#define IFNDEF_LINE_START_SZ (sizeof(IFNDEF_LINE_START) - 1)
|
||||
#define IS_IFNDEF_LINE(line) (!strncmp(line, IFNDEF_LINE_START, IFNDEF_LINE_START_SZ))
|
||||
|
||||
#define ENDIF_LINE_START "#endif"
|
||||
#define ENDIF_LINE_START_SZ (sizeof(ENDIF_LINE_START) - 1)
|
||||
#define IS_ENDIF_LINE(line) (!strncmp(line, ENDIF_LINE_START, ENDIF_LINE_START_SZ))
|
||||
|
||||
#define IS_CURR_BRANCH_END(line) (IS_ELSE_LINE(line) || IS_ENDIF_LINE(line))
|
||||
|
||||
#define SKIP_UNTIL_CURR_BRANCH_END 1
|
||||
#define SKIP_UNTIL_ENDIF_LINE 2
|
||||
|
||||
int _is_sym_defined(string_map_t define_map, char *ifdef_line)
|
||||
{
|
||||
char *sym;
|
||||
char *mapp;
|
||||
|
||||
int sym_len;
|
||||
int res;
|
||||
|
||||
if (!strncmp(ifdef_line, IFDEF_LINE_START, IFDEF_LINE_START_SZ))
|
||||
sym = ifdef_line + IFDEF_LINE_START_SZ;
|
||||
else if (!strncmp(ifdef_line, IFNDEF_LINE_START, IFNDEF_LINE_START_SZ))
|
||||
sym = ifdef_line + IFNDEF_LINE_START_SZ;
|
||||
|
||||
sym_len = strlen(sym);
|
||||
sym[sym_len - 1] = 0x00;
|
||||
|
||||
res = hashmap_get(define_map, sym, &mapp);
|
||||
if (res == MAP_BAD_ARGS)
|
||||
goto restore_line_and_exit;
|
||||
|
||||
return res == MAP_OK && mapp;
|
||||
|
||||
restore_line_and_exit:
|
||||
sym[sym_len - 1] = '\n';
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _ifdef_skip_until(FILE *f, int until)
|
||||
int expand_ifdef(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
FILE *source, FILE *out)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
char *exp_line;
|
||||
|
||||
int line_len;
|
||||
int res;
|
||||
|
||||
while (fgets(line, PP_LINE_LEN, f)) {
|
||||
if (until == SKIP_UNTIL_CURR_BRANCH_END && IS_CURR_BRANCH_END(line))
|
||||
break;
|
||||
|
||||
if (until == SKIP_UNTIL_ENDIF_LINE && IS_ENDIF_LINE(line))
|
||||
break;
|
||||
}
|
||||
|
||||
line_len = strlen(line);
|
||||
res = fseek(f, -line_len, SEEK_CUR);
|
||||
|
||||
if (res == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int _expand_ifdef(string_map_t define_map, FILE *source, FILE *output)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
|
||||
int res;
|
||||
int ret;
|
||||
int line_len;
|
||||
int if_en;
|
||||
int else_en;
|
||||
|
@ -96,88 +27,142 @@ int _expand_ifdef(string_map_t define_map, FILE *source, FILE *output)
|
|||
break;
|
||||
|
||||
if (if_en && IS_ELSE_LINE(line)) {
|
||||
res = _ifdef_skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
||||
if (res == PP_FAILED)
|
||||
return res;
|
||||
ret = skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
if_en = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (if_en || else_en) {
|
||||
res = write_line_to_file(output, line);
|
||||
if (res == -1)
|
||||
return res;
|
||||
ret = line_handler(
|
||||
line,
|
||||
def_map,
|
||||
inc_dirs,
|
||||
source,
|
||||
out
|
||||
);
|
||||
|
||||
if (ret == PP_FAILED)
|
||||
return ret;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IS_IFDEF_LINE(line)) {
|
||||
if (!_is_sym_defined(define_map, line)) {
|
||||
res = _ifdef_skip_until(source, SKIP_UNTIL_CURR_BRANCH_END);
|
||||
if (res == PP_FAILED)
|
||||
return res;
|
||||
exp_line = get_expanded_line(def_map, line);
|
||||
if (!exp_line)
|
||||
return PP_FAILED;
|
||||
|
||||
if (!_is_sym_defined(def_map, line)) {
|
||||
ret = skip_until(
|
||||
source,
|
||||
SKIP_UNTIL_CURR_BRANCH_END
|
||||
);
|
||||
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
fgets(line, PP_LINE_LEN, source);
|
||||
if (IS_ELSE_LINE(line)) {
|
||||
else_en = 1;
|
||||
} else {
|
||||
line_len = strlen(line);
|
||||
res = fseek(source, -line_len, SEEK_CUR);
|
||||
ret = fseek(
|
||||
source,
|
||||
-line_len,
|
||||
SEEK_CUR
|
||||
);
|
||||
|
||||
if (res == -1)
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
}
|
||||
} else {
|
||||
if_en = 1;
|
||||
}
|
||||
|
||||
free(exp_line);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IS_IFNDEF_LINE(line)) {
|
||||
if (_is_sym_defined(define_map, line)) {
|
||||
res = _ifdef_skip_until(source, SKIP_UNTIL_CURR_BRANCH_END);
|
||||
if (res == PP_FAILED)
|
||||
return res;
|
||||
exp_line = get_expanded_line(def_map, line);
|
||||
|
||||
if (!exp_line)
|
||||
return PP_FAILED;
|
||||
|
||||
if (_is_sym_defined(def_map, line)) {
|
||||
ret = skip_until(
|
||||
source,
|
||||
SKIP_UNTIL_CURR_BRANCH_END
|
||||
);
|
||||
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
|
||||
fgets(line, PP_LINE_LEN, source);
|
||||
|
||||
if (IS_ELSE_LINE(line)) {
|
||||
else_en = 1;
|
||||
} else {
|
||||
line_len = strlen(line);
|
||||
res = fseek(source, -line_len, SEEK_CUR);
|
||||
ret = fseek(
|
||||
source,
|
||||
-line_len,
|
||||
SEEK_CUR
|
||||
);
|
||||
|
||||
if (res == -1)
|
||||
if (ret == -1)
|
||||
return PP_FAILED;
|
||||
}
|
||||
} else {
|
||||
if_en = 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(exp_line);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
int pp_expand_ifdefs(string_map_t define_map, FILE *source, FILE *output)
|
||||
int _is_sym_defined(void *def_map, char *ifdef_line)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
char *sym;
|
||||
char *mapp;
|
||||
|
||||
int res;
|
||||
int line_len;
|
||||
int sym_len;
|
||||
int ret;
|
||||
|
||||
while (fgets(line, PP_LINE_LEN, source)) {
|
||||
if (IS_IFDEF_LINE(line) || IS_IFNDEF_LINE(line)) {
|
||||
line_len = strlen(line);
|
||||
sym = NULL;
|
||||
mapp = NULL;
|
||||
|
||||
res = fseek(source, -line_len, SEEK_CUR);
|
||||
if (res == -1)
|
||||
return PP_FAILED;
|
||||
if (!strncmp(ifdef_line, IFDEF_LINE_START, IFDEF_LINE_START_SZ))
|
||||
sym = ifdef_line + IFDEF_LINE_START_SZ;
|
||||
else if (!strncmp(ifdef_line, IFNDEF_LINE_START, IFNDEF_LINE_START_SZ))
|
||||
sym = ifdef_line + IFNDEF_LINE_START_SZ;
|
||||
|
||||
_expand_ifdef(define_map, source, output);
|
||||
} else {
|
||||
res = write_line_to_file(output, line);
|
||||
if (res == -1)
|
||||
return PP_FAILED;
|
||||
}
|
||||
if (!sym)
|
||||
return 0;
|
||||
|
||||
sym_len = strlen(sym);
|
||||
sym[sym_len - 1] = 0x00;
|
||||
|
||||
ret = hashmap_get(def_map, sym, &mapp);
|
||||
if (ret == MAP_BAD_ARGS) {
|
||||
ret = 0;
|
||||
goto rettore_line_and_exit;
|
||||
}
|
||||
|
||||
return PP_OK;
|
||||
ret = ret == MAP_OK && mapp;
|
||||
|
||||
rettore_line_and_exit:
|
||||
sym[sym_len - 1] = '\n';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
#include "pp_inc.h"
|
||||
#include "pp_line_id.h"
|
||||
#include "utils.h"
|
||||
#include "pp.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char *_get_filename_from_inc(char *inc);
|
||||
int _compute_inc_file(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
char *inc_filename, FILE *out);
|
||||
|
||||
int expand_inc(void *def_map, const struct str_dyn_arr *inc_dirs, FILE *source,
|
||||
FILE *out)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
char *fgets_ret;
|
||||
char *inc_filename;
|
||||
char *full_inc_filename;
|
||||
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
fgets_ret = fgets(line, PP_LINE_LEN, source);
|
||||
if (!fgets_ret)
|
||||
return PP_FAILED;
|
||||
|
||||
inc_filename = _get_filename_from_inc(line);
|
||||
|
||||
full_inc_filename = l_strdup("_test/inputs/");
|
||||
if (!full_inc_filename)
|
||||
return PP_FAILED;
|
||||
|
||||
a_strcat(&full_inc_filename, inc_filename);
|
||||
|
||||
ret = _compute_inc_file(def_map, inc_dirs, full_inc_filename, out);
|
||||
free(full_inc_filename);
|
||||
|
||||
if (ret == PP_OK)
|
||||
return PP_OK;
|
||||
|
||||
for (i = 0; i < inc_dirs->used; i++) {
|
||||
full_inc_filename = l_strdup(inc_dirs->data[i]);
|
||||
if (!full_inc_filename)
|
||||
return PP_FAILED;
|
||||
|
||||
a_strcat(&full_inc_filename, "/");
|
||||
a_strcat(&full_inc_filename, inc_filename);
|
||||
|
||||
ret = _compute_inc_file(
|
||||
def_map,
|
||||
inc_dirs,
|
||||
full_inc_filename,
|
||||
out
|
||||
);
|
||||
free(full_inc_filename);
|
||||
|
||||
if (ret == PP_OK)
|
||||
return PP_OK;
|
||||
}
|
||||
|
||||
return PP_FAILED;
|
||||
}
|
||||
|
||||
char *_get_filename_from_inc(char *inc)
|
||||
{
|
||||
char *filename;
|
||||
int filename_len;
|
||||
|
||||
filename = inc;
|
||||
|
||||
filename += INC_LINE_START_SZ + 1;
|
||||
filename += 1;
|
||||
|
||||
filename_len = strlen(filename);
|
||||
filename[filename_len - 2] = 0x00;
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
int _compute_inc_file(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||
char *inc_filename, FILE *out)
|
||||
{
|
||||
FILE *inc_file;
|
||||
|
||||
int ret;
|
||||
|
||||
inc_file = fopen(inc_filename, "rb");
|
||||
|
||||
if (inc_file) {
|
||||
ret = pp_compute(def_map, inc_dirs, inc_file, out);
|
||||
fclose(inc_file);
|
||||
|
||||
return ret == PP_OK ? PP_OK : PP_FAILED;
|
||||
}
|
||||
|
||||
return PP_FAILED;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Tema1 Test Suite
|
||||
#
|
||||
# 2020, Operating Systems
|
||||
#
|
||||
first_test=0
|
||||
last_test=38
|
||||
script=./_test/run_test.sh
|
||||
|
||||
# Call init to set up testing environment
|
||||
bash "$script" init
|
||||
|
||||
# check the source (disabled, part of tests now)
|
||||
#bash "$script" check
|
||||
|
||||
for i in $(seq $first_test $last_test); do
|
||||
bash "$script" $i
|
||||
done | tee results.txt
|
||||
|
||||
cat results.txt | grep -a '\[.*\]$' | awk -F '[] /[]+' '
|
||||
BEGIN {
|
||||
sum=0
|
||||
}
|
||||
|
||||
{
|
||||
sum += $(NF-2);
|
||||
}
|
||||
|
||||
END {
|
||||
printf "\n%66s [%02d/95]\n", "Total:", sum;
|
||||
}'
|
||||
|
||||
# Cleanup testing environment
|
||||
bash "$script" cleanup
|
||||
rm -f results.txt
|
54
so-cpp.c
54
so-cpp.c
|
@ -1,5 +1,4 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
|
||||
/* SPDX-License-Identifier: BSD-2 */
|
||||
#include "hashmap.h"
|
||||
#include "pp.h"
|
||||
#include "pp_defines.h"
|
||||
|
@ -7,43 +6,41 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
string_map_t define_map;
|
||||
void *def_map;
|
||||
struct args *args;
|
||||
FILE *in;
|
||||
FILE *source;
|
||||
FILE *out;
|
||||
|
||||
int ret;
|
||||
|
||||
define_map = NULL;
|
||||
def_map = NULL;
|
||||
args = NULL;
|
||||
in = NULL;
|
||||
source = NULL;
|
||||
out = NULL;
|
||||
|
||||
define_map = hashmap_new();
|
||||
args = pp_parse_args(argc, argv, define_map);
|
||||
def_map = hashmap_new();
|
||||
args = pp_parse_args(argc, argv, def_map);
|
||||
|
||||
if (!args) {
|
||||
if (errno) {
|
||||
if (errno)
|
||||
ret = errno;
|
||||
else
|
||||
ret = PP_FAILED;
|
||||
goto free_and_exit;
|
||||
}
|
||||
if (pp_errno != PP_OK) {
|
||||
ret = pp_errno;
|
||||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (args->in_file) {
|
||||
in = fopen(args->in_file, "r");
|
||||
if (!in) {
|
||||
source = fopen(args->in_file, "rb");
|
||||
if (!source) {
|
||||
ret = errno;
|
||||
goto free_and_exit;
|
||||
}
|
||||
} else {
|
||||
in = stdin;
|
||||
source = stdin;
|
||||
}
|
||||
|
||||
if (args->out_file) {
|
||||
|
@ -56,20 +53,31 @@ int main(int argc, char **argv)
|
|||
out = stdout;
|
||||
}
|
||||
|
||||
ret = pp_start(define_map, in, out);
|
||||
if (ret != PP_OK)
|
||||
ret = pp_compute(def_map, args->inc_dirs, source, out);
|
||||
|
||||
if (ret == PP_FAILED && errno == ENOMEM) {
|
||||
ret = ENOMEM;
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
if (ret == PP_OK && errno == ENOENT) {
|
||||
ret = PP_OK;
|
||||
goto free_and_exit;
|
||||
}
|
||||
|
||||
if (ret == PP_FAILED)
|
||||
goto free_and_exit;
|
||||
|
||||
|
||||
ret = errno;
|
||||
|
||||
free_and_exit:
|
||||
hashmap_free(define_map);
|
||||
hashmap_free(def_map);
|
||||
pp_free_args(args);
|
||||
if (in)
|
||||
fclose(in);
|
||||
if (source)
|
||||
fclose(source);
|
||||
if (out)
|
||||
fclose(out);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
// SPDX-License-Identifier: BSD-2
|
||||
/* SPDX-License-Identifier: BSD-2 */
|
||||
|
||||
#include "char_dyn_arr.h"
|
||||
#include "str_dyn_arr.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct char_dyn_arr *init_char_dyn_arr(int size)
|
||||
struct str_dyn_arr *init_str_dyn_arr(int size)
|
||||
{
|
||||
struct char_dyn_arr *a;
|
||||
struct str_dyn_arr *a;
|
||||
|
||||
a = NULL;
|
||||
|
||||
a = calloc(1, sizeof(struct char_dyn_arr));
|
||||
a = calloc(1, sizeof(struct str_dyn_arr));
|
||||
if (!a)
|
||||
goto free_and_exit;
|
||||
|
||||
|
@ -24,13 +24,14 @@ struct char_dyn_arr *init_char_dyn_arr(int size)
|
|||
return a;
|
||||
|
||||
free_and_exit:
|
||||
free(a);
|
||||
if (a)
|
||||
free(a->data);
|
||||
free(a);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int insert_char_dyn_arr(struct char_dyn_arr *a, char *e)
|
||||
int insert_str_dyn_arr(struct str_dyn_arr *a, char *e)
|
||||
{
|
||||
if (a->used == a->size) {
|
||||
a->size *= 2;
|
||||
|
@ -50,7 +51,7 @@ free_and_exit:
|
|||
return CHAR_DYN_ARR_FAILED;
|
||||
}
|
||||
|
||||
extern void free_char_dyn_arr(struct char_dyn_arr *a)
|
||||
extern void free_str_dyn_arr(struct str_dyn_arr *a)
|
||||
{
|
||||
int i;
|
||||
|
135
utils.c
135
utils.c
|
@ -1,6 +1,10 @@
|
|||
#include "utils.h"
|
||||
#include "pp_defines.h"
|
||||
#include "pp_line_id.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int write_line_to_file(FILE *f, char *line)
|
||||
{
|
||||
|
@ -16,3 +20,134 @@ int write_line_to_file(FILE *f, char *line)
|
|||
return 0;
|
||||
}
|
||||
|
||||
char *l_strdup(char *s)
|
||||
{
|
||||
int size;
|
||||
char *p;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
size = strlen(s) + 1;
|
||||
p = calloc(size, sizeof(char));
|
||||
|
||||
if (p)
|
||||
memcpy(p, s, size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void strip_spaces_in_def(char *def)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
int in_quotes;
|
||||
|
||||
in_quotes = 0;
|
||||
|
||||
for (i = x = 0; def[i]; i++) {
|
||||
if (i > 0 && def[i] == '\"' && def[i - 1] != '\\' && !in_quotes)
|
||||
in_quotes = 1;
|
||||
else if (i > 0 && def[i] == '\"' && def[i - 1] != '\\'
|
||||
&& in_quotes)
|
||||
in_quotes = 0;
|
||||
|
||||
if (!in_quotes && (!isspace(def[i]) || (i > 0
|
||||
&& !isspace(def[i - 1]))))
|
||||
def[x++] = def[i];
|
||||
else if (in_quotes)
|
||||
x++;
|
||||
}
|
||||
|
||||
def[x] = 0x00;
|
||||
}
|
||||
|
||||
int a_strcat(char **dest, char *src)
|
||||
{
|
||||
char *result;
|
||||
char *temp;
|
||||
int needed;
|
||||
|
||||
needed = strlen(*dest) + strlen(src) + 1;
|
||||
result = calloc(needed, sizeof(char));
|
||||
if (!result)
|
||||
return -1;
|
||||
|
||||
sprintf(result, "%s%s", *dest, src);
|
||||
|
||||
temp = *dest;
|
||||
*dest = result;
|
||||
|
||||
free(temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_next_whitespace_idx(char *s)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = 0;
|
||||
while (!isspace(*s)) {
|
||||
s++;
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
char *skip_word(char *s)
|
||||
{
|
||||
char *_s;
|
||||
|
||||
_s = s;
|
||||
while (!isspace(*_s))
|
||||
_s++;
|
||||
|
||||
_s++;
|
||||
|
||||
return _s;
|
||||
}
|
||||
|
||||
int is_cond_null(char *cond_line)
|
||||
{
|
||||
char *cond;
|
||||
|
||||
cond = NULL;
|
||||
|
||||
if (!strncmp(cond_line, IF_LINE_START, IF_LINE_START_SZ))
|
||||
cond = cond_line + IF_LINE_START_SZ;
|
||||
else if (!strncmp(cond_line, ELIF_LINE_START, ELIF_LINE_START_SZ))
|
||||
cond = cond_line + ELIF_LINE_START_SZ;
|
||||
|
||||
if (!cond)
|
||||
return 0;
|
||||
|
||||
return cond[0] == '0';
|
||||
}
|
||||
|
||||
|
||||
int skip_until(FILE *f, int until)
|
||||
{
|
||||
char line[PP_LINE_LEN + 1];
|
||||
|
||||
int line_len;
|
||||
int res;
|
||||
|
||||
while (fgets(line, PP_LINE_LEN, f)) {
|
||||
if (until == SKIP_UNTIL_CURR_BRANCH_END
|
||||
&& IS_IF_CURR_BRANCH_END(line))
|
||||
break;
|
||||
|
||||
if (until == SKIP_UNTIL_ENDIF_LINE && IS_ENDIF_LINE(line))
|
||||
break;
|
||||
}
|
||||
|
||||
line_len = strlen(line);
|
||||
res = fseek(f, -line_len, SEEK_CUR);
|
||||
|
||||
if (res == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue