Compare commits

...

15 Commits

Author SHA1 Message Date
Jan Nieuwenhuizen c842a65dfc
Revert "bootstrappable: vstack."
This reverts commit 2fc3784892.
2018-10-03 21:17:46 +02:00
Jan Nieuwenhuizen 2fc3784892
bootstrappable: vstack. 2018-10-03 21:17:42 +02:00
Jan Nieuwenhuizen f2b471409f
build 2018-10-03 21:17:39 +02:00
Jan Nieuwenhuizen 812e9343e4
bootstrappable: Force static link. 2018-09-18 07:29:10 +02:00
Jan Nieuwenhuizen 80eecb15ca
bootstrappable: Work around MesCC bug.
* tccelf.c (squeeze_multi_relocs): Simplify expressions.
2018-09-18 07:29:10 +02:00
Jan Nieuwenhuizen fb5db716f1
bootstrappable: add tcc.h include guards to include location. 2018-09-18 07:29:09 +02:00
Jan Nieuwenhuizen f4d018677a
bootstrappable: uint16_t in struct on heap. 2018-09-18 07:29:09 +02:00
Jan Nieuwenhuizen ad531e6cf9
bootstrappable: Handle libtcc1.a. 2018-09-18 07:29:09 +02:00
Jan Nieuwenhuizen 8a100a504c
bootstrappable: Skip tidy_section_headers.
* tccelf.c (elf_output_file)[BOOTSTRAPPABLE]: Skip tidy_section_headers.
2018-09-18 07:29:09 +02:00
Jan Nieuwenhuizen 3c366a2777
bootstrappable: HAVE_FLOAT. 2018-09-18 07:29:09 +02:00
Jan Nieuwenhuizen c5ed7ef2d1
bootstrappable: HAVE_BITFIELD. 2018-09-18 07:29:09 +02:00
Jan Nieuwenhuizen 603369913c
bootstrappable: HAVE_LONG_LONG.
* tccpp.c (parse_number)[!HAVE_LONG_LONG]: Skip overflow test.  Do not
  set TOK_CCLONG.
2018-09-18 07:29:09 +02:00
Jan Nieuwenhuizen c44bbd3db7
bootstrappable: Work around Nyacc-0.80.42 bug.
* tccgen.c (update_storage)[__MESC__]: Work around Nyacc-0.80.42 bug.
2018-09-18 07:29:08 +02:00
Jan Nieuwenhuizen c3356933f6
build: bootstrap build scripts.
* bootstrap.sh: New file.
* build.sh: New file.
* check.sh: New file.
* doit: New file.
* install.sh: New file.
* test.sh: New file.
2018-09-18 07:28:57 +02:00
Jan Nieuwenhuizen 584478fca2
bootstrappable: Remove non-free grep test.
* tests/tests2/46_grep.c: Remove non-free grep code.
* tests/tests2/46_grep.expect: Remove.
2018-09-18 07:27:57 +02:00
30 changed files with 1001 additions and 577 deletions

8
BOOT Normal file
View File

@ -0,0 +1,8 @@
#export LIBRARY_PATH=/home/janneke/src/tinycc-seed
#export INCLUDE_PATH=/home/janneke/src/mes/include
export C_INCLUDE_PATH=/home/janneke/src/mes/include
export LIBRARY_PATH=/home/janneke/src/tinycc-seed
./configure --cc='mes-tcc -static' --cpu=i386
make ONE_SOURCE=yes CPPFLAGS=-DONE_SOURCE=yes

View File

@ -188,7 +188,7 @@ $(X)%.o : %.c $(LIBTCC_INC)
$(X)tcc.o : tcctools.c
# Host Tiny C Compiler
tcc$(EXESUF): tcc.o $(LIBTCC)
$(PROGRAM_PREFIX)tcc$(EXESUF): tcc.o $(LIBTCC)
$(CC) -o $@ $^ $(LIBS) $(LDFLAGS) $(LINK_LIBTCC)
# Cross Tiny C Compilers

131
boot.sh Executable file
View File

@ -0,0 +1,131 @@
#! /bin/sh
set -ex
TCC=${TCC-./mes-tcc}
if [ "$TCC" = ./mes-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot0-}
elif [ "$TCC" = ./boot0-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot1-}
elif [ "$TCC" = ./boot1-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot2-}
elif [ "$TCC" = ./boot2-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot3-}
elif [ "$TCC" = ./boot3-tcc ]; then
PROGRAM_PREFIX=${PROGRAM_PREFIX-boot4-}
fi
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
mkdir -p $PREFIX
ABSPREFIX=$(cd $PREFIX && pwd)
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
##MES_PREFIX=${MES_PREFIX-$(dirname $MESCC)/../share/mes}
C_INCLUDE_PATH=${C_INCLUDE_PATH-$MES_PREFIX/include}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
LIBRARY_PATH=${LIBRARY_PATH-..$TINYCC_SEED}
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
# ./configure --cc='mes-tcc -static' --cpu=i386
# ${TCC-tcc} -static -o tcc tcc.c -DTCC_TARGET_I386 -Wall -g -O2 -I. -DONE_SOURCE=yes
if [ "$PROGRAM_PREFIX" = "boot0-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D inline=
-D BOOTSTRAP=1
-D HAVE_FLOAT_STUB=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot1-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
-D HAVE_FLOAT_STUB=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot2-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_BITFIELD=1
-D HAVE_FLOAT_STUB=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
LIBTCC1=-ltcc1
elif [ "$PROGRAM_PREFIX" = "boot3-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_FLOAT=1
-D HAVE_BITFIELD=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
elif [ "$PROGRAM_PREFIX" = "boot4-" ]; then
BOOT_CPPFLAGS=${BOOT_CPPFLAGS-"
-D BOOTSTRAP=1
-D HAVE_FLOAT=1
-D HAVE_BITFIELD=1
-D HAVE_LONG_LONG=1
-D CONFIG_TCCBOOT=1
-D CONFIG_USE_LIBGCC=1
-D TCC_MES_LIBC=1
"}
fi
$TCC\
-v\
-static\
-o ${PROGRAM_PREFIX}tcc\
$BOOT_CPPFLAGS\
-I .\
-I $MES_PREFIX/include\
-D TCC_TARGET_I386\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D ONE_SOURCE=yes\
-D CONFIG_TCC_LIBTCC1=1\
-D CONFIG_TCC_STATIC=1\
-D TCC_TARGET_I386=1\
-L .\
-L $TINYCC_SEED\
tcc.c\
$LIBTCC1
for i in 1 i n; do
rm -f crt$i.o;
./${PROGRAM_PREFIX}tcc -c $MES_PREFIX/lib/linux/x86-mes-gcc/crt$i.c
done
# rm -f libc.a
# ./${PROGRAM_PREFIX}tcc -c -I $MES_PREFIX/include -I $MES_PREFIX/lib $MES_PREFIX/lib/libc+gnu.c
# ./${PROGRAM_PREFIX}tcc -ar rc libc.a libc+gnu.o
rm -f libtcc1.a
./${PROGRAM_PREFIX}tcc -c -g -D TCC_TARGET_I386=1 -o libtcc1.o lib/libtcc1.c
./${PROGRAM_PREFIX}tcc -ar rc libtcc1.a libtcc1.o
mkdir -p $PREFIX/lib/tcc
cp -f libtcc1.a $PREFIX/lib/tcc

12
bootstrap.sh Executable file
View File

@ -0,0 +1,12 @@
#! /bin/sh
set -ex
export PREFIX=usr
export HEX2=../mescc-tools/bin/hex2
export M1=../mescc-tools/bin/M1
export MESCC=../mes/guile/mescc.scm
export MES_PREFIX=../mes
export TINYCC_SEED=../tinycc-seed
sh build.sh
sh check.sh

20
build-gcc.sh Executable file
View File

@ -0,0 +1,20 @@
#! /bin/sh
set -ex
rm -f tcc
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
touch config.mak
make clean
rm -f crt*.o
crt1=$(gcc --print-file-name=crt1.o)
#crtdir=$(dirname $crt1)
#crti=$(gcc --print-file-name=crti.o)
#crtn=$(gcc --print-file-name=crtn.o)
unset ONE_SOURCE
./configure --tccdir=$PWD --crtprefix=$crtdir --extra-cflags="-DHAVE_FLOAT=1 -DHAVE_BITFIELD=1"
make ETAGS
make PROGRAM_PREFIX=gcc- gcc-tcc
make libtcc1.a

62
build-x86.sh Executable file
View File

@ -0,0 +1,62 @@
#! /bin/sh
set -ex
rm -f i686-unknown-linux-gnu-tcc
# crt1=$(i686-unknown-linux-gnu-gcc --print-file-name=crt1.o)
# crtdir=$(dirname $crt1)
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
GUIX=${GUIX-$(command -v guix||:)}
MES_PREFIX=${MES_PREFIX-../mes}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}/../share/mes}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
cp $TINYCC_SEED/x86-mes-gcc/crt1.o crt1.o
cp $TINYCC_SEED/x86-mes-gcc/crti.o crti.o
cp $TINYCC_SEED/x86-mes-gcc/crtn.o crtn.o
CC=${CC-i686-unknown-linux-gnu-gcc}
CFLAGS="
-nostdinc
-nostdlib
-fno-builtin
--include=$MES_PREFIX/lib/linux/x86-mes-gcc/crt1.c
--include=$MES_PREFIX/lib/libc+tcc.c
--include=$MES_PREFIX/lib/libtcc1.c
-Wl,-Ttext-segment=0x1000000
"
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
mkdir -p $PREFIX/lib
ABSPREFIX=$(cd $PREFIX && pwd)
cp $TINYCC_SEED/x86-mes-gcc/libc+tcc.o $ABSPREFIX/lib
cp $TINYCC_SEED/x86-mes-gcc/libtcc1.o $ABSPREFIX/lib
$CC -g -o i686-unknown-linux-gnu-tcc\
$CFLAGS\
-I.\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D CONFIG_USE_LIBGCC=1\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D ONE_SOURCE=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
tcc.c

110
build.sh Executable file
View File

@ -0,0 +1,110 @@
#! /bin/sh
set -e
export BUILD_DEBUG
export MES_DEBUG
export MES_PREFIX
export PREFIX
export TINYCC_SEED
export interpreter
if [ -n "$BUILD_DEBUG" ]; then
set -x
MESCCFLAGS="$MESCCFLAGS -v"
fi
rm -f tcc.E tcc.hex2 tcc.M1 tcc.m1 mes-tcc boot?-tcc
unset C_INCLUDE_PATH LIBRARY_PATH
PREFIX=${PREFIX-usr}
GUIX=${GUIX-$(command -v guix||:)}
CC=${MESCC-mescc}
MES=${MES-../mes/src/mes}
MESCC=${MESCC-mescc}
HEX2=${HEX2-hex2}
M1=${M1-M1}
BLOOD_ELF=${BLOOD_ELF-blood-elf}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}/../share/mes}
#MES_PREFIX=${MES_PREFIX-../mes}
MES_SEED=${MES_SEED-../mes-seed}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
cp $TINYCC_SEED/x86-mes-tcc/crt1.o crt1.o
cp $TINYCC_SEED/x86-mes-tcc/crti.o crti.o
cp $TINYCC_SEED/x86-mes-tcc/crtn.o crtn.o
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
mkdir -p $PREFIX/lib
ABSPREFIX=$(cd $PREFIX && pwd)
cp $TINYCC_SEED/x86-mes-tcc/libc+tcc.o $ABSPREFIX/lib
if [ -n "$ONE_SOURCE" ]; then
sh cc.sh tcc
files="tcc.S"
else
sh cc.sh tccpp
sh cc.sh tccgen
sh cc.sh tccelf
sh cc.sh tccrun
sh cc.sh i386-gen
sh cc.sh i386-link
sh cc.sh i386-asm
sh cc.sh tccasm
sh cc.sh libtcc
sh cc.sh tcc
files="
tccpp.S
tccgen.S
tccelf.S
tccrun.S
i386-gen.S
i386-link.S
i386-asm.S
tccasm.S
libtcc.S
tcc.S
"
fi
$MESCC\
$MESCCFLAGS\
-g\
-o mes-tcc\
-L $TINYCC_SEED\
-L $MES_SEED\
-l c+tcc\
$files\
$TINYCC_SEED/x86-mes/libc+tcc.o
rm -f libc.a
if false; then
# ../mes/lib/linux-gcc.c:33: error: bad operand with opcode 'mov'
# it works with bootx-tcc
./mes-tcc -c -I $MES_PREFIX/include -I $MES_PREFIX/lib $MES_PREFIX/lib/libc+gnu.c
./mes-tcc -ar rc libc.a libc+gnu.o
else
##./mes-tcc -ar rc libc.a $TINYCC_SEED/x86-mes-tcc/libc+gnu.o
cp -f $TINYCC_SEED/x86-mes-gcc/libc+gnu.o .
./mes-tcc -ar rc libc.a libc+gnu.o
fi
rm -f libtcc1.a
cp -f $TINYCC_SEED/x86-mes-gcc/libtcc1.o .
./mes-tcc -ar rc libtcc1.a libtcc1.o
sh boot.sh
TCC=./boot0-tcc sh boot.sh
TCC=./boot1-tcc sh boot.sh
TCC=./boot2-tcc sh boot.sh
TCC=./boot3-tcc sh boot.sh
ln -f boot4-tcc tcc

78
cc.sh Executable file
View File

@ -0,0 +1,78 @@
#! /bin/sh
set -e
if [ -n "$BUILD_DEBUG" ]; then
set -x
MESCCFLAGS="$MESCCFLAGS -v"
fi
t=$1
rm -f $t.E $t.M1 $t.m1
GUIX=${GUIX-$(command -v guix||:)}
CC=${MESCC-mescc}
MES=${MES-../mes/src/mes}
MESCC=${MESCC-mescc}
CFLAGS=${CFLAGS-}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
ABSPREFIX=$(cd $PREFIX && pwd)
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
ulimit -s 17030
if [ -n "$ONE_SOURCE" ]; then
CFLAGS="$CFLAGS -D ONE_SOURCE=$ONE_SOURCE"
fi
if [ -n "$PREPROCESS" ]; then
time sh $MESCC $MESCCFLAGS -E -o $t.E\
$CFLAGS\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
$t.c
time sh $MESCC $MESCCFLAGS -S -o $t.M1 $t.E
else
time sh $MESCC $MESCCFLAGS -S -o $t.M1\
$CFLAGS\
-I .\
-I $MES_PREFIX/lib\
-I $MES_PREFIX/include\
-D inline=\
-D 'CONFIG_TCCDIR="'$PREFIX'/lib/tcc"'\
-D 'CONFIG_TCC_CRTPREFIX="'$PREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_ELFINTERP="'$interpreter'"'\
-D 'CONFIG_TCC_LIBPATHS="'$ABSPREFIX'/lib:{B}/lib:."'\
-D 'CONFIG_TCC_SYSINCLUDEPATHS="'$MES_PREFIX'/include:'$PREFIX'/include:{B}/include"'\
-D CONFIG_USE_LIBGCC=1\
-D 'TCC_LIBGCC="'$ABSPREFIX'/lib/libc.a"'\
-D BOOTSTRAP=1\
-D CONFIG_TCCBOOT=1\
-D CONFIG_TCC_STATIC=1\
-D CONFIG_USE_LIBGCC=1\
-D TCC_MES_LIBC=1\
-D TCC_TARGET_I386=1\
$t.c
fi
tr -d '\r' < $t.M1 > $t.S

265
check.sh Executable file
View File

@ -0,0 +1,265 @@
#! /bin/sh
###MESCC=${MESCC-mescc}
MES_ARENA=70000000
MES_MAX_ARENA=70000000
export MES_ARENA MES_MAX_ARENA
MES=guile
MESCC=${MESCC-../mes/pre-inst-env mescc}
MES_PREFIX=${MES_PREFIX-../mes}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
tests="
t
00-exit-0
01-return-0
02-return-1
03-call
04-call-0
05-call-1
06-call-!1
10-if-0
11-if-1
12-if-==
13-if-!=
14-if-goto
15-if-!f
16-if-t
20-while
21-char[]
22-while-char[]
23-pointer
30-strlen
31-eputs
32-compare
33-and-or
34-pre-post
35-compare-char
36-compare-arithmetic
37-compare-assign
38-compare-call
40-if-else
41-?
42-goto-label
43-for-do-while
44-switch
45-void-call
46-function-static
47-function-expression
48-function-destruct
49-global-static
4a-char-array
50-assert
51-strcmp
52-itoa
53-strcpy
54-argv
60-math
61-array
62-array
63-struct-cell
64-make-cell
65-read
70-printf
71-struct-array
72-typedef-struct-def
73-union
74-multi-line-string
75-struct-union
76-pointer-arithmetic
77-pointer-assign
78-union-struct
79-int-array
7a-struct-char-array
7b-struct-int-array
7c-dynarray
7d-cast-char
7e-struct-array-access
7f-struct-pointer-arithmetic
7g-struct-byte-word-field
7h-struct-assign
7i-struct-struct
7j-strtoull
7k-for-each-elem
7l-struct-any-size-array
7m-struct-char-array-assign
7n-struct-struct-array
7o-struct-pre-post
7p-struct-cast
7q-bit-field
80-setjmp
81-qsort
82-define
83-heterogenoous-init
84-struct-field-list
86-strncpy
87-sscanf
90-strpbrk
91-fseek
"
broken="
t
00-exit-0
01-return-0
02-return-1
03-call
04-call-0
05-call-1
06-call-!1
10-if-0
11-if-1
12-if-==
13-if-!=
14-if-goto
15-if-!f
16-if-t
20-while
21-char[]
22-while-char[]
23-pointer
"
if [ ! -x ./i686-unknown-linux-gnu-tcc ]; then
broken="$broken
02-return-1
05-call-1
"
fi
expect=$(echo $broken | wc -w)
mkdir -p scaffold/tests
set +e
pass=0
fail=0
total=0
for t in $tests; do
sh test.sh "$MES_PREFIX/scaffold/tests/$t" &> "scaffold/tests/$t".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
tests="
00_assignment
01_comment
02_printf
03_struct
04_for
05_array
06_case
07_function
08_while
09_do_while
10_pointer
11_precedence
12_hashdefine
13_integer_literals
14_if
15_recursion
16_nesting
17_enum
18_include
19_pointer_arithmetic
20_pointer_comparison
21_char_array
22_floating_point
23_type_coercion
24_math_library
25_quicksort
26_character_constants
27_sizeof
28_strings
29_array_address
30_hanoi
31_args
32_led
33_ternary_op
34_array_assignment
35_sizeof
36_array_initialisers
37_sprintf
38_multiple_array_index
39_typedef
40_stdio
41_hashif
42_function_pointer
43_void_param
44_scoped_declarations
45_empty_for
47_switch_return
48_nested_break
49_bracket_evaluation
50_logical_second_arg
51_static
52_unnamed_enum
54_goto
55_lshift_type
"
broken="$broken
22_floating_point
23_type_coercion
24_math_library
34_array_assignment
37_sprintf
40_stdio
49_bracket_evaluation
55_lshift_type
"
#22_floating_point ; float
#23_type_coercion ; float
#24_math_library ; float
#27_sizeof ; float
#34_array_assignment ; fails with GCC
#37_sprintf ; integer formatting unsupported
#49_bracket_evaluation ; float
mkdir -p scaffold/tinycc
expect=$(echo $broken | wc -w)
for t in $tests; do
if [ ! -f $MES_PREFIX/scaffold/tinycc/"$t.c" ]; then
echo ' [SKIP]'
continue;
fi
sh test.sh "$MES_PREFIX/scaffold/tinycc/$t" &> scaffold/tinycc/"$t".log
r=$?
total=$((total+1))
if [ $r = 0 ]; then
echo $t: [OK]
pass=$((pass+1))
else
echo $t: [FAIL]
fail=$((fail+1))
fi
done
[ $expect != 0 ] && echo "expect: $expect"
[ $fail != 0 ] && echo "failed: $fail"
echo "passed: $pass"
[ $fail -lt $expect ] && echo "solved: $(($expect - $fail))"
echo "total: $total"
if [ $fail != 0 -a $fail -gt $expect ]; then
echo FAILED: $fail/$total
exit 1
elif [ $fail != 0 ]; then
echo PASS: $pass/$total
else
echo PASS: $total
fi

15
compile.sh Executable file
View File

@ -0,0 +1,15 @@
#! /bin/sh
set -ex
rm -f *.i686-unknown-linux-gnu-o *.mes-o
rm -f 1 2 1.elf 2.elf 1.a 2.a
# trivial object
./tcc -c -I ../mes/include ../mes/scaffold/main.c 2>/dev/null
./i686-unknown-linux-gnu-tcc -o main.i686-unknown-linux-gnu-o -c -I ../mes/include ../mes/scaffold/main.c 2> 1
set +e
./mes-tcc -o main.mes-o -c -I ../mes/include ../mes/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.i686-unknown-linux-gnu-o > 1.elf
readelf -a main.mes-o > 2.elf
diff -y 1.elf 2.elf || :

21
d Executable file
View File

@ -0,0 +1,21 @@
#! /bin/sh
set -ex
rm -f *.o *.a *.E *.hex2 *.mesc-o *.i686-unknown-linux-gnu-o *.M1
rm -f 1 2 1.elf 2.elf
# trivial object
set +e
./tcc -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2>/dev/null
./i686-unknown-linux-gnu-tcc -o main.i686-unknown-linux-gnu-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1
./tcc.mes -o main.mesc-o -c -I ../mes/mlibc/include ../mes/scaffold/main.c &> 2
diff -y 1 2
readelf -a main.i686-unknown-linux-gnu-o > 1.elf
readelf -a main.mesc-o > 2.elf
diff -y 1.elf 2.elf
# trivial bin
./tcc ../mes/scaffold/main.c
./i686-unknown-linux-gnu-tcc -o a.i686-unknown-linux-gnu-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 1.a
./tcc.mes -o a.mes-out -I ../mes/mlibc/include ../mes/scaffold/main.c 2> 2.a
diff -y 1.a 2.a

59
doit Executable file
View File

@ -0,0 +1,59 @@
#! /bin/sh
set -ex
export BLOOD_ELF
export BUILD_DEBUG
export GUILE_LOAD_PATH
export HEX2
export M1
export MES
export MESCC
export MES_DEBUG
export MES_PREFIX
export ONE_SOURCE
export PREFIX
export PREPROCESS
export TINYCC_SEED
PREFIX=usr
HEX2=../mescc-tools/bin/hex2
M1=../mescc-tools/bin/M1
BLOOD_ELF=../mescc-tools/bin/blood-elf
MES=${MES-../mes/src/mes}
MES_ARENA=70000000
MES_MAX_ARENA=70000000
export MES_ARENA MES_MAX_ARENA
MES=guile
#MES=${MES-../mes/src/mes.gcc}
#MES=${MES-../mes/src/mes.mlibc-gcc}
MESCC=${MESCC-../mes/pre-inst-env mescc}
#GUILE_LOAD_PATH=/home/janneke/src/nyacc/module:$GUILE_LOAD_PATH
GUILE_LOAD_PATH=nyacc
MES_DEBUG=2
MES_PREFIX=../mes
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
if [ -z "$interpreter" -a -n "$GUIX" ]; then
interpreter=$($GUIX environment --ad-hoc patchelf -- patchelf --print-interpreter $(guix build --system=i686-linux hello)/bin/hello)
elif [ -x /lib/ld-linux.so.2 ]; then
# legacy non-GuixSD support
interpreter=/lib/ld-linux.so.2
fi
interpreter=${interpreter-interpreter}
export interpreter
sh build-gcc.sh
PREPROCESS=1
ONE_SOURCE=1
sh build-x86.sh
sh build.sh
sh compile.sh
sh link.sh ||:
sh check.sh
rm -rf usr
sh install.sh

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAX_OPERANDS 3

View File

@ -74,7 +74,9 @@ enum {
/******************************************************/
#else /* ! TARGET_DEFS_ONLY */
/******************************************************/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* define to 1/0 to [not] have EBX as 4th register */
#define USE_EBX 0

View File

@ -20,7 +20,9 @@
#else /* !TARGET_DEFS_ONLY */
#ifndef _TCC_H
#include "tcc.h"
#endif
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
relocations, returns -1. */

26
install.sh Executable file
View File

@ -0,0 +1,26 @@
#! /bin/sh
if [ -n "$BUILD_DEBUG" ]; then
set -x
fi
set -e
PREFIX=${PREFIX-usr}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
mkdir -p $PREFIX/bin
cp tcc $PREFIX/bin
tar -C $MES_PREFIX -cf- include | tar -C $PREFIX -xf-
mkdir -p $PREFIX/lib
cp crt1.o $PREFIX/lib/crt1.o
cp crti.o $PREFIX/lib/crti.o
cp crtn.o $PREFIX/lib/crtn.o
mkdir -p $PREFIX/lib/tcc
cp libc.a $PREFIX/lib
cp libtcc1.a $PREFIX/lib/tcc
tar -C $TINYCC_SEED -cf- . | tar -C $PREFIX/lib -xf-

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/********************************************************/
/* global variables */
@ -734,6 +736,9 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_state = s;
++nb_states;
#if BOOTSTRAP
s->static_link = 1;
#endif
s->alacarte_link = 1;
s->nocommon = 1;
s->warn_implicit_function_declaration = 1;
@ -1445,8 +1450,13 @@ static int tcc_set_linker(TCCState *s, const char *option)
typedef struct TCCOption {
const char *name;
#if !BOOTSTRAP
uint16_t index;
uint16_t flags;
#else
int index;
int flags;
#endif
} TCCOption;
enum {

29
link.sh Executable file
View File

@ -0,0 +1,29 @@
#! /bin/sh
set -ex
rm -f 1.a 2.a
MES_PREFIX=${MES_PREFIX-../mes}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
# trivial bin
###./tcc ../mes/scaffold/main.c
c=${1-$MES_PREFIX/scaffold/main}
b=scaffold/${c##*/}
rm -f "$b".mes-gcc-out
rm -f "$b".mes-out
./i686-unknown-linux-gnu-tcc\
-static -g -o "$b".mes-gcc-out -I $MES_PREFIX/include -L $TINYCC_SEED "$c".c 2> "$b".mes-gcc-stderr
set +e
${MES_TCC-./mes-tcc}\
-static -g -o "$b".mes-out -I $MES_PREFIX/include -L $TINYCC_SEED "$c".c 2> "$b".mes-stderr
objdump -d "$b".mes-gcc-out > "$b".mes-gcc-d
objdump -d "$b".mes-out > "$b".mes-d
#readelf -a a.i686-unknown-linux-gnu-out > 1.r
#readelf -a a.mes-out > 2.r
#diff -y 1.a 2.a
echo diff -y "$b".mes-gcc-stderr "$b".mes-stderr
echo diff -y "$b".mes-gcc-d "$b".mes-d
"$b".mes-out

17
tcc.h
View File

@ -410,6 +410,7 @@ typedef struct SValue {
} SValue;
struct Attribute {
#if HAVE_BITFIELD
unsigned
func_call : 3, /* calling convention (0..5), see below */
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
@ -423,6 +424,22 @@ struct Attribute {
visibility : 2,
unsigned_enum : 1,
fill : 7; // 7 bits left to fit well in union below
#else // !HAVE_BITFIELD
struct {
unsigned func_call;
unsigned aligned;
unsigned packed;
unsigned func_export;
unsigned func_import;
unsigned func_args;
unsigned func_body;
unsigned mode;
unsigned weak;
unsigned visibility;
unsigned unsigned_enum;
unsigned fill;
};
#endif // !HAVE_BITFIELD
};
/* GNUC attribute definition */

View File

@ -18,7 +18,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#ifdef CONFIG_TCC_ASM
ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)

View File

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
#define MAX_STR_TABLE 1000000

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* Define this to get some debug output during relocation processing. */
#undef DEBUG_RELOC
@ -566,9 +568,13 @@ ST_FUNC void squeeze_multi_relocs(Section *s, size_t oldrelocoffset)
a simple insertion sort. */
for (a = oldrelocoffset + sizeof(*r); a < sr->data_offset; a += sizeof(*r)) {
ssize_t i = a - sizeof(*r);
addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
///addr = ((ElfW_Rel*)(sr->data + a))->r_offset;
ElfW_Rel* ea = (ElfW_Rel*)(sr->data + a);
ElfW_Rel* ei = (ElfW_Rel*)(sr->data + i);
addr = ea->r_offset;
for (; i >= (ssize_t)oldrelocoffset &&
((ElfW_Rel*)(sr->data + i))->r_offset > addr; i -= sizeof(*r)) {
ei->r_offset > addr; i -= sizeof(*r)) {
ei = (ElfW_Rel*)(sr->data + i);
ElfW_Rel tmp = *(ElfW_Rel*)(sr->data + a);
*(ElfW_Rel*)(sr->data + a) = *(ElfW_Rel*)(sr->data + i);
*(ElfW_Rel*)(sr->data + i) = tmp;
@ -1146,7 +1152,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
tcc_add_dll(s1, TCC_LIBGCC, 0);
}
#endif
#if CONFIG_TCC_LIBTCC1
tcc_add_support(s1, TCC_LIBTCC1);
#endif
/* add crt end if not memory output */
if (s1->output_type != TCC_OUTPUT_MEMORY)
tcc_add_crt(s1, "crtn.o");
@ -2167,7 +2175,9 @@ static int elf_output_file(TCCState *s1, const char *filename)
ret = final_sections_reloc(s1);
if (ret)
goto the_end;
#if !BOOTSTRAP
tidy_section_headers(s1, sec_order);
#endif
}
/* Perform relocation to GOT or PLT entries */

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/********************************************************/
/* global variables */
@ -270,13 +272,16 @@ static void update_storage(Sym *sym)
t = sym->type.t;
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
#if !__MESC__ // Nyacc 0.80.40 cpp-bug
if (t & VT_VIS_MASK)
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
| ((t & VT_VIS_MASK) >> VT_VIS_SHIFT);
if (t & VT_WEAK)
esym->st_info = ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(esym->st_info));
#else //__MESC__
// #warning work around Nyacc 0.80.42 bug.
#endif // __MESC__
#ifdef TCC_TARGET_PE
if (t & VT_EXPORT)
esym->st_other |= ST_PE_EXPORT;
@ -1845,11 +1850,13 @@ static void gen_opif(int op)
case '-': f1 -= f2; break;
case '*': f1 *= f2; break;
case '/':
#if HAVE_FLOAT
if (f2 == 0.0) {
if (const_wanted)
tcc_error("division by zero in constant");
goto general_case;
}
#endif
f1 /= f2;
break;
/* XXX: also handles tests ? */
@ -4655,12 +4662,14 @@ ST_FUNC void unary(void)
/* In IEEE negate(x) isn't subtract(0,x), but rather
subtract(-0, x). */
vpush(&vtop->type);
#if HAVE_FLOAT
if (t == VT_FLOAT)
vtop->c.f = -1.0 * 0.0;
else if (t == VT_DOUBLE)
vtop->c.d = -1.0 * 0.0;
else
vtop->c.ld = -1.0 * 0.0;
#endif
} else
vpushi(0);
vswap();
@ -6190,7 +6199,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
#if (defined __i386__ || defined __x86_64__) && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64)
else if (sizeof (long double) >= 10)
memcpy(memset(ptr, 0, LDOUBLE_SIZE), &vtop->c.ld, 10);
#ifdef __TINYC__
#if defined (__TINYC__) && HAVE_FLOAT
else if (sizeof (long double) == sizeof (double))
__asm__("fldl %1\nfstpt %0\n" : "=m"
(memset(ptr, 0, LDOUBLE_SIZE), ptr) : "m" (vtop->c.ld));

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
#define PE_MERGE_DATA
/* #define PE_PRINT_SECTIONS */

11
tccpp.c
View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/********************************************************/
/* global variables */
@ -2282,7 +2284,9 @@ static void parse_number(const char *p)
/* now we can generate the number */
/* XXX: should patch directly float number */
#if HAVE_FLOAT
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
#endif
d = ldexp(d, exp_val - frac_bits);
t = toup(ch);
if (t == 'F') {
@ -2388,10 +2392,12 @@ static void parse_number(const char *p)
tcc_error("invalid digit");
n1 = n;
n = n * b + t;
#if HAVE_LONG_LONG
/* detect overflow */
/* XXX: this test is not reliable */
if (n < n1)
tcc_error("integer constant overflow");
#endif
}
/* Determine the characteristics (unsigned and/or 64bit) the type of
@ -2421,11 +2427,14 @@ static void parse_number(const char *p)
}
}
#if HAVE_LONG_LONG
/* Whether 64 bits are needed to hold the constant's value */
if (n & 0xffffffff00000000LL || must_64bit) {
tok = TOK_CLLONG;
n1 = n >> 32;
} else {
} else
#endif
{
tok = TOK_CINT;
n1 = n;
}

View File

@ -18,7 +18,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
/* only native compiler supports -run */
#ifdef TCC_IS_NATIVE

View File

@ -28,7 +28,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _TCC_H
#include "tcc.h"
#endif
//#define ARMAG "!<arch>\n"
#define ARFMAG "`\n"

87
test.sh Executable file
View File

@ -0,0 +1,87 @@
#! /bin/sh
set -ex
TCC=${TCC-./mes-tcc}
MESCC=${MESCC-mescc}
MES_PREFIX=${MES_PREFIX-../mes}
MES_PREFIX=${MES_PREFIX-${MESCC%/*}}
TINYCC_SEED=${TINYCC_SEED-../tinycc-seed}
OBJDUMP=${OBJDUMP-objdump}
DIFF=${DIFF-diff}
unset C_INCLUDE_PATH LIBRARY_PATH
t=${1-$MES_PREFIX/scaffold/tests/t}
mkdir -p scaffold
b=scaffold/${t##*/}
rm -f "$b".i686-unknown-linux-gnu-out
rm -f "$b".mes-out
r=0
if [ -x ./i686-unknown-linux-gnu-tcc ]; then
./i686-unknown-linux-gnu-tcc\
-c\
-o "$b".mes-gcc-o\
-nostdlib\
-g\
-m32\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
"$t".c &> 1
#$OBJDUMP -d "$t".mes-gcc-o > 1.s
./i686-unknown-linux-gnu-tcc\
-static\
-o "$b".mes-gcc-out\
-L .\
-L $TINYCC_SEED\
"$b".mes-gcc-o &> 1.link
set +e
"$b".mes-gcc-out arg1 arg2 arg3 arg4 arg5 > "$b".mes-gcc-stdout
m=$?
set -e
[ -f "$t".exit ] && r=$(cat "$t".exit)
[ $m = $r ]
if [ -f "$t".expect ]; then
$DIFF -ub "$t".expect "$b".mes-gcc-stdout;
fi
fi
$TCC\
-c\
-g\
-m32\
-o "$b".mes-o\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
"$t".c &> 2
$OBJDUMP -d "$b".mes-o > 2.s || true
$TCC\
-static\
-o "$b".mes-out\
-g\
-m32\
-D __TINYC__=1\
-I $MES_PREFIX/include\
-I $MES_PREFIX/scaffold/tests\
-I $MES_PREFIX/scaffold/tinycc\
-L $TINYCC_SEED\
"$t".c &> 2.link
set +e
"$b".mes-out arg1 arg2 arg3 arg4 arg5 > "$b".mes-stdout
m=$?
#$OBJDUMP -d "$t".mes-out > 2.x
set -e
[ $m = $r ]
[ -f "$t".exit ] && r=$(cat "$t".exit)
if [ -f "$t".expect ]; then
$DIFF -ub "$t".expect "$b".mes-stdout;
fi
#diff -y 1.s 2.s
#diff -y 1 2

View File

@ -1,568 +0,0 @@
/*
* The information in this document is subject to change
* without notice and should not be construed as a commitment
* by Digital Equipment Corporation or by DECUS.
*
* Neither Digital Equipment Corporation, DECUS, nor the authors
* assume any responsibility for the use or reliability of this
* document or the described software.
*
* Copyright (C) 1980, DECUS
*
* General permission to copy or modify, but not for profit, is
* hereby granted, provided that the above copyright notice is
* included and reference made to the fact that reproduction
* privileges were granted by DECUS.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> // tolower()
/*
* grep
*
* Runs on the Decus compiler or on vms, On vms, define as:
* grep :== "$disk:[account]grep" (native)
* grep :== "$disk:[account]grep grep" (Decus)
* See below for more information.
*/
char *documentation[] = {
"grep searches a file for a given pattern. Execute by",
" grep [flags] regular_expression file_list\n",
"Flags are single characters preceded by '-':",
" -c Only a count of matching lines is printed",
" -f Print file name for matching lines switch, see below",
" -n Each line is preceded by its line number",
" -v Only print non-matching lines\n",
"The file_list is a list of files (wildcards are acceptable on RSX modes).",
"\nThe file name is normally printed if there is a file given.",
"The -f flag reverses this action (print name no file, not if more).\n",
0 };
char *patdoc[] = {
"The regular_expression defines the pattern to search for. Upper- and",
"lower-case are always ignored. Blank lines never match. The expression",
"should be quoted to prevent file-name translation.",
"x An ordinary character (not mentioned below) matches that character.",
"'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.",
"'^' A circumflex at the beginning of an expression matches the",
" beginning of a line.",
"'$' A dollar-sign at the end of an expression matches the end of a line.",
"'.' A period matches any character except \"new-line\".",
"':a' A colon matches a class of characters described by the following",
"':d' character. \":a\" matches any alphabetic, \":d\" matches digits,",
"':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and",
"': ' other control characters, such as new-line.",
"'*' An expression followed by an asterisk matches zero or more",
" occurrences of that expression: \"fo*\" matches \"f\", \"fo\"",
" \"foo\", etc.",
"'+' An expression followed by a plus sign matches one or more",
" occurrences of that expression: \"fo+\" matches \"fo\", etc.",
"'-' An expression followed by a minus sign optionally matches",
" the expression.",
"'[]' A string enclosed in square brackets matches any character in",
" that string, but no others. If the first character in the",
" string is a circumflex, the expression matches any character",
" except \"new-line\" and the characters in the string. For",
" example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\"",
" matches \"abc\" but not \"axb\". A range of characters may be",
" specified by two characters separated by \"-\". Note that,",
" [a-z] matches alphabetics, while [z-a] never matches.",
"The concatenation of regular expressions is a regular expression.",
0};
#define LMAX 512
#define PMAX 256
#define CHAR 1
#define BOL 2
#define EOL 3
#define ANY 4
#define CLASS 5
#define NCLASS 6
#define STAR 7
#define PLUS 8
#define MINUS 9
#define ALPHA 10
#define DIGIT 11
#define NALPHA 12
#define PUNCT 13
#define RANGE 14
#define ENDPAT 15
int cflag=0, fflag=0, nflag=0, vflag=0, nfile=0, debug=0;
char *pp, lbuf[LMAX], pbuf[PMAX];
char *cclass();
char *pmatch();
void store(int);
void error(char *);
void badpat(char *, char *, char *);
int match(void);
/*** Display a file name *******************************/
void file(char *s)
{
printf("File %s:\n", s);
}
/*** Report unopenable file ****************************/
void cant(char *s)
{
fprintf(stderr, "%s: cannot open\n", s);
}
/*** Give good help ************************************/
void help(char **hp)
{
char **dp;
for (dp = hp; *dp; ++dp)
printf("%s\n", *dp);
}
/*** Display usage summary *****************************/
void usage(char *s)
{
fprintf(stderr, "?GREP-E-%s\n", s);
fprintf(stderr,
"Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n");
exit(1);
}
/*** Compile the pattern into global pbuf[] ************/
void compile(char *source)
{
char *s; /* Source string pointer */
char *lp; /* Last pattern pointer */
int c; /* Current character */
int o; /* Temp */
char *spp; /* Save beginning of pattern */
s = source;
if (debug)
printf("Pattern = \"%s\"\n", s);
pp = pbuf;
while (c = *s++) {
/*
* STAR, PLUS and MINUS are special.
*/
if (c == '*' || c == '+' || c == '-') {
if (pp == pbuf ||
(o=pp[-1]) == BOL ||
o == EOL ||
o == STAR ||
o == PLUS ||
o == MINUS)
badpat("Illegal occurrence op.", source, s);
store(ENDPAT);
store(ENDPAT);
spp = pp; /* Save pattern end */
while (--pp > lp) /* Move pattern down */
*pp = pp[-1]; /* one byte */
*pp = (c == '*') ? STAR :
(c == '-') ? MINUS : PLUS;
pp = spp; /* Restore pattern end */
continue;
}
/*
* All the rest.
*/
lp = pp; /* Remember start */
switch(c) {
case '^':
store(BOL);
break;
case '$':
store(EOL);
break;
case '.':
store(ANY);
break;
case '[':
s = cclass(source, s);
break;
case ':':
if (*s) {
switch(tolower(c = *s++)) {
case 'a':
case 'A':
store(ALPHA);
break;
case 'd':
case 'D':
store(DIGIT);
break;
case 'n':
case 'N':
store(NALPHA);
break;
case ' ':
store(PUNCT);
break;
default:
badpat("Unknown : type", source, s);
}
break;
}
else badpat("No : type", source, s);
case '\\':
if (*s)
c = *s++;
default:
store(CHAR);
store(tolower(c));
}
}
store(ENDPAT);
store(0); /* Terminate string */
if (debug) {
for (lp = pbuf; lp < pp;) {
if ((c = (*lp++ & 0377)) < ' ')
printf("\\%o ", c);
else printf("%c ", c);
}
printf("\n");
}
}
/*** Compile a class (within []) ***********************/
char *cclass(char *source, char *src)
/* char *source; // Pattern start -- for error msg. */
/* char *src; // Class start */
{
char *s; /* Source pointer */
char *cp; /* Pattern start */
int c; /* Current character */
int o; /* Temp */
s = src;
o = CLASS;
if (*s == '^') {
++s;
o = NCLASS;
}
store(o);
cp = pp;
store(0); /* Byte count */
while ((c = *s++) && c!=']') {
if (c == '\\') { /* Store quoted char */
if ((c = *s++) == '\0') /* Gotta get something */
badpat("Class terminates badly", source, s);
else store(tolower(c));
}
else if (c == '-' &&
(pp - cp) > 1 && *s != ']' && *s != '\0') {
c = pp[-1]; /* Range start */
pp[-1] = RANGE; /* Range signal */
store(c); /* Re-store start */
c = *s++; /* Get end char and*/
store(tolower(c)); /* Store it */
}
else {
store(tolower(c)); /* Store normal char */
}
}
if (c != ']')
badpat("Unterminated class", source, s);
if ((c = (pp - cp)) >= 256)
badpat("Class too large", source, s);
if (c == 0)
badpat("Empty class", source, s);
*cp = c;
return(s);
}
/*** Store an entry in the pattern buffer **************/
void store(int op)
{
if (pp >= &pbuf[PMAX])
error("Pattern too complex\n");
*pp++ = op;
}
/*** Report a bad pattern specification ****************/
void badpat(char *message, char *source, char *stop)
/* char *message; // Error message */
/* char *source; // Pattern start */
/* char *stop; // Pattern end */
{
fprintf(stderr, "-GREP-E-%s, pattern is\"%s\"\n", message, source);
fprintf(stderr, "-GREP-E-Stopped at byte %ld, '%c'\n",
stop-source, stop[-1]);
error("?GREP-E-Bad pattern\n");
}
/*** Scan the file for the pattern in pbuf[] ***********/
void grep(FILE *fp, char *fn)
/* FILE *fp; // File to process */
/* char *fn; // File name (for -f option) */
{
int lno, count, m;
lno = 0;
count = 0;
while (fgets(lbuf, LMAX, fp)) {
++lno;
m = match();
if ((m && !vflag) || (!m && vflag)) {
++count;
if (!cflag) {
if (fflag && fn) {
file(fn);
fn = 0;
}
if (nflag)
printf("%d\t", lno);
printf("%s\n", lbuf);
}
}
}
if (cflag) {
if (fflag && fn)
file(fn);
printf("%d\n", count);
}
}
/*** Match line (lbuf) with pattern (pbuf) return 1 if match ***/
int match()
{
char *l; /* Line pointer */
for (l = lbuf; *l; ++l) {
if (pmatch(l, pbuf))
return(1);
}
return(0);
}
/*** Match partial line with pattern *******************/
char *pmatch(char *line, char *pattern)
/* char *line; // (partial) line to match */
/* char *pattern; // (partial) pattern to match */
{
char *l; /* Current line pointer */
char *p; /* Current pattern pointer */
char c; /* Current character */
char *e; /* End for STAR and PLUS match */
int op; /* Pattern operation */
int n; /* Class counter */
char *are; /* Start of STAR match */
l = line;
if (debug > 1)
printf("pmatch(\"%s\")\n", line);
p = pattern;
while ((op = *p++) != ENDPAT) {
if (debug > 1)
printf("byte[%ld] = 0%o, '%c', op = 0%o\n",
l-line, *l, *l, op);
switch(op) {
case CHAR:
if (tolower(*l++) != *p++)
return(0);
break;
case BOL:
if (l != lbuf)
return(0);
break;
case EOL:
if (*l != '\0')
return(0);
break;
case ANY:
if (*l++ == '\0')
return(0);
break;
case DIGIT:
if ((c = *l++) < '0' || (c > '9'))
return(0);
break;
case ALPHA:
c = tolower(*l++);
if (c < 'a' || c > 'z')
return(0);
break;
case NALPHA:
c = tolower(*l++);
if (c >= 'a' && c <= 'z')
break;
else if (c < '0' || c > '9')
return(0);
break;
case PUNCT:
c = *l++;
if (c == 0 || c > ' ')
return(0);
break;
case CLASS:
case NCLASS:
c = tolower(*l++);
n = *p++ & 0377;
do {
if (*p == RANGE) {
p += 3;
n -= 2;
if (c >= p[-2] && c <= p[-1])
break;
}
else if (c == *p++)
break;
} while (--n > 1);
if ((op == CLASS) == (n <= 1))
return(0);
if (op == CLASS)
p += n - 2;
break;
case MINUS:
e = pmatch(l, p); /* Look for a match */
while (*p++ != ENDPAT); /* Skip over pattern */
if (e) /* Got a match? */
l = e; /* Yes, update string */
break; /* Always succeeds */
case PLUS: /* One or more ... */
if ((l = pmatch(l, p)) == 0)
return(0); /* Gotta have a match */
case STAR: /* Zero or more ... */
are = l; /* Remember line start */
while (*l && (e = pmatch(l, p)))
l = e; /* Get longest match */
while (*p++ != ENDPAT); /* Skip over pattern */
while (l >= are) { /* Try to match rest */
if (e = pmatch(l, p))
return(e);
--l; /* Nope, try earlier */
}
return(0); /* Nothing else worked */
default:
printf("Bad op code %d\n", op);
error("Cannot happen -- match\n");
}
}
return(l);
}
/*** Report an error ***********************************/
void error(char *s)
{
fprintf(stderr, "%s", s);
exit(1);
}
/*** Main program - parse arguments & grep *************/
int main(int argc, char **argv)
{
char *p;
int c, i;
int gotpattern;
FILE *f;
if (argc <= 1)
usage("No arguments");
if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) {
help(documentation);
help(patdoc);
return 0;
}
nfile = argc-1;
gotpattern = 0;
for (i=1; i < argc; ++i) {
p = argv[i];
if (*p == '-') {
++p;
while (c = *p++) {
switch(tolower(c)) {
case '?':
help(documentation);
break;
case 'C':
case 'c':
++cflag;
break;
case 'D':
case 'd':
++debug;
break;
case 'F':
case 'f':
++fflag;
break;
case 'n':
case 'N':
++nflag;
break;
case 'v':
case 'V':
++vflag;
break;
default:
usage("Unknown flag");
}
}
argv[i] = 0;
--nfile;
} else if (!gotpattern) {
compile(p);
argv[i] = 0;
++gotpattern;
--nfile;
}
}
if (!gotpattern)
usage("No pattern");
if (nfile == 0)
grep(stdin, 0);
else {
fflag = fflag ^ (nfile > 0);
for (i=1; i < argc; ++i) {
if (p = argv[i]) {
if ((f=fopen(p, "r")) == NULL)
cant(p);
else {
grep(f, p);
fclose(f);
}
}
}
}
return 0;
}
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/

View File

@ -1,3 +0,0 @@
File 46_grep.c:
/* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/