diff options
Diffstat (limited to 'bcc/idcc')
-rwxr-xr-x | bcc/idcc | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/bcc/idcc b/bcc/idcc new file mode 100755 index 0000000..a04afc8 --- /dev/null +++ b/bcc/idcc @@ -0,0 +1,311 @@ +#!/bin/ash +# +# This is a shell version of the bcc compiler driver. It's a little slower +# than a C version but overall seems to be a lot cleaner, perhaps a C version +# based on this might be a good idea ... +# +# The compiler works on a 'modal' basis certain flags given to it put the +# compiler into specific modes, it can only be in one mode for a run. +# +# The mode defines the basic passes and specific options that are available +# +# To define a mode see the functions 'run_0' and 'run_3' for examples. The +# variable assignments just above the definitions enable the functions. +# +# This script is specifically designed so the there is as little interaction +# between the modes as is possible. +# +# It's run using ash because this appears to be _much_ faster than bash, it's +# also reasonable with ksh. +# (On other interpreters I think perl would be too big, but awk might work...) +# + +TMPFIL="/tmp/cc$$" +trap "rm -f $TMPFIL.* ; exit 1" 1 2 3 15 +TMPCNT=0 + +FILES= +OPTS= +RESEXTN= +OPTIM=no +VERBOSE=no +MULTISRC=no + +LDOPTS= +DESTDEF=no +LDDEST=a.out +DEFMODE=0 + +ccmode= +LIBPATH="/lib:/usr/lib:/usr/bin" + +main() { + scanargs "$@" + + PATH="$LIBPATH:$PATH" + [ "$EXEC_PREFIX" != "" ] && PATH="$EXEC_PREFIX:$PATH" + + rv=0 + LDFILES= + [ "$MULTISRC" = yes -o "$RESEXTN" = "" ] && DESTDEF=no + + for FILE in $FILES + do + case "$FILE" in + *.c ) PASS=cpp ; BASE="`basename $FILE .c`" ;; + *.s ) PASS=as ; BASE="`basename $FILE .s`" ;; + * ) PASS=lnk ;; + esac + + NAME="`basename $FILE`" + DEST="`dirname $FILE`/" + [ "$DEST" = "./" ] && DEST= + DEST="$DEST$BASE.$RESEXTN" + [ "$DESTDEF" = yes ] && DEST="$LDDEST" + + STEMP=0 INTEMP=0 + [ "$PASS" = "cpp" ] && { compile $FILE || rv=$? ; } + [ "$PASS" = "as" ] && { assem $FILE || rv=$? ; } + if [ "$PASS" = "lnk" ] + then + LDFILES="$LDFILES $FILE" + else + # If there's a fail can't link - still assembling to temps tho. + [ "$RESEXTN" = "" ] && RESEXTN=O + fi + [ "$STEMP" = 1 ] && rm -f "$SFILE" + [ "$INTEMP" = 1 ] && RMFILES="$RMFILES $FILE" + done + + [ "$RESEXTN" != "" ] && exit $rv + + [ "$VERBOSE" = yes ] && + echo "$LD $SYSLIB $LDOPTS $LDFLAGS -o $LDDEST $CRT0 $LDFILES $LIBS" + + $LD $SYSLIB $LDOPTS $LDFLAGS -o $LDDEST $CRT0 $LDFILES $LIBS + rv=$? + [ "$RMFILES" != "" ] && rm -f $RMFILES + exit "$rv" +} + +scanargs() { + WILDOPT=no + + while [ "$#" -gt 0 ] + do + case "$1" in + -[DU]* ) CPPDEFS="$CPPDEFS $1" ;; + -B?* ) PATH="`echo '.$1:$PATH' | sed 's/...//'`" ;; + -I?* ) CPPFLAGS="$CPPFLAGS $1" ;; + -L?* ) LDOPTS="$LDOPTS $1" ;; + -o ) LDDEST="$2"; DESTDEF=yes ; shift ;; + -b ) . /usr/lib/idcc/opts_$2 || exit 1; shift ;; + -E ) RESEXTN=i ;; + -S ) RESEXTN=s ;; + -c ) RESEXTN=o ;; + -O ) OPTIM=yes ;; + -v ) VERBOSE=yes ;; + -l?* ) FILES="$FILES $1" ; MULTISRC=yes ;; + -* ) OPTS="$OPTS `echo .$1 | sed 's/..//'`" ;; + * ) [ "$FILES" != "" ] && MULTISRC=yes ; FILES="$FILES $1" ;; + esac + shift + done + + while [ "$OPTS" != "" -o "$DEFMODE" != "" ] + do + # So they can try again ... with DEFMODE if needed + MOPTS="$OPTS" + OPTS= + + for opt in $MOPTS + do + # Option can be defined only for specific mode so if we haven't seen + # the mode yet save the opt. If we have check for conflicts too. + [ "$ccmode" = "" -a "$DEFMODE" != "" ] && { + eval "[ \"\$opt_$opt\" = yes ]" || { OPTS="$OPTS $opt" ; opt= ; } + } + [ "$opt" != "" ] && { + [ "$ccmode" = "" ] || { + eval "[ \"\$mode_$opt\" = yes ]" && { + echo Option "-$opt incompatible with -$ccmode" 1>&2 + exit 2 + } + } + + eval "[ \"\$opt_$opt\" = yes ]" || { + { eval "[ \"$WILDOPT\" = yes ]" && wild_opt "-$opt" ; } || { + echo Option '-'$opt unknown for this mode 1>&2 + exit 3 + } + } + + eval "[ \"\$opt_$opt\" = yes ]" && run_$opt + eval "[ \"\$mode_$opt\" = yes ]" && ccmode="$opt" + } + done + [ "$ccmode" = "" -a "$DEFMODE" != "" ] && OPTS="$DEFMODE $OPTS" + DEFMODE= + done +} + +compile() { + [ -r "$FILE" ] || { echo "Cannot open $FILE" 1>&2 ; return 1 ; } + + [ "$RESEXTN" = "i" ] && { + cpp_only $FILE + return + } + + # Loop for the pass list + # The CCX variables _are_ expanded again. + + ret=1 + for pass in $PASSLIST + do + for extn in '' pre post inf res opt + do eval "CCX$extn=\"\$CC$pass$extn\"" + done + + [ "$CCX" = "" ] && continue; + [ "$OPTIM" = "" -a "$CCXopt" = yes ] && continue; + + shuffel "$RESEXTN" $CCXres + [ "$VERBOSE" = yes ] && + eval "echo \"$CCX $CCXpre $SFILE $CCXinf $FILE $CCXpost\"" + eval "$CCX $CCXpre $SFILE $CCXinf $FILE $CCXpost" || return 1 + ret=0 + done + [ "$ret" = 1 ] && { echo 'CC configuration error' 1>&2 ; return $ret ; } + + [ "$RESEXTN" != "s" ] && PASS=as + return 0 +} + +assem() { + [ -r "$FILE" ] || { echo "Cannot open $FILE" 1>&2 ; return 1 ; } + + shuffel "$RESEXTN" o + + n= + [ "$ASNAME" != "" ] && n="$ASNAME$NAME" + + [ "$VERBOSE" = yes ] && echo "$AS $ASFLAGS $n $SFILE -o $FILE" + $AS $ASFLAGS $n $SFILE -o $FILE || return + + [ "$RESEXTN" != "o" ] && PASS=lnk + return 0 +} + +if [ "2" = "$[1+1]" ] ; then inc_tmpcnt() { TMPCNT="$[$TMPCNT+1]" ; } +else inc_tmpcnt() { TMPCNT="`expr $TMPCNT + 1`" ; } +fi + +shuffel() { + [ "$STEMP" = 1 ] && rm -f "$SFILE" + + SFILE="$FILE" + STEMP="$INTEMP" + + if [ "$1" = "$2" ] + then + FILE="$DEST" + INTEMP=0 + else + inc_tmpcnt + FILE="$TMPFIL.$TMPCNT.$2" + INTEMP=1 + fi +} + +mode_0=yes opt_0=yes +run_0() +{ + SYSINC="-I/usr/bcc/include" + SYSLIB="-L/usr/bcc/lib/bcc/i86/" + LIBPATH="/usr/bcc/lib/bcc" + CRT0="-C0" + LIBS="-lc" + CGEN= + DEFS= + + CPP="cpp" + + PASSLIST=2 + CC2="bcc-cc1" CC2pre='$SYSINC $DEFS $CPPFLAGS' + CC2inf='-o' CC2post='-0 $CGEN $CPPDEFS' CC2res=s + AS="as86" ASFLAGS='-u -w -0' ASNAME='-n ' + LD="ld86" LDFLAGS='-i -0' + + opt_ansi=yes + run_ansi() + { + PASSLIST="0 1 2" + CC0="bcc-cc1" CC0pre='$SYSINC $DEFS $CPPFLAGS' CC0inf='-o' + CC0post='-0 -E -D__STDC__=0 $CPPDEFS' CC0res=i + CC1="unproto" CC1pre='' CC1inf='' CC1post='' CC1res=k + CC2="bcc-cc1" CC2pre='$CGEN' CC2inf='-o' CC2post='-0' CC2res=s + } + opt_I=yes; run_I() { SYSINC= ; } + opt_L=yes; run_L() { SYSLIB= ; } + opt_s=yes; run_s() { LDFLAGS="$LDFLAGS -s" ; } + opt_Mf=yes; run_Mf() { LIBS=-lc_f ; CGEN='-f -c' ;} + opt_Md=yes; run_Md() { LIBS=-ldos ; DEFS='-D__MSDOS__' LDFLAGS='-i -0 -d' ;} + + WILDOPT=yes + wild_opt() + { + case "$1" in + -O* ) OPTIM=yes ; OPTFLG="$OPTFLG $1" ;; + * ) return 1 ;; + # For normal CC operation unknowns go to the linker. ie: + # * ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; + esac + return 0 + } +} + +mode_3=yes opt_3=yes +run_3() +{ + SYSINC="-I/usr/bcc/include" + SYSLIB="-L/usr/bcc/lib/bcc/i386/" + LIBPATH="/usr/bcc/lib/bcc" + CRT0="-C0" + LIBS="-lc" + CGEN= + DEFS= + + CPP="cpp" + + PASSLIST=2 + CC2="bcc-cc3" CC2pre='$SYSINC $DEFS $CPPFLAGS' + CC2inf='-o' CC2post='-3 $CGEN $CPPDEFS' CC2res=s + AS="as86" ASFLAGS='-u -w -3' ASNAME='-n ' + LD="ld86" LDFLAGS='-i -3' + + opt_ansi=yes + run_ansi() + { + PASSLIST="0 1 2" + CC0="bcc-cc3" CC0pre='$SYSINC $DEFS $CPPFLAGS' CC0inf='-o' + CC0post='-3 -E -D__STDC__=0 $CPPDEFS' CC0res=i + CC1="unproto" CC1pre='' CC1inf='' CC1post='' CC1res=k + CC2="bcc-cc1" CC2pre='$CGEN' CC2inf='-o' CC2post='-3' CC2res=s + } + opt_I=yes; run_I() { SYSINC= ; } + opt_L=yes; run_L() { SYSLIB= ; } + opt_s=yes; run_s() { LDFLAGS="$LDFLAGS -s" ; } + + WILDOPT=yes + wild_opt() + { + case "$1" in + -O* ) OPTIM=yes ; OPTFLG="$OPTFLG $1" ;; + * ) return 1 ;; + esac + return 0 + } +} + +main "$@" |