commit
d5b883d06a
|
@ -4,7 +4,7 @@ LIBRARY=none
|
||||||
INCPATHS=include
|
INCPATHS=include
|
||||||
LIBPATHS=
|
LIBPATHS=
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
CCFLAGS=-c -Wall -g -Wextra -Werror -pedantic-errors
|
CCFLAGS=-c -Wall -g -Wextra -Werror -pedantic-errors -std=c89
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CODING_STYLE_CHECKER=checkpatch_wrapper.sh
|
CODING_STYLE_CHECKER=checkpatch_wrapper.sh
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ OBJECTS=$(SOURCES:.c=.o)
|
||||||
INCFLAGS=$(foreach TMP,$(INCPATHS),-I$(TMP))
|
INCFLAGS=$(foreach TMP,$(INCPATHS),-I$(TMP))
|
||||||
LIBFLAGS=$(foreach TMP,$(LIBPATHS),-L$(TMP))
|
LIBFLAGS=$(foreach TMP,$(LIBPATHS),-L$(TMP))
|
||||||
|
|
||||||
all: $(SOURCES) $(OUTPUT)
|
build: $(SOURCES) $(OUTPUT)
|
||||||
|
|
||||||
coding_style:
|
coding_style:
|
||||||
./$(CODING_STYLE_CHECKER) $(SOURCES) $(INCPATHS)/*
|
./$(CODING_STYLE_CHECKER)
|
||||||
|
|
||||||
$(OUTPUT): $(OBJECTS)
|
$(OUTPUT): $(OBJECTS)
|
||||||
$(CC) $(LIBFLAGS) $(OBJECTS) $(LDFLAGS) -o $@
|
$(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 <hashmap.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -19,7 +19,7 @@ struct hashmap_map {
|
||||||
struct hashmap_elem *data;
|
struct hashmap_elem *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
string_map_t hashmap_new(void)
|
void *hashmap_new(void)
|
||||||
{
|
{
|
||||||
struct hashmap_map *m;
|
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)
|
if (!m->data[pos].in_use)
|
||||||
return pos;
|
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;
|
return MAP_ALREADY_USED;
|
||||||
|
|
||||||
pos = (pos + 1) % m->max_size;
|
pos = (pos + 1) % m->max_size;
|
||||||
|
@ -107,7 +108,7 @@ int _rehash(struct hashmap_map *m)
|
||||||
return MAP_OK;
|
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;
|
int pos;
|
||||||
struct hashmap_map *m;
|
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);
|
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++;
|
m->curr_size++;
|
||||||
|
|
||||||
return MAP_OK;
|
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)
|
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 pos;
|
||||||
int i;
|
int i;
|
||||||
|
@ -165,7 +170,7 @@ int hashmap_get(string_map_t map, char *key, char **ret_val)
|
||||||
return MAP_MISSING;
|
return MAP_MISSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hashmap_del(string_map_t map, char *key)
|
int hashmap_del(void *map, char *key)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
int i;
|
int i;
|
||||||
|
@ -197,14 +202,17 @@ int hashmap_del(string_map_t map, char *key)
|
||||||
return MAP_MISSING;
|
return MAP_MISSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hashmap_free(string_map_t map)
|
void hashmap_free(void *map)
|
||||||
{
|
{
|
||||||
struct hashmap_map *m;
|
struct hashmap_map *m;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
m = (struct hashmap_map *) map;
|
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].key);
|
||||||
free(m->data[i].val);
|
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_BAD_ARGS -4
|
||||||
#define MAP_ALREADY_USED -5
|
#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 int hashmap_put(void *map, char *key, char *val);
|
||||||
extern void hashmap_free(string_map_t map);
|
extern int hashmap_get(void *map, char *key, char **ret_val);
|
||||||
|
extern int hashmap_del(void *map, char *key);
|
||||||
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);
|
|
||||||
|
|
||||||
#endif
|
#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
|
#ifndef _pp_h
|
||||||
#define _pp_h
|
#define _pp_h
|
||||||
|
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "char_dyn_arr.h"
|
#include "str_dyn_arr.h"
|
||||||
#include <stdio.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
|
#endif
|
||||||
|
|
|
@ -4,15 +4,15 @@
|
||||||
#define _pp_args
|
#define _pp_args
|
||||||
|
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "char_dyn_arr.h"
|
#include "str_dyn_arr.h"
|
||||||
|
|
||||||
struct args {
|
struct args {
|
||||||
struct char_dyn_arr *inc_dirs;
|
struct str_dyn_arr *inc_dirs;
|
||||||
char *in_file;
|
char *in_file;
|
||||||
char *out_file;
|
char *out_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void pp_free_args(struct args *args);
|
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
|
#endif
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/* SPDX-License-Identifier: BSD-2 */
|
#ifndef _pp_define
|
||||||
|
#define _pp_define
|
||||||
#ifndef _pp_define_h
|
|
||||||
#define _pp_define_h
|
|
||||||
|
|
||||||
|
#include "pp_defines.h"
|
||||||
|
#include "str_dyn_arr.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
extern int pp_expand_defines(string_map_t define_map, FILE *source, FILE *output);
|
extern int collect_def(char *line, void *def_map, FILE *in);
|
||||||
|
extern int apply_undef(char *line, void *def_map);
|
||||||
extern char *pp_strerr(int pp_errno);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,4 @@
|
||||||
|
|
||||||
#define PP_LINE_LEN 256
|
#define PP_LINE_LEN 256
|
||||||
|
|
||||||
extern int pp_errno;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
/* SPDX-License-Identifier: BSD-2 */
|
|
||||||
|
|
||||||
#ifndef _pp_if_h
|
#ifndef _pp_if_h
|
||||||
#define _pp_if_h
|
#define _pp_if_h
|
||||||
|
|
||||||
|
#include "pp_defines.h"
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include "str_dyn_arr.h"
|
||||||
#include <stdio.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
|
#endif
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/* SPDX-License-Identifier: BSD-2 */
|
|
||||||
|
|
||||||
#ifndef _pp_ifdef_h
|
#ifndef _pp_ifdef_h
|
||||||
#define _pp_ifdef_h
|
#define _pp_ifdef_h
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "pp_defines.h"
|
||||||
#include "hashmap.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
|
#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>
|
#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
|
#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.h"
|
||||||
#include "pp_define.h"
|
|
||||||
#include "pp_if.h"
|
|
||||||
#include "pp_defines.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;
|
int ret;
|
||||||
FILE *temp;
|
|
||||||
|
|
||||||
temp = fopen(IF_TEMP_FILE, "w+");
|
read_lines = 0;
|
||||||
if (!temp)
|
|
||||||
return PP_FAILED;
|
|
||||||
|
|
||||||
ret = pp_expand_defines(define_map, source, temp);
|
while (fgets(line, PP_LINE_LEN, source)) {
|
||||||
if (ret == PP_FAILED)
|
read_lines++;
|
||||||
goto free_and_exit;
|
|
||||||
|
|
||||||
ret = fseek(temp, 0, SEEK_SET);
|
ret = line_handler(line, def_map, inc_dirs, source, out);
|
||||||
if (ret == -1) {
|
if (ret == PP_FAILED)
|
||||||
ret = PP_FAILED;
|
return ret;
|
||||||
goto free_and_exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pp_expand_ifs(temp, output);
|
if (ferror(source) || !read_lines)
|
||||||
if (ret == PP_FAILED)
|
return PP_FAILED;
|
||||||
goto free_and_exit;
|
|
||||||
|
|
||||||
free_and_exit:
|
return PP_OK;
|
||||||
fclose(temp);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
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_args.h"
|
||||||
#include "pp_defines.h"
|
#include "pp_defines.h"
|
||||||
|
#include "utils.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -53,15 +54,13 @@ int _is_unrecognized_flag(char *flag)
|
||||||
int _calloc_and_check(char **p, int sz)
|
int _calloc_and_check(char **p, int sz)
|
||||||
{
|
{
|
||||||
*p = calloc(sz, sizeof(char));
|
*p = calloc(sz, sizeof(char));
|
||||||
if (!(*p)) {
|
if (!(*p))
|
||||||
pp_errno = PP_OMEM;
|
|
||||||
return PP_FAILED;
|
return PP_FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
return PP_OK;
|
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 *sym;
|
||||||
char *mapp;
|
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);
|
strncpy(sym, sym_mapp, sym_len);
|
||||||
|
|
||||||
res = hashmap_put(define_map, sym, mapp);
|
res = hashmap_put(def_map, sym, mapp);
|
||||||
|
|
||||||
if (res != MAP_OK)
|
if (res != MAP_OK)
|
||||||
return PP_FAILED;
|
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);
|
strncpy(mapp, eq_pos, mapp_len);
|
||||||
|
|
||||||
ret = hashmap_put(define_map, sym, mapp);
|
ret = hashmap_put(def_map, sym, mapp);
|
||||||
|
|
||||||
if (ret == MAP_OK)
|
if (ret == MAP_OK)
|
||||||
return PP_OK;
|
return PP_OK;
|
||||||
|
@ -142,23 +141,29 @@ struct args *_create_struct_args(void)
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
|
|
||||||
ret->inc_dirs = init_char_dyn_arr(2);
|
ret->inc_dirs = init_str_dyn_arr(2);
|
||||||
if (!(ret->inc_dirs))
|
if (!(ret->inc_dirs))
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
free_and_exit:
|
free_and_exit:
|
||||||
free_char_dyn_arr(ret->inc_dirs);
|
if (ret)
|
||||||
|
free_str_dyn_arr(ret->inc_dirs);
|
||||||
free(ret);
|
free(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _collect_inc_dirs(struct args *args, char *inc_dir)
|
int _collect_inc_dirs(struct args *args, char *inc_dir)
|
||||||
{
|
{
|
||||||
|
char *a_inc_dir;
|
||||||
int res;
|
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)
|
if (res == CHAR_DYN_ARR_OK)
|
||||||
return PP_OK;
|
return PP_OK;
|
||||||
|
@ -202,7 +207,7 @@ int _add_out_file_to_args(struct args *args, char *out_file)
|
||||||
return PP_OK;
|
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;
|
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++) {
|
for (i = 0; i < argc; i++) {
|
||||||
is_flag = 0;
|
is_flag = 0;
|
||||||
|
|
||||||
if (_is_unrecognized_flag(argv[i])) {
|
if (_is_unrecognized_flag(argv[i]))
|
||||||
pp_errno = PP_BAD_ARGS;
|
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
}
|
|
||||||
|
|
||||||
if (_is_split_define_flag(argv[i])) {
|
if (_is_split_define_flag(argv[i])) {
|
||||||
if (i + 1 < argc) {
|
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)
|
if (res == PP_FAILED)
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
is_flag = 1;
|
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])) {
|
if (_is_tied_define_flag(argv[i])) {
|
||||||
sym_mapp = argv[i] + DEFINE_FLAG_SZ;
|
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)
|
if (res == PP_FAILED)
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
is_flag = 1;
|
is_flag = 1;
|
||||||
|
@ -279,22 +286,26 @@ struct args *pp_parse_args(int argc, char **argv, string_map_t define_map)
|
||||||
continue;
|
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]);
|
res = _add_in_file_to_args(args, argv[i]);
|
||||||
if (res == PP_FAILED)
|
if (res == PP_FAILED)
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
|
|
||||||
in_file_found = 1;
|
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) {
|
} else if (!is_flag && in_file_found && i - 1 >= 0
|
||||||
pp_errno = PP_BAD_ARGS;
|
&& _is_in_out_file_arg(argv[i - 1])) {
|
||||||
|
|
||||||
|
if (out_file_found)
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
}
|
|
||||||
|
|
||||||
res = _add_out_file_to_args(args, argv[i]);
|
res = _add_out_file_to_args(args, argv[i]);
|
||||||
if (res == PP_FAILED)
|
if (res == PP_FAILED)
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
out_file_found = 1;
|
out_file_found = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,8 +321,9 @@ void pp_free_args(struct args *args)
|
||||||
if (!args)
|
if (!args)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
free_char_dyn_arr(args->inc_dirs);
|
free_str_dyn_arr(args->inc_dirs);
|
||||||
free(args->in_file);
|
free(args->in_file);
|
||||||
free(args->out_file);
|
free(args->out_file);
|
||||||
free(args);
|
free(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
699
pp_define.c
699
pp_define.c
|
@ -1,541 +1,86 @@
|
||||||
// SPDX-License-Identifier: BSD-2
|
|
||||||
|
|
||||||
#include "pp_define.h"
|
#include "pp_define.h"
|
||||||
#include "pp_defines.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 <stdlib.h>
|
||||||
#include <string.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"
|
int _collect_sym_mapp(void *def_map, char *def_line);
|
||||||
#define UNDEF_LINE_START_SZ (sizeof(UNDEF_LINE_START) - 1)
|
char *_get_sym(char *def_line);
|
||||||
|
char *_get_mapp(char *def_line);
|
||||||
|
|
||||||
#define IF_LINE_START "#if"
|
int collect_def(char *line, void *def_map, FILE *source)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
return !strncmp(line, DEFINE_LINE_START, DEFINE_LINE_START_SZ);
|
char *def_multiline;
|
||||||
}
|
char read_line[PP_LINE_LEN + 1];
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
int len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
_strip_extra_spaces_in_define(define_line);
|
def_multiline = NULL;
|
||||||
|
len = strlen(line);
|
||||||
|
|
||||||
if (define_line[strlen(define_line) - 2] != '\\') {
|
strip_spaces_in_def(line);
|
||||||
ret = _add_symbol_mapping_to_hashmap(map, define_line);
|
|
||||||
|
if (line[len - 2] != '\\') {
|
||||||
|
ret = _collect_sym_mapp(def_map, line);
|
||||||
|
if (ret == PP_FAILED) {
|
||||||
|
ret = PP_FAILED;
|
||||||
|
goto free_and_exit;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
define_multiline = strdup(define_line);
|
def_multiline = l_strdup(line);
|
||||||
if (!define_multiline)
|
if (!def_multiline)
|
||||||
return PP_FAILED;
|
return PP_FAILED;
|
||||||
|
|
||||||
line = NULL;
|
while (fgets(read_line, PP_LINE_LEN, source)) {
|
||||||
len = 0;
|
strip_spaces_in_def(read_line);
|
||||||
|
|
||||||
while ((read = getline(&line, &len, f)) != -1) {
|
len = strlen(def_multiline);
|
||||||
_strip_extra_spaces_in_define(line);
|
def_multiline[len - 2] = 0x00;
|
||||||
|
|
||||||
define_multiline[strlen(define_multiline) - 2] = 0x00;
|
ret = a_strcat(&def_multiline, read_line);
|
||||||
_concat_str(&define_multiline, 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(line);
|
ret = _collect_sym_mapp(def_map, def_multiline);
|
||||||
|
if (ret == PP_FAILED) {
|
||||||
ret = _add_symbol_mapping_to_hashmap(map, define_multiline);
|
|
||||||
free(define_multiline);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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;
|
ret = PP_FAILED;
|
||||||
goto free_resources_and_exit;
|
goto free_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:
|
ret = PP_OK;
|
||||||
free(line);
|
|
||||||
|
free_and_exit:
|
||||||
|
free(def_multiline);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *_get_expanded_token(string_map_t map, char *token)
|
int apply_undef(char *line, void *map)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
char *sym;
|
char *sym;
|
||||||
int sym_len;
|
int sym_len;
|
||||||
int res;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
sym = undef_line + UNDEF_LINE_START_SZ + 1;
|
sym = line + UNDEF_LINE_START_SZ + 1;
|
||||||
sym_len = strlen(sym);
|
sym_len = strlen(sym);
|
||||||
|
|
||||||
sym[sym_len - 1] = 0x00;
|
sym[sym_len - 1] = 0x00;
|
||||||
|
|
||||||
res = hashmap_del(map, sym);
|
ret = hashmap_del(map, sym);
|
||||||
if (res == MAP_BAD_ARGS) {
|
if (ret == MAP_BAD_ARGS) {
|
||||||
ret = PP_FAILED;
|
ret = PP_FAILED;
|
||||||
goto restore_undef_line_and_exit;
|
goto restore_undef_line_and_exit;
|
||||||
}
|
}
|
||||||
|
@ -547,98 +92,80 @@ restore_undef_line_and_exit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pp_write_expanded_defines_to_file(string_map_t map, FILE *in, FILE *out)
|
int _collect_sym_mapp(void *def_map, char *def_line)
|
||||||
{
|
|
||||||
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 ret;
|
int ret;
|
||||||
FILE *temp_precomp;
|
|
||||||
FILE *temp_precomp_1;
|
|
||||||
|
|
||||||
ret = pp_collect_defines(define_map, source);
|
char *sym;
|
||||||
if (ret != PP_OK)
|
char *mapp;
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = fseek(source, 0, SEEK_SET);
|
sym = NULL;
|
||||||
if (ret == -1) {
|
mapp = NULL;
|
||||||
ret = PP_FAILED;
|
|
||||||
goto close_file_and_exit;
|
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+");
|
ret = hashmap_put(def_map, sym, mapp);
|
||||||
if (!temp_precomp)
|
|
||||||
return PP_FAILED;
|
|
||||||
|
|
||||||
temp_precomp_1 = fopen(TEMP_PRECOMP_1, "w+");
|
if (ret == MAP_OMEM)
|
||||||
if (!temp_precomp_1)
|
goto free_and_exit;
|
||||||
return PP_FAILED;
|
|
||||||
|
|
||||||
ret = pp_create_file_without_defines(source, temp_precomp);
|
return PP_OK;
|
||||||
if (ret != PP_OK)
|
|
||||||
goto close_file_and_exit;
|
|
||||||
|
|
||||||
fseek(temp_precomp, 0, SEEK_SET);
|
free_and_exit:
|
||||||
if (ret == -1) {
|
free(sym);
|
||||||
ret = PP_FAILED;
|
free(mapp);
|
||||||
goto close_file_and_exit;
|
return PP_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pp_expand_ifdefs(define_map, temp_precomp, temp_precomp_1);
|
char *_get_sym(char *def_line)
|
||||||
if (ret != PP_OK)
|
{
|
||||||
goto close_file_and_exit;
|
char *sym;
|
||||||
|
int sym_end_index;
|
||||||
fseek(temp_precomp_1, 0, SEEK_SET);
|
|
||||||
|
def_line = skip_word(def_line);
|
||||||
ret = pp_write_expanded_defines_to_file(define_map, temp_precomp_1, output);
|
if (!(*def_line))
|
||||||
if (ret != PP_OK)
|
return NULL;
|
||||||
goto close_file_and_exit;
|
|
||||||
|
sym_end_index = get_next_whitespace_idx(def_line);
|
||||||
ret = PP_OK;
|
|
||||||
|
sym = calloc(sym_end_index + 1, sizeof(char));
|
||||||
close_file_and_exit:
|
if (!sym)
|
||||||
fclose(temp_precomp);
|
return NULL;
|
||||||
fclose(temp_precomp_1);
|
|
||||||
remove(TEMP_PRECOMP);
|
strncpy(sym, def_line, sym_end_index);
|
||||||
remove(TEMP_PRECOMP_1);
|
return sym;
|
||||||
return ret;
|
}
|
||||||
|
|
||||||
|
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_if.h"
|
||||||
#include "pp_defines.h"
|
#include "pp_line_id.h"
|
||||||
|
#include "line_handler.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include <string.h>
|
#include "expand_line.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define IF_LINE_START "#if "
|
int expand_if(void *def_map, const struct str_dyn_arr *inc_dirs, FILE *source,
|
||||||
#define IF_LINE_START_SZ (sizeof(IF_LINE_START) - 1)
|
FILE *out)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
char line[PP_LINE_LEN + 1];
|
char line[PP_LINE_LEN + 1];
|
||||||
|
char *exp_line;
|
||||||
|
|
||||||
int line_len;
|
int ret;
|
||||||
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 line_len;
|
int line_len;
|
||||||
int if_en;
|
int if_en;
|
||||||
int else_en;
|
int else_en;
|
||||||
|
@ -79,68 +24,62 @@ int _expand_if(FILE *source, FILE *output)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (if_en && (IS_ELSE_LINE(line) || IS_ELIF_LINE(line))) {
|
if (if_en && (IS_ELSE_LINE(line) || IS_ELIF_LINE(line))) {
|
||||||
res = _skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
ret = skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
||||||
if (res == PP_FAILED)
|
if (ret == -1)
|
||||||
return res;
|
return PP_FAILED;
|
||||||
if_en = 0;
|
if_en = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (if_en || else_en) {
|
if (if_en || else_en) {
|
||||||
res = write_line_to_file(output, line);
|
ret = line_handler(
|
||||||
if (res == -1)
|
line,
|
||||||
return res;
|
def_map,
|
||||||
|
inc_dirs,
|
||||||
|
source,
|
||||||
|
out
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ret == PP_FAILED)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_IF_LINE(line) || IS_ELIF_LINE(line)) {
|
if (IS_IF_LINE(line) || IS_ELIF_LINE(line)) {
|
||||||
if (_is_cond_null(line)) {
|
exp_line = get_expanded_line(def_map, line);
|
||||||
res = _skip_until(source, SKIP_UNTIL_CURR_BRANCH_END);
|
|
||||||
if (res == PP_FAILED)
|
if (!exp_line)
|
||||||
return res;
|
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);
|
fgets(line, PP_LINE_LEN, source);
|
||||||
if (IS_ELSE_LINE(line)) {
|
if (IS_ELSE_LINE(line)) {
|
||||||
else_en = 1;
|
else_en = 1;
|
||||||
} else {
|
} else {
|
||||||
line_len = strlen(line);
|
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;
|
return PP_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if_en = 1;
|
if_en = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(exp_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PP_OK;
|
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_ifdef.h"
|
||||||
#include "pp_defines.h"
|
#include "pp_defines.h"
|
||||||
|
#include "expand_line.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "hashmap.h"
|
#include "pp_line_id.h"
|
||||||
#include <stdio.h>
|
#include "line_handler.h"
|
||||||
#include <string.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define IFDEF_LINE_START "#ifdef "
|
int _is_sym_defined(void *def_map, char *ifdef_line);
|
||||||
#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 ELSE_LINE_START "#else"
|
int expand_ifdef(void *def_map, const struct str_dyn_arr *inc_dirs,
|
||||||
#define ELSE_LINE_START_SZ (sizeof(ELSE_LINE_START) - 1)
|
FILE *source, FILE *out)
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
char line[PP_LINE_LEN + 1];
|
char line[PP_LINE_LEN + 1];
|
||||||
|
char *exp_line;
|
||||||
|
|
||||||
int line_len;
|
int ret;
|
||||||
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 line_len;
|
int line_len;
|
||||||
int if_en;
|
int if_en;
|
||||||
int else_en;
|
int else_en;
|
||||||
|
@ -96,88 +27,142 @@ int _expand_ifdef(string_map_t define_map, FILE *source, FILE *output)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (if_en && IS_ELSE_LINE(line)) {
|
if (if_en && IS_ELSE_LINE(line)) {
|
||||||
res = _ifdef_skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
ret = skip_until(source, SKIP_UNTIL_ENDIF_LINE);
|
||||||
if (res == PP_FAILED)
|
if (ret == -1)
|
||||||
return res;
|
return PP_FAILED;
|
||||||
if_en = 0;
|
if_en = 0;
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (if_en || else_en) {
|
if (if_en || else_en) {
|
||||||
res = write_line_to_file(output, line);
|
ret = line_handler(
|
||||||
if (res == -1)
|
line,
|
||||||
return res;
|
def_map,
|
||||||
|
inc_dirs,
|
||||||
|
source,
|
||||||
|
out
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ret == PP_FAILED)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_IFDEF_LINE(line)) {
|
if (IS_IFDEF_LINE(line)) {
|
||||||
if (!_is_sym_defined(define_map, line)) {
|
exp_line = get_expanded_line(def_map, line);
|
||||||
res = _ifdef_skip_until(source, SKIP_UNTIL_CURR_BRANCH_END);
|
if (!exp_line)
|
||||||
if (res == PP_FAILED)
|
return PP_FAILED;
|
||||||
return res;
|
|
||||||
|
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);
|
fgets(line, PP_LINE_LEN, source);
|
||||||
if (IS_ELSE_LINE(line)) {
|
if (IS_ELSE_LINE(line)) {
|
||||||
else_en = 1;
|
else_en = 1;
|
||||||
} else {
|
} else {
|
||||||
line_len = strlen(line);
|
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;
|
return PP_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if_en = 1;
|
if_en = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(exp_line);
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_IFNDEF_LINE(line)) {
|
if (IS_IFNDEF_LINE(line)) {
|
||||||
if (_is_sym_defined(define_map, line)) {
|
exp_line = get_expanded_line(def_map, line);
|
||||||
res = _ifdef_skip_until(source, SKIP_UNTIL_CURR_BRANCH_END);
|
|
||||||
if (res == PP_FAILED)
|
if (!exp_line)
|
||||||
return res;
|
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);
|
fgets(line, PP_LINE_LEN, source);
|
||||||
|
|
||||||
if (IS_ELSE_LINE(line)) {
|
if (IS_ELSE_LINE(line)) {
|
||||||
else_en = 1;
|
else_en = 1;
|
||||||
} else {
|
} else {
|
||||||
line_len = strlen(line);
|
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;
|
return PP_FAILED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if_en = 1;
|
if_en = 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
free(exp_line);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return PP_OK;
|
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 sym_len;
|
||||||
int line_len;
|
int ret;
|
||||||
|
|
||||||
while (fgets(line, PP_LINE_LEN, source)) {
|
sym = NULL;
|
||||||
if (IS_IFDEF_LINE(line) || IS_IFNDEF_LINE(line)) {
|
mapp = NULL;
|
||||||
line_len = strlen(line);
|
|
||||||
|
|
||||||
res = fseek(source, -line_len, SEEK_CUR);
|
if (!strncmp(ifdef_line, IFDEF_LINE_START, IFDEF_LINE_START_SZ))
|
||||||
if (res == -1)
|
sym = ifdef_line + IFDEF_LINE_START_SZ;
|
||||||
return PP_FAILED;
|
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);
|
if (!sym)
|
||||||
} else {
|
return 0;
|
||||||
res = write_line_to_file(output, line);
|
|
||||||
if (res == -1)
|
sym_len = strlen(sym);
|
||||||
return PP_FAILED;
|
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
|
56
so-cpp.c
56
so-cpp.c
|
@ -1,5 +1,4 @@
|
||||||
// SPDX-License-Identifier: BSD-2
|
/* SPDX-License-Identifier: BSD-2 */
|
||||||
|
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "pp.h"
|
#include "pp.h"
|
||||||
#include "pp_defines.h"
|
#include "pp_defines.h"
|
||||||
|
@ -7,43 +6,41 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
string_map_t define_map;
|
void *def_map;
|
||||||
struct args *args;
|
struct args *args;
|
||||||
FILE *in;
|
FILE *source;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
define_map = NULL;
|
def_map = NULL;
|
||||||
args = NULL;
|
args = NULL;
|
||||||
in = NULL;
|
source = NULL;
|
||||||
out = NULL;
|
out = NULL;
|
||||||
|
|
||||||
define_map = hashmap_new();
|
def_map = hashmap_new();
|
||||||
args = pp_parse_args(argc, argv, define_map);
|
args = pp_parse_args(argc, argv, def_map);
|
||||||
|
|
||||||
if (!args) {
|
if (!args) {
|
||||||
if (errno) {
|
if (errno)
|
||||||
ret = errno;
|
ret = errno;
|
||||||
goto free_and_exit;
|
else
|
||||||
}
|
ret = PP_FAILED;
|
||||||
if (pp_errno != PP_OK) {
|
goto free_and_exit;
|
||||||
ret = pp_errno;
|
|
||||||
goto free_and_exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->in_file) {
|
if (args->in_file) {
|
||||||
in = fopen(args->in_file, "r");
|
source = fopen(args->in_file, "rb");
|
||||||
if (!in) {
|
if (!source) {
|
||||||
ret = errno;
|
ret = errno;
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
in = stdin;
|
source = stdin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->out_file) {
|
if (args->out_file) {
|
||||||
|
@ -56,20 +53,31 @@ int main(int argc, char **argv)
|
||||||
out = stdout;
|
out = stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pp_start(define_map, in, out);
|
ret = pp_compute(def_map, args->inc_dirs, source, out);
|
||||||
if (ret != PP_OK)
|
|
||||||
|
if (ret == PP_FAILED && errno == ENOMEM) {
|
||||||
|
ret = ENOMEM;
|
||||||
goto free_and_exit;
|
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;
|
ret = errno;
|
||||||
|
|
||||||
free_and_exit:
|
free_and_exit:
|
||||||
hashmap_free(define_map);
|
hashmap_free(def_map);
|
||||||
pp_free_args(args);
|
pp_free_args(args);
|
||||||
if (in)
|
if (source)
|
||||||
fclose(in);
|
fclose(source);
|
||||||
if (out)
|
if (out)
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
|
||||||
return ret;
|
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 <errno.h>
|
||||||
#include <stdlib.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 = NULL;
|
||||||
|
|
||||||
a = calloc(1, sizeof(struct char_dyn_arr));
|
a = calloc(1, sizeof(struct str_dyn_arr));
|
||||||
if (!a)
|
if (!a)
|
||||||
goto free_and_exit;
|
goto free_and_exit;
|
||||||
|
|
||||||
|
@ -24,13 +24,14 @@ struct char_dyn_arr *init_char_dyn_arr(int size)
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
free_and_exit:
|
free_and_exit:
|
||||||
|
if (a)
|
||||||
|
free(a->data);
|
||||||
free(a);
|
free(a);
|
||||||
free(a->data);
|
|
||||||
|
|
||||||
return NULL;
|
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) {
|
if (a->used == a->size) {
|
||||||
a->size *= 2;
|
a->size *= 2;
|
||||||
|
@ -50,7 +51,7 @@ free_and_exit:
|
||||||
return CHAR_DYN_ARR_FAILED;
|
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;
|
int i;
|
||||||
|
|
135
utils.c
135
utils.c
|
@ -1,6 +1,10 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "pp_defines.h"
|
||||||
|
#include "pp_line_id.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
int write_line_to_file(FILE *f, char *line)
|
int write_line_to_file(FILE *f, char *line)
|
||||||
{
|
{
|
||||||
|
@ -16,3 +20,134 @@ int write_line_to_file(FILE *f, char *line)
|
||||||
return 0;
|
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