diff --git a/native/clang/TSP_util.c b/native/clang/TSP_util.c index a17879f..60769bc 100755 --- a/native/clang/TSP_util.c +++ b/native/clang/TSP_util.c @@ -1,7 +1,38 @@ #ifndef _TCL #include #endif - +int TSP_debug(Tcl_Interp* interp, char const *format, ...) { + /* Helper for Debugging*/ + char __buf [4096]; + va_list aptr; + int ret; + va_start(aptr, format); + ret = vsnprintf(__buf, 4096, format, aptr); + va_end(aptr); + // compensate for surplus linebreaks, sincs puts will already write one + if(ret<0) return EOF; + if(ret>4096) ret=4096; + if(__buf[ret-1]=='\n') __buf[ret-1]=0; + Tcl_Interp* ip = interp; + if (ip==NULL) Tcl_Panic("No interp found to call tcl routine!"); + mod_Tcl_errorCode=0; + Tcl_Obj* argObjvArray [2]; + Tcl_Obj* funcname = Tcl_NewStringObj("puts",-1); + Tcl_IncrRefCount(funcname); + argObjvArray[0] = funcname; + Tcl_Obj* target_1 = Tcl_NewStringObj(__buf,-1); + Tcl_IncrRefCount(target_1); + argObjvArray[1] = target_1; + int rs = Tcl_EvalObjv(ip, 2, argObjvArray, 0); + if(funcname!=NULL) Tcl_DecrRefCount(funcname); + if(target_1 != NULL) Tcl_DecrRefCount(target_1); + if(rs !=TCL_OK) { + Tcl_Eval (ip, "puts {Error evaluating TCL-Function puts}; puts $errorInfo; flush stdout;"); + return EOF; + } + Tcl_DoOneEvent(TCL_DONT_WAIT|TCL_ALL_EVENTS); + return 1; +} /*********************************************************************************************/ /* convert to an int from a string */ @@ -224,9 +255,12 @@ TSP_Util_lang_assign_var_var(Tcl_Obj* targetVarName, Tcl_Obj* sourceVarName) { /*********************************************************************************************/ /* assign an array & element from a var */ + TSP_REMOVABLE int TSP_Util_lang_assign_array_var(Tcl_Interp* interp, Tcl_Obj* targetArrayVar, Tcl_Obj* targetIdxVar, Tcl_Obj* var) { Tcl_Obj* obj; + if (var==NULL) {return TCL_ERROR;}; + //debug(interp,"TSP_Util_lang_assign_array_var %p %p %p\n",targetArrayVar,targetIdxVar,var); obj = Tcl_ObjSetVar2(interp, targetArrayVar, targetIdxVar, var, TCL_LEAVE_ERR_MSG); if (obj == NULL) { return TCL_ERROR; diff --git a/native/clang/backup_n.tcl b/native/clang/backup_n.tcl deleted file mode 100755 index 82fed8a..0000000 --- a/native/clang/backup_n.tcl +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/tclsh -## exec tclkit -## Backup - -set t [clock format [clock seconds] -format "%Y-%m-%d_%H-%M"] -catch {console show} -file mkdir "./cvs" -foreach f0 [glob -nocomplain [file join "./" *]] { - if {[file isfile $f0]} { - set f [file tail $f0] - set n [file rootname $f] - set x [file extension $f] - set t0 [file mtime $f0] - set ts0 [clock format $t0 -format "%Y-%m-%d_%H-%M"] - #if {$f!=[file tail $::argv0]} { - set f1 "./cvs/$n.$ts0$x" - if {![file exists $f1]} { - puts "copy $f0 $f1" - file copy $f0 $f1 - } - #} - } -} diff --git a/tcc4tcl_helper.tcl b/tcc4tcl_helper.tcl index 0bdc72b..0ad38ad 100644 --- a/tcc4tcl_helper.tcl +++ b/tcc4tcl_helper.tcl @@ -1,6 +1,6 @@ package provide tcc4tcl_helper 0.1 -namespace eval tccenv { +namespace eval ::tccenv { # some common envelope vars for our ide # this tries to analyze the surrounding dirs # to find a suitable external compiler @@ -26,10 +26,29 @@ namespace eval tccenv { variable projectincludedir ${projectdir}/include variable projectlibdir ${projectdir}/lib + variable compiletime "" + variable includes_missing "" variable EXTERNAL_COMPILERS "" variable CC_DIRECTIVES "" + variable DLEXPORTMAKRO " +/***************** DLL EXPORT MAKRO FOR TCC AND GCC ************/ +#if (defined(_WIN32) && (defined(_MSC_VER)|| defined(__TINYC__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0550)) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec)))) +#undef DLLIMPORT +#undef DLLEXPORT +# define DLLIMPORT __declspec(dllimport) +# define DLLEXPORT __declspec(dllexport) +#else +# define DLLIMPORT +# if defined(__GNUC__) && __GNUC__ > 3 +# define DLLEXPORT __attribute__ ((visibility(\"default\"))) +# else +# define DLLEXPORT +# endif +#endif +/***************************************************************/ +" # the following routines try to find tcc.exe and gcc.exe under win32 and set the tccenv vars accordingly @@ -163,7 +182,7 @@ proc ::tcc4tcl::analyse_includes {handle {prefix ""}} { set prefix $::tccenv::pathprefix/ } set prefix1 ${prefix}lib/ - set prefix2 ${prefix}lib/tcc4tcl-0.30/ + set prefix2 ${prefix}lib/tcc4tcl/ foreach path $usedpath { set shortpath [string map [list $prefix ""] $path] @@ -264,7 +283,8 @@ proc ::tcc4tcl::prepare_compilerdirectives {filepath handle} { # $exeFile cc to execute # $compilertype can be gccwin32/gcclin64/tccwin32/tcclin64/user and defines prebuilt ccOptions to use; set to user to have no predefined options puts "Making Directives for $filepath ($::tccenv::tccmaindir)" - set pathway [::tcc4tcl::analyse_includes $handle] + set pathway "" + catch {set pathway [::tcc4tcl::analyse_includes $handle]} set includestccwin32 "-Iinclude -Iinclude/stdinc -Iinclude/generic -Iinclude/generic/win -Iinclude/xlib -Iwin32 -Iwin32/winapi " set includesgccwin32 "-Iinclude -Iinclude/generic -Iinclude/generic/win -Iinclude/xlib" set includestcclin64 "-Iinclude -Iinclude/stdinc -Iinclude/generic -Iinclude/generic/unix -Iinclude/xlib " @@ -272,15 +292,15 @@ proc ::tcc4tcl::prepare_compilerdirectives {filepath handle} { set includesuser "" set librariestccwin32 "-ltclstub86elf -ltkstub86elf" - set librariestcclin64 "-ltclstub86elf -ltkstub86elf" + set librariestcclin64 "-ltclstub86_64 -ltkstub86_64" set librariesgccwin32 "-Llib -ltclstub86 -ltkstub86" set librariesgcclin64 "-Llib -ltclstub86_64 -ltkstub86_64" set librariesuser "" set ccoptionstccwin32 "-m32 -D_WIN32 " set ccoptionsgccwin32 "-s -m32 -D_WIN32 -static-libgcc " - set ccoptionstcclin64 "" - set ccoptionsgcclin64 "-s -fPIC -D_GNU_SOURCE " + set ccoptionstcclin64 {-Wl,-rpath=.} + set ccoptionsgcclin64 {-s -fPIC -D_GNU_SOURCE -Wl,-rpath=. } set ccoptionstccuser "" @@ -296,8 +316,14 @@ proc ::tcc4tcl::prepare_compilerdirectives {filepath handle} { set libraries_addon "" lappend libraries_addon "-Llib" + set libps "" + set libs "" + set opts "" + catch { set libps [$handle add_library_path] set libs [$handle add_library] + set opts [$handle add_options] + } foreach inclib $libs { lappend libraries_addon "-l$inclib" } @@ -342,14 +368,64 @@ proc ::tcc4tcl::prepare_compilerdirectives {filepath handle} { set ccpath [file join $exeDir $exeFile] append ccoptions " -shared -DUSE_TCL_STUBS -O2" append ccOptions " $ccoptions" + append ccOptions " [join $opts { }]" - puts "Directive for $compiler" - puts "$ccpath $ccOptions $includes $includes_generic $cfile -o$ofile $libraries" + #puts "Directive for $compiler" + #puts "$ccpath $ccOptions $includes $includes_generic $cfile -o$ofile $libraries" lappend ccdirectives $compiler "$ccpath $ccOptions $includes $includes_generic $cfile -o$ofile $libraries" } return $ccdirectives } +proc lstride {L n} { + set t [list]; set res [list] + foreach i $L { + lappend t $i + if {[llength $t]==$n} { + lappend res $t + set t [list] + } + } + if [llength $t] {lappend res $t} ;# maybe keep the rest + set res +} + +proc ::tcc4tcl::dlexport_procdefs {procdefs proclist} { + # + ### experimental insert### + # + ########################## + # + set exportcode "" + foreach {procname cname_obj} $procdefs { + # [list $tclname $rtype $adefs] + lassign $cname_obj cname rtype adefs + if {[string range $procname 0 1]!="__"} {;#rmoeve special procs + # + set adefs [lstride $adefs 2] + set adefs [join $adefs ,] + set dlcode "DLLEXPORT $rtype $cname ($adefs);\n" + puts "$procname -> obj $cname_obj cname $cname rtype $rtype adefs $adefs" + puts $dlcode + append exportcode $dlcode + } + } + return $exportcode +} + +proc ::tcc4tcl::prepare_packagecode {handle} { + # + set DLEXPORTMAKRO $::tccenv::DLEXPORTMAKRO + upvar #0 $handle state + #modify code with dlexportmakro + set oldcode $state(code) + set newcode $DLEXPORTMAKRO + append newcode $oldcode + #append newcode [::tcc4tcl::dlexport_procdefs $state(procdefs) ""] + set state(code) $newcode + +} + proc ::tcc4tcl::write_packagecode {handle packagename {filepath ""} {packageversion 1.0} {tclversion TCL_VERSION}} { proc relTo {targetfile currentpath } { # Get relative path to target file from current path @@ -397,24 +473,7 @@ proc ::tcc4tcl::write_packagecode {handle packagename {filepath ""} {packagevers default {\n} } } - - set DLEXPORTMAKRO " -/***************** DLL EXPORT MAKRO FOR TCC AND GCC ************/ -#if (defined(_WIN32) && (defined(_MSC_VER)|| defined(__TINYC__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0550)) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec)))) -#undef DLLIMPORT -#undef DLLEXPORT -# define DLLIMPORT __declspec(dllimport) -# define DLLEXPORT __declspec(dllexport) -#else -# define DLLIMPORT __attribute__(dllimport) -# if defined(__GNUC__) && __GNUC__ > 3 -# define DLLEXPORT __attribute__ ((visibility(\"default\"))) -# else -# define DLLEXPORT -# endif -#endif -/***************************************************************/ -" + upvar #0 $handle state set oldtype "package" if {$state(type)!="package"} { @@ -423,28 +482,25 @@ proc ::tcc4tcl::write_packagecode {handle packagename {filepath ""} {packagevers set state(type) "package" } - #modify code with dlexportmakro - set oldcode $state(code) - set newcode $DLEXPORTMAKRO - append newcode $oldcode - set state(code) $newcode - + set ::tccenv::compiletime [clock format [clock seconds]] +# puts "Writing Package $packagename --> $filepath" set mycode [$handle code] + # beautify code set mycode [::tcc4tcl::reformat [string map [list [eol] \n] $mycode] 4] set $state(type) $oldtype set filename [file join $filepath "$packagename.c"] - set ccdirectives [::tcc4tcl::prepare_compilerdirectives $filename $::tsp::TCC_HANDLE] + set ccdirectives [::tcc4tcl::prepare_compilerdirectives $filename $handle] set fp [open $filename w] - puts $fp "/***************** Automatically Created with TCC4TCL Helper and maybe TSP **********************************/" + puts $fp "/***************** $::tccenv::compiletime Automatically Created with TCC4TCL Helper and maybe TSP **********************************/" puts $fp "/* Compiler directives are raw estimates, please adapt to given pathstructure */\n" foreach {compiler ccdirective} $ccdirectives { puts $fp "/* for $compiler use */" puts $fp "/* $ccdirective */\n" } - puts $fp "/***************** Automatically Created with TCC4TCL Helper and maybe TSP **********************************/" + puts $fp "/***************** $::tccenv::compiletime Automatically Created with TCC4TCL Helper and maybe TSP **********************************/" puts $fp $mycode close $fp return $ccdirectives diff --git a/tsp-clang.tcl b/tsp-clang.tcl index 752701b..9f1af37 100755 --- a/tsp-clang.tcl +++ b/tsp-clang.tcl @@ -134,6 +134,7 @@ proc ::tsp::lang_type_null {} { # declare a native boolean # proc ::tsp::lang_decl_native_boolean {varName} { + return "int $varName;\n" return "int $varName = 0;\n" } @@ -141,6 +142,7 @@ proc ::tsp::lang_decl_native_boolean {varName} { # declare a native int # proc ::tsp::lang_decl_native_int {varName} { + return "Tcl_WideInt $varName;\n" return "Tcl_WideInt $varName = 0;\n" } @@ -148,6 +150,7 @@ proc ::tsp::lang_decl_native_int {varName} { # declare a native double # proc ::tsp::lang_decl_native_double {varName} { + return "double $varName;\n" return "double $varName = 0;\n" } @@ -263,7 +266,8 @@ proc ::tsp::lang_convert_int_string {targetVarName sourceVarName errMsg} { append result "if ((*rc = TSP_Util_lang_convert_int_string(interp, $sourceVarName, &$targetVarName)) != TCL_OK) \{\n" } #FIXME: see Tcl_GetInt() but convert use Tcl_GetWideIntFromObj instead. - append result " Tcl_AppendResult(interp, [::tsp::lang_quote_string $errMsg], Tcl_GetString($sourceVarName), (char *) NULL);\n" +# append result " Tcl_AppendResult(interp, [::tsp::lang_quote_string $errMsg], Tcl_GetString($sourceVarName), (char *) NULL);\n" + append result " Tcl_AppendResult(interp, [::tsp::lang_quote_string $errMsg], $sourceVarName, (char *) NULL);\n" append result " ERROR_EXIT;\n" append result "\}\n" return $result @@ -567,13 +571,14 @@ proc ::tsp::lang_assign_empty_zero {var type} { # proc ::tsp::lang_assign_var_array_idxvar {targetObj arrVar idxVar errMsg} { append result "/* ::tsp::lang_assign_var_array_idxvar */\n" - + append result "[::tsp::lang_safe_release $targetObj]" append result "$targetObj = Tcl_ObjGetVar2(interp, $arrVar, $idxVar, TCL_LEAVE_ERR_MSG);\n" append result "if ($targetObj == NULL) \{\n" append result " /* Tcl_AppendResult(interp, [::tsp::lang_quote_string $errMsg], (char *) NULL);*/\n" append result " *rc = TCL_ERROR;\n" append result " ERROR_EXIT;\n" append result "\}\n" + append result "[::tsp::lang_preserve $targetObj]" return $result } @@ -584,15 +589,14 @@ proc ::tsp::lang_assign_var_array_idxvar {targetObj arrVar idxVar errMsg} { # proc ::tsp::lang_assign_var_array_idxtext {targetObj arrVar idxTxtVar errMsg} { append result "/* ::tsp::lang_array_get_array_idxtext */\n" - + append result "[::tsp::lang_safe_release $targetObj]" append result "$targetObj = Tcl_ObjGetVar2(interp, $arrVar, $idxTxtVar, TCL_LEAVE_ERR_MSG);\n" append result "if ($targetObj == NULL) \{\n" append result " /* Tcl_AppendResult(interp, [::tsp::lang_quote_string $errMsg], (char *) NULL);*/\n" append result " *rc = TCL_ERROR;\n" append result " ERROR_EXIT;\n" append result "\}\n" - return $result - + append result "[::tsp::lang_preserve $targetObj]" return $result } @@ -671,8 +675,7 @@ proc ::tsp::lang_assign_var_var {targetVarName sourceVarName {preserve 1}} { # which is preserved and released # proc ::tsp::lang_assign_array_var {targetArrayVar targetIdxVar var} { - append result "/* ::tsp::lang_assign_array_var */\n" - + append result "/* ::tsp::lang_assign_array_var $targetArrayVar $targetIdxVar $var */\n" append result "TSP_Util_lang_assign_array_var(interp, $targetArrayVar, $targetIdxVar, $var);\n" return $result } @@ -1161,7 +1164,7 @@ proc ::tsp::lang_create_compilable {compUnitDict code} { lassign $proc_info procType procArgTypes procRef if {$procType eq "void"} { - set procNativeType "" + set procNativeType "void" } else { set procNativeType "[::tsp::lang_xlate_native_type $procType] " } @@ -1232,10 +1235,11 @@ TSP_UserDirect_${name}(Tcl_Interp* interp, int* rc $nativeTypedArgs ) { int idx2; char* str1; char* str2; - char* exprErrMsg = NULL; + char* exprErrMsg ; + Tcl_Obj* _tmpVar_cmdResultObj = NULL; - Tcl_CallFrame* frame = NULL; + Tcl_CallFrame* frame; $returnVarDecl [::tsp::indent compUnit $argObjvArrays 1 \n] diff --git a/tsp-compile.tcl b/tsp-compile.tcl index 176272b..c254621 100755 --- a/tsp-compile.tcl +++ b/tsp-compile.tcl @@ -88,7 +88,8 @@ proc ::tsp::compile_proc {file name procargs body} { set errInf "" set rc [ catch {set compileResult [::tsp::parse_body compUnit {0 end}] } errInf] if {$rc != 0} { - error "tsp internal error: parse_body error: $errInf" + catch {puts [join [dict get $compUnit errors] \n]} + error "tsp internal error parsing $name: parse_body error: $errInf" } set returnType [dict get $compUnit returns] @@ -110,7 +111,8 @@ proc ::tsp::compile_proc {file name procargs body} { # reparse set rc [ catch {set compileResult [::tsp::parse_body compUnit {0 end}] } errInf] if {$rc != 0} { - error "tsp internal error: parse_body error: $errInf" + catch {puts [join [dict get $compUnit errors] \n]} + error "tsp internal error w parsing $name: parse_body error: $errInf" } lassign $compileResult bodyType bodyRhs code diff --git a/tsp-expr.tcl b/tsp-expr.tcl index 1f7c908..03e8626 100755 --- a/tsp-expr.tcl +++ b/tsp-expr.tcl @@ -443,6 +443,7 @@ proc ::tsp::produce_func {compUnitDict op expr tree} { } elseif {[llength $tree] == 1 && [lsearch -exact $::tsp::FUNC_1ARG $op] >= 0} { lassign [::tsp::produce_subexpr compUnit $expr [lindex $tree 0]] firstType firstOperand if {[string match string* $firstType]} { + #::tsp::lang_convert_int_string {targetVarName $firstType errMsg} error "arg type cannot be string for function: $op" } if {[::tsp::typeIsBoolean $firstType]} { @@ -587,7 +588,7 @@ proc ::tsp::produce_subexpr {compUnitDict expr tree} { set type [::tsp::getVarType compUnit $thingtext] set idx [lsearch -exact $::tsp::EXPR_TYPES $type] if {$idx == -1} { - error "variable \"$thingtext\" not type of boolean, int, double, or string: \"$type\" in expression: $nodeexpr" + error "subex variable \"$thingtext\" not type of boolean, int, double, or string: \"$type\" in expression: $nodeexpr" } # NOTE that we change the variable for native compilation by prefixing with "__" set pre [::tsp::var_prefix $thingtext] diff --git a/tsp-generate-control.tcl b/tsp-generate-control.tcl index b12edcf..0f723ca 100755 --- a/tsp-generate-control.tcl +++ b/tsp-generate-control.tcl @@ -19,14 +19,14 @@ proc ::tsp::gen_command_for {compUnitDict tree} { set rawtext [::tsp::parse_getstring compUnit [lindex $tree 1]] if {[string range $rawtext 0 0] ne "\{"} { - ::tsp::addError compUnit "start code argument not a braced word" + ::tsp::addError compUnit "start code argument not a braced word $rawtext" return [list void "" ""] } set pretext [lindex $rawtext 0] set rawtext [::tsp::parse_getstring compUnit [lindex $tree 2]] if {[string range $rawtext 0 0] ne "\{"} { - ::tsp::addError compUnit "test expr argument not a braced expression" + ::tsp::addError compUnit "test expr argument not a braced expression $rawtext" return [list void "" ""] } set exprtext [lindex $rawtext 0] @@ -112,7 +112,7 @@ proc ::tsp::gen_command_while {compUnitDict tree} { # get expr component, make sure it is braced set rawtext [::tsp::parse_getstring compUnit [lindex $tree 1]] if {[string range $rawtext 0 0] ne "\{"} { - ::tsp::addError compUnit "expr argument not a braced expression" + ::tsp::addError compUnit "expr argument not a braced expression $rawtext" return [list void "" ""] } set exprtext [lindex $rawtext 0] diff --git a/tsp-generate-math.tcl b/tsp-generate-math.tcl index 4f50a85..491acfd 100755 --- a/tsp-generate-math.tcl +++ b/tsp-generate-math.tcl @@ -16,7 +16,6 @@ proc ::tsp::gen_command_expr {compUnitDict tree} { # just get raw text from body set rawtext [::tsp::parse_getstring compUnit [lindex $tree 1]] - if { [string range $rawtext 0 0] ne "\{"} { ::tsp::addError compUnit "expr argument not a braced expression" return [list void "" ""] diff --git a/tsp-generate-set.tcl b/tsp-generate-set.tcl index 8dea751..67adbf4 100755 --- a/tsp-generate-set.tcl +++ b/tsp-generate-set.tcl @@ -67,7 +67,7 @@ proc ::tsp::gen_command_set {compUnitDict tree} { } set targetStr [parse getstring $body [lindex [lindex $tree 1] 1]] set sourceStr [parse getstring $body [lindex [lindex $tree 2] 1]] - + #puts "set $targetStr $sourceStr " # check target, should be a single text, text_array_idxtext, or text_array_idxvar set targetComponents [::tsp::parse_word compUnit [lindex $tree 1]] set firstType [lindex [lindex $targetComponents 0] 0] @@ -142,6 +142,7 @@ proc ::tsp::produce_set {compUnitDict tree targetComponents sourceComponents} { # variable parsed as an array, but some other type set errors 1 ::tsp::addError compUnit "set arg 1 \"$targetVarName\" previously defined as type: \"$targetType\", now referenced as array" + #puts "set arg 1 \"$targetVarName\" previously defined as type: \"$targetType\", now referenced as array" } # is index a string or variable? @@ -390,7 +391,7 @@ proc ::tsp::produce_set {compUnitDict tree targetComponents sourceComponents} { # generate assignment # mostly same as a scalar from scalar assignment set sourceVarName $sourceRhsVar - append result "\n/***** ::tsp::generate_set assign from command */\n" + append result "\n/***** ::tsp::generate_set assign from command (set $targetVarName = $sourceVarName) */\n" append code $sourceCode set targetType [::tsp::gen_check_target_var compUnit $targetVarName $targetType $sourceType] if {$targetType eq "ERROR"} { @@ -637,10 +638,29 @@ proc ::tsp::gen_assign_var_string_interpolated_string {compUnitDict targetVarNam # puts "gen_assign_var_string_interpolated_string- ::tsp::setDirty compUnit $targetVarName" ::tsp::setDirty compUnit $targetVarName - set targetPre [::tsp::var_prefix $targetVarName] - - append result "\n/***** ::tsp::gen_assign_var_string_interpolated_string */\n" + set recursiveSet "" + set oldTarget $targetVarName + + foreach component $sourceComponents { + # preanalyse, if recursive set occurs + set compType [lindex $component 0] + set sourceVarName [lindex $component 1] + if {$sourceVarName==$targetVarName} { + if {$compType=="scalar"} { + append code "// DEBUG: recursive set $sourceVarName \n" + set recursiveSet [::tsp::get_tmpvar compUnit string] + set targetVarName $recursiveSet + append code [::tsp::lang_assign_empty_zero $recursiveSet string] + } else { + ::tsp::addError compUnit "recursive assignment to \"$targetVarName\"" + return ERROR + } + } + } + set targetPre [::tsp::var_prefix $targetVarName] + append result "\n/***** ::tsp::gen_assign_var_string_interpolated_string targetType $targetType */\n" + set tmp [::tsp::get_tmpvar compUnit string] set tmp2 "" set arrVar "" @@ -648,6 +668,14 @@ proc ::tsp::gen_assign_var_string_interpolated_string {compUnitDict targetVarNam set tmp2 [::tsp::get_tmpvar compUnit string] append result [::tsp::lang_assign_empty_zero $tmp2 string] } + # fix: why is this not reset? + if {$targetType eq "string"} { + if {$targetPre!=""} { + append result [::tsp::lang_assign_empty_zero $targetPre$targetVarName string] + #append result "/* DEBUG Tcl_DStringSetLength($targetPre$targetVarName,0);*/\n" + } + } + foreach component $sourceComponents { set compType [lindex $component 0] switch $compType { @@ -660,6 +688,10 @@ proc ::tsp::gen_assign_var_string_interpolated_string {compUnitDict targetVarNam scalar { # assignment from native variable or var, possible type coersion set sourceVarName [lindex $component 1] + if {$sourceVarName==$targetVarName} { + # create another tempvar + append code "// DEBUG: sourceVarName=targetVarName=$targetVarName \n" + } set sourceType [::tsp::getVarType compUnit $sourceVarName] if {$sourceType eq "undefined"} { ::tsp::addError compUnit "set command arg 2 interpolated string variable not defined: \"$sourceVarName\"" @@ -671,29 +703,137 @@ proc ::tsp::gen_assign_var_string_interpolated_string {compUnitDict targetVarNam set sourceCmdRange [lindex $component 2] lassign [::tsp::parse_nestedbody compUnit $sourceCmdRange] sourceType sourceRhsVar sourceCode - if {$sourceCode eq ""} { - ::tsp::addError compUnit "assignment from nested command: no code generated: target \"$targetVarName\" " - return [list void "" ""] + if {$sourceCode eq ""} { + ::tsp::addError compUnit "assignment from nested command: no code generated: target \"$targetVarName\" " + return [list void "" ""] + } + + if {$sourceType eq "void"} { + ::tsp::addError compUnit "void assignment from nested command: target \"$targetVarName\"" + return [list void "" ""] } - - if {$sourceType eq "void"} { - ::tsp::addError compUnit "void assignment from nested command: target \"$targetVarName\"" - return [list void "" ""] - } append code $sourceCode append code [::tsp::gen_assign_scalar_scalar compUnit $tmp string $sourceRhsVar $sourceType ] } + text_array_idxvar - array_idxvar { + append code "//Parsing Array $compType in $component of $sourceComponents\n" + puts "//Parsing Array $compType in $component of $sourceComponents\n" + #::tsp::addWarning compUnit "$compType not implemented $component $sourceComponents" + #append code "//Parsing $component in $sourceComponents\n" + set tmp_s [::tsp::get_tmpvar compUnit string] + set doreturn 0 + + # assignment from native variable or var, possible type coersion + set sourceVarName [lindex $component 2] + set sourceType [::tsp::getVarType compUnit $sourceVarName] + #append code "// assignment |$sourceVarName|$sourceType| to $tmp_s\n" + if {$sourceType eq "undefined"} { + ::tsp::addError compUnit "set command arg 2 interpolated string variable not defined: \"$sourceVarName\"" + return [list ""] + } + append code [::tsp::gen_assign_scalar_scalar compUnit $tmp_s string $sourceVarName $sourceType] + + if {($compType=="array_idxvar")} { + #::tsp::addWarning compUnit "set arg 2 interpolated string cannot contain $compType as $component in $sourceComponents, only commands, text, backslash, or scalar variables" + set tmp_a [::tsp::get_tmpvar compUnit var tmp_array] + set tmp_v [::tsp::get_tmpvar compUnit var tmp_idx] + append code [::tsp::lang_assign_var_string $tmp_v $tmp_s] + #append code "// Convert array |$tmp_a| to $tmp\n" + append code [::tsp::lang_assign_var_array_idxvar $tmp_a [::tsp::get_constvar [::tsp::getConstant compUnit [lindex $component 1]]] $tmp_v "Error loading Array Text"] + append code "//DEBUG1: lang_convert_string_var after array \n" + append code [::tsp::lang_convert_string_var $tmp $tmp_a] + } else { + set sourceText [lindex $sourceComponents 3] + if {$sourceText eq ""} { + append code "//Missing source in $sourceComponents\n" + continue + } else { + error "DEBUG here, this is an unknown testcase??? 2025-04-18" + #::tsp::addWarning compUnit "set arg 2 interpolated string should not contain $compType as $sourceText in $sourceComponents, only commands, text, backslash, or scalar variables\n" + set newsource "[lindex $sourceComponents 1](" + #append code "// Convert |$newsource| to $tmp via $tmp_s\n" + append code [::tsp::lang_assign_string_const $tmp $newsource] + append code [::tsp::lang_append_string $tmp $tmp_s] + append code [::tsp::lang_append_string $tmp "\")\""] + append code "// DEBUG Tcl_DStringAppend($tmp,\")\",-1);\n//DEBUG Appended additional braces\n" + set doreturn 1 + } + } + if {$targetType eq "string"} { + append code "// Append string 727 dropped |$tmp|\n" + #append code [::tsp::lang_append_string $targetPre$targetVarName $tmp] + } elseif {$targetType eq "var"} { + append code "// Append var 740 dropped |$tmp|\n" + #append code [::tsp::lang_assign_var_string $targetVarName $tmp] + } + #append code [::tsp::lang_assign_empty_zero $tmp string] + if {$doreturn>0} { + #append code "// exiting\n" + return $code + } + } + text_array_idxtext - array_idxtext { + append code "//Parsing Array $compType in $component of $sourceComponents\n" + set tmp_s [::tsp::get_tmpvar compUnit string] + set sourceVarName [lindex $component 1] + set sourceType [::tsp::getVarType compUnit $sourceVarName] + #append code "// assignment |$sourceVarName|$sourceType| to $tmp_s\n" + if {($sourceVarName ne "") && ($sourceType ne "array")} { + ::tsp::addError compUnit "set command argument not defined as array but as $sourceType: \"$sourceVarName\"" + return [list ""] + } + set doreturn 0 + if {($compType=="array_idxtext")} { + #::tsp::addWarning compUnit "set arg 2 interpolated string cannot contain $compType as $component in $sourceComponents, only commands, text, backslash, or scalar variables" + set tmp_a [::tsp::get_tmpvar compUnit var tmp_array] + #append code "// Convert array |$tmp_a| to $tmp\n" + append code [::tsp::lang_assign_var_array_idxvar $tmp_a [::tsp::get_constvar [::tsp::getConstant compUnit [lindex $component 1]]] [::tsp::get_constvar [::tsp::getConstant compUnit [lindex $component 2]]] "Error loading Array Text"] + append code [::tsp::lang_convert_string_var $tmp $tmp_a] + } else { + set sourceText [lindex $sourceComponents 3] + if {$sourceText eq ""} { + append code "//Missing source in $sourceComponents\n" + continue + } else { + #::tsp::addWarning compUnit "set arg 2 interpolated string should not contain $compType as $sourceText in $sourceComponents, only commands, text, backslash, or scalar variables\n" + #append code "// Convert |$sourceText| to $tmp\n" + append code [::tsp::lang_assign_string_const $tmp $sourceText] + set doreturn 1 + } + } + if {$targetType eq "string"} { + #append code "// Append string 763 |$tmp|\n" + ##???append code [::tsp::lang_append_string $targetPre$targetVarName $tmp] + ### deleted this output 23-Oct 20, since it produced continuosly double output with + ### Line 781 string case + #append code "// ok;\n" + } elseif {$targetType eq "var"} { + append code "// Append var 778 |$tmp|\n" + append code [::tsp::lang_assign_var_string $targetVarName $tmp] + } + #append code [::tsp::lang_assign_empty_zero $tmp string] + if {$doreturn>0} { + append code "// exiting\n" + return $code + } + } default { ::tsp::addError compUnit "set arg 2 interpolated string cannot contain $compType, only commands, text, backslash, or scalar variables" return "" } } if {$targetType eq "string"} { + append code "// Append string 781 |$tmp|\n" append code [::tsp::lang_append_string $targetPre$targetVarName $tmp] } elseif {$targetType eq "var"} { append code [::tsp::lang_append_string $tmp2 $tmp] } } + if {$recursiveSet!=""} { + append code "// DEBUG: had recursive set\n" + append code [::tsp::lang_convert_string_string [::tsp::var_prefix $oldTarget]$oldTarget $targetPre$targetVarName] + set targetVarName $oldTarget + } if {$targetType eq "var"} { append code [::tsp::gen_assign_scalar_scalar compUnit $targetVarName var $tmp2 string] } @@ -763,6 +903,7 @@ proc ::tsp::gen_assign_array_scalar {compUnitDict targetVarName targetArrayIdxte append code [::tsp::lang_assign_var_$sourceType $value $pre$sourceVarName] } else { # it's a native var, use a shadow var + ::tsp::setDirty compUnit $sourceVarName lassign [::tsp::getCleanShadowVar compUnit $sourceVarName] value shadowCode append code $shadowCode } diff --git a/tsp-generate.tcl b/tsp-generate.tcl index 1f05b87..311fbea 100755 --- a/tsp-generate.tcl +++ b/tsp-generate.tcl @@ -800,22 +800,33 @@ proc ::tsp::mkComment {text {len 40} {rawOnly 0}} { # get a clean shadow var for a native variable # generates code to set the shadow var if native variable is currently dirty # returns list of {var code} +# BUG FIXME This does not really work, if the shadow var gets set clean in a different code-path! +# HACK At least inserted a test if shadowVar is NULL +# to avoid crashing fron NULL Pointer Deref proc ::tsp::getCleanShadowVar {compUnitDict nativeVar} { upvar $compUnitDict compUnit set shadowVar [::tsp::get_tmpvar compUnit var $nativeVar] + set argVarComponents [list [list text $shadowVar $shadowVar]] + set sourceComponents [list [list scalar $nativeVar]] + set setTree "" if {[lsearch [::tsp::getCleanList compUnit] $nativeVar] == -1} { # var is not clean or not present, generate an assignment - set argVarComponents [list [list text $shadowVar $shadowVar]] - set sourceComponents [list [list scalar $nativeVar]] - set setTree "" set result "\n/* set shadow variable $nativeVar */" append result [lindex [::tsp::produce_set compUnit $setTree $argVarComponents $sourceComponents] 2] # mark the native variable clean - ::tsp::setDirty compUnit $nativeVar 0 +# BUG FIXME This does not really work, if the shadow var gets set clean in a different code-path! +# REMOVED, since it broke in case of multiple loops +# heapsort failed dramatically + # ::tsp::setDirty compUnit $nativeVar 0 } else { # var is clean no need to re-assign set result "/* shadow variable $nativeVar marked as clean */\n" + # prevent, that it's null + append result "if($shadowVar==NULL) {\n" + append result [lindex [::tsp::produce_set compUnit $setTree $argVarComponents $sourceComponents] 2] + append result "}\n" + } return [list $shadowVar $result] diff --git a/tsp-packagehelper.tcl b/tsp-packagehelper.tcl index 1d207cf..f9298e3 100755 --- a/tsp-packagehelper.tcl +++ b/tsp-packagehelper.tcl @@ -7,7 +7,7 @@ # PACKAGENAME_tsp_YYYY-MM-DD-hh-mm-ss.tcl (with tsp directives to create package) # pkgIndex.tcl # PACKAGENAME.puretcl.tcl (Untouched, pure TCL procs) -# PACKAGENAME.tclorig.tcl (TCL Replacment procs) +# PACKAGENAME.tclprocs.tcl (TCL Replacment procs) # PACKAGENAME.c (sourcecode, final) # PACKAGENAME.dll (binary file) # @@ -16,19 +16,24 @@ package require tcc4tcl source [file join [file dirname [info script]] tcc4tcl_helper.tcl] - namespace eval ::tsp { - # added for code package making MiR + # added for code package making MiR, also defined and used in tsp.tcl variable COMPILE_PACKAGE 0 variable PACKAGE_NAMESPACE "" - variable NAMESPACE_VARS "" variable PACKAGE_HEADER "" - variable TCC_HANDLE variable PACKAGE_PROCS "" + variable NAMESPACE_VARS "" + variable TCC_HANDLE + variable TSP_VERSION "-unknown-" + + # these variables are NOT to be used elsewhere in tsp variable PACKAGE_NAME "" variable PACKAGE_VERSION "1.0" variable PACKAGE_DIR "" + variable writepkg 1 ;# controls if any code is written out + variable TEST_PROC "" + #variable TSPPACKAGE_SPACE [file normalize [file dirname [info script]]] variable TCL_VERSION "TCL_VERSION" variable TCL_PROCS "" # load tcls for additional sources @@ -41,21 +46,40 @@ namespace eval ::tsp { # give name of save tcl source here, otherwise we use __lastsaved__.tcl variable ACTSOURCE "" + + variable _HOOK_LEVEL 0 } -proc ::tsp::hook_proc {} { +proc ::tsp::hook_proc {level} { # we hook the proc construct to get information about package defined procs + variable _HOOK_LEVEL + set _HOOK_LEVEL $level + #puts "Hooking proc $level" if {[info command ::__proc] eq ""} { rename ::proc ::__proc ::__proc ::proc {procName procargs procbody} { - lappend ::tsp::TCL_PROCS [list $procName $procargs $procbody] - if {[catch {uplevel 0 ::__proc [list $procName $procargs $procbody]} err]} { + #puts "Hook hit $procName in -[info script]- lv [info level]==$::tsp::_HOOK_LEVEL ?" + set nsprocname $procName + if {(([info script] eq "")||([info script] eq $::tsp::ACTSOURCE))&&([info level]==$::tsp::_HOOK_LEVEL)} { + #puts "lappend ::tsp::TCL_PROCS [list $procName $procargs $procbody]" + if {$::tsp::PACKAGE_NAMESPACE ne ""} { + set nsprocname ::${::tsp::PACKAGE_NAMESPACE}::$procName + puts "Namespace rewriting $procName to $nsprocname" + # check if namespace exists or create it + if {[namespace exists ::${::tsp::PACKAGE_NAMESPACE}]==0} { + namespace eval ::${::tsp::PACKAGE_NAMESPACE} {} + } + } + lappend ::tsp::TCL_PROCS [list $nsprocname $procargs $procbody] + } + if {[catch {uplevel 0 ::__proc [list $nsprocname $procargs $procbody]} err]} { rename ::proc "" rename ::__proc ::proc return -code error "Error in proc $err" } } } + } proc ::tsp::unhook_proc {} { @@ -75,9 +99,15 @@ proc ::tsp::init_package {packagename {packagenamespace ""} {packageversion 1.0} } set ::tsp::COMPILE_PACKAGE 1 set ::tsp::PACKAGE_NAME $packagename - set ::tsp::PACKAGE_NAMESPACE $packagenamespace + set ::tsp::PACKAGE_NAMESPACE [string trim $packagenamespace :]; # remove prepending/trailing :: set ::tsp::PACKAGE_VERSION $packageversion set ::tsp::TCL_VERSION $tclversion + + #which version of tsp did create the source? + if {$::tsp::TSP_VERSION eq "-unknown-"} { + # try taking it from application + catch {set ::tsp::TSP_VERSION $::_version} + } # reset system in case set ::tsp::COMPILER_LOG [dict create] set ::tsp::COMPILED_PROCS [dict create] @@ -87,20 +117,19 @@ proc ::tsp::init_package {packagename {packagenamespace ""} {packageversion 1.0} catch { unset ::tsp::TCC_HANDLE} set ::tsp::TCC_HANDLE [tcc4tcl::new] - set ::tsp::PACKAGE_PROCS "" + set ::tsp::NAMESPACE_VARS "" set ::tsp::PACKAGE_INIT_PROC 0 set ::tsp::TCL_PROCS "" - set ::tsp::PACKAGE_HEADER \ - { -/* START OF PACKAGE_HEADER */ + set ::tsp::PACKAGE_HEADER " +/* START OF PACKAGE_HEADER TSP (Version $::tsp::TSP_VERSION) */ /* don't forget to declare includedir tsp-package/native/clang/ in the right way */ #include #include -#include "TSP_cmd.c" -#include "TSP_func.c" -#include "TSP_util.c" +#include \"TSP_cmd.c\" +#include \"TSP_func.c\" +#include \"TSP_util.c\" /* END OF PACKAGE_HEADER */ - } + " $::tsp::TCC_HANDLE add_include_path "$::tsp::HOME_DIR/native/clang/" $::tsp::TCC_HANDLE add_include_path $packagename @@ -112,9 +141,11 @@ proc ::tsp::init_package {packagename {packagenamespace ""} {packageversion 1.0} set ::tsp::LOAD_DLLS "" set ::tsp::EXTERNAL_DLLS "" - ::tsp::hook_proc + ::tsp::hook_proc [info level] +} +proc ::tsp::package_export {exportprocnames} { + # } - proc ::tsp::finalize_package {{packagedir ""} {compiler none}} { ::tsp::unhook_proc @@ -127,12 +158,13 @@ proc ::tsp::finalize_package {{packagedir ""} {compiler none}} { return } - set tsp::PACKAGE_DIR $packagedir - if {![file isdir $tsp::PACKAGE_DIR]} { - file mkdir $tsp::PACKAGE_DIR + set ::tsp::PACKAGE_DIR $packagedir + if {![file isdir $::tsp::PACKAGE_DIR]} { + file mkdir $::tsp::PACKAGE_DIR } ::tsp::rewrite_procnamespace + ::tcc4tcl::prepare_packagecode $::tsp::TCC_HANDLE if {$compiler eq ""} { set compiler "intern" @@ -142,36 +174,87 @@ proc ::tsp::finalize_package {{packagedir ""} {compiler none}} { set ::tsp::COMPILE_DIRECTIVES "" puts "failed crafting compiledirectives... use package require tcc4tcc-helper" } else { - set ::tsp::COMPILE_DIRECTIVES [::tcc4tcl::write_packagecode $::tsp::TCC_HANDLE $::tsp::PACKAGE_NAME $tsp::PACKAGE_DIR $::tsp::PACKAGE_VERSION $::tsp::TCL_VERSION] + set ::tsp::COMPILE_DIRECTIVES [::tcc4tcl::write_packagecode $::tsp::TCC_HANDLE $::tsp::PACKAGE_NAME $::tsp::PACKAGE_DIR $::tsp::PACKAGE_VERSION $::tsp::TCL_VERSION] } - } - - ::tsp::write_pkgAltTcl $::tsp::PACKAGE_NAME - ::tsp::write_pkgIndex $::tsp::PACKAGE_NAME + } + # add a little help function + if {$::tsp::PACKAGE_NAMESPACE eq ""} { + set help_proc ::${::tsp::PACKAGE_NAME}_help + } else { + set help_proc ::${::tsp::PACKAGE_NAMESPACE}::help + } + # add help-index + set help_body " puts {\n" + append help_body [::tsp::getProcIndex $::tsp::PACKAGE_NAME] + append help_body "\n}\n" + set help_procdef [list $help_proc "" $help_body] + set cmd "::$help_proc {} $help_body" + ::proc ::$help_proc {} $help_body + lappend ::tsp::TCL_PROCS $help_procdef + if {$::tsp::writepkg>0} { + puts "writing pkg $::tsp::PACKAGE_NAME from -$::tsp::ACTSOURCE-" + ::tsp::write_pkgAltTcl $::tsp::PACKAGE_NAME + ::tsp::write_pkgIndex $::tsp::PACKAGE_NAME + } # if a source file is given # copy source to packagedir... if already in place, rename if {($::tsp::ACTSOURCE ne "")&&[file exist $::tsp::ACTSOURCE]} { set t [clock format [clock seconds] -format "%Y-%m-%d_%H-%M-%S"] set srcname "${::tsp::PACKAGE_NAME}_tsp_${t}.tcl" - set srcname [file join $tsp::PACKAGE_DIR $srcname] + set srcname [file join $::tsp::PACKAGE_DIR $srcname] set vdiff 1 catch { - set lastsrcname [file join $tsp::PACKAGE_DIR "${::tsp::PACKAGE_NAME}_tsp_*.tcl"] + set lastsrcname [file join $::tsp::PACKAGE_DIR "${::tsp::PACKAGE_NAME}_tsp_*.tcl"] set lastsrcname [lindex [lsort -decreasing [glob $lastsrcname]] 0] set vdiff [version:filediff $::tsp::ACTSOURCE $lastsrcname] } if {$vdiff >0} { - puts "Copy src to $srcname" + puts "Copy src $::tsp::ACTSOURCE to $srcname" file copy "$::tsp::ACTSOURCE" "$srcname" } } ::tsp::compile_package $::tsp::PACKAGE_NAME $compiler + + # pkginit? + if {$::tsp::PACKAGE_INIT_PROC>0} { + if {$compiler in "intern memory"} { + if {[catch {${::tsp::PACKAGE_NAME}_pkgInit} e]} { + puts "error ${::tsp::PACKAGE_NAME}_pkgInit: $e" + } + } + } set ::tsp::COMPILE_PACKAGE 0 set ::tsp::PACKAGE_NAME "" + +} + +proc ::tsp::tclwrap {name {adefs {}} {rtype void} {cname ""}} { + # this is a trampoline for tcc4tcls tclwrap routine adding the namespace + if {[namespace exists ::${::tsp::PACKAGE_NAMESPACE}]>0} { + # prepend package_namespace to name + # first clean up the nampespace_identifeier + set vname "::${::tsp::PACKAGE_NAMESPACE}::${name}" + if {[info command $vname]==$vname} { + set name $vname + } + } + $::tsp::TCC_HANDLE tclwrap $name $adefs $rtype $cname +} +proc ::tsp::tclwrap_eval {name {adefs {}} {rtype void} {cname ""}} { + # this is a trampoline for tcc4tcls tclwrap routine adding the namespace + if {[namespace exists ::${::tsp::PACKAGE_NAMESPACE}]>0} { + # prepend package_namespace to name + set vname "::${::tsp::PACKAGE_NAMESPACE}::${name}" + if {[info command $vname]==$vname} { + set name $vname + } + } + $::tsp::TCC_HANDLE tclwrap_eval $name $adefs $rtype $cname } + proc ::tsp::addExternalCompiler {compiler ccOptions exeDir exeFile {compilertype gccwin32}} { # add external compiler to list EXTERNAL_COMPILERS # $compiler: compilername cc @@ -188,6 +271,7 @@ proc ::tsp::safeEval {cmd} { set r [namespace eval :: "$cmd"] puts "Result: $r" } err]} { + interp delete sl ::tsp::unhook_proc puts "Eval Error: $err" } @@ -206,69 +290,101 @@ proc ::tsp::add_dllinclude {fname} { lappend ::tsp::EXTERNAL_DLLS $fname } -proc ::tsp::test_packageX {packagename {callcmd ""} {shell "./tclkit_866_3.upx.exe"}} { - # ok, now things really get difficult, if the directory structure doesn't work +proc ::tsp::test_packageX {packagename {callcmd ""} {shell "tclkit_8.6.12.exe"}} { + # ok, now things really get difficult, if the directory structure doesn't work "./tclkit_866_3.upx.exe" # this actually only works under windows, you need a tclkit named $shell in the current working dir - set result "failed testloading package $packagename" + set result "failed testloading package $packagename in [pwd]" set callresult "" - puts "Testing package $packagename" + set packagedir [file dir $packagename] + set packagename [file tail $packagename] + puts "Testing package $packagename in [pwd]" if {[catch { puts "Creating new exec" - set fd [open resrc.tcl w] - puts "appending auto_path with [file dir $tsp::PACKAGE_DIR]" + set res_name [file normalize resrc.tcl] + set fd [open $res_name w] + fconfigure $fd -translation lf + puts $fd "#!/usr/bin/tclsh" puts $fd "catch {console show}" - puts $fd "lappend auto_path [file dir $tsp::PACKAGE_DIR]" - puts "Loading package... $packagename" + puts ">>> appending auto_path with [file normalize [file dir $::tsp::PACKAGE_DIR]]" + puts $fd "lappend auto_path ." + puts $fd "lappend auto_path [file normalize [file dir $::tsp::PACKAGE_DIR]]" + #puts "Testing for [file dir $::tsp::PACKAGE_DIR] ne $packagedir" + if {[file dir $::tsp::PACKAGE_DIR] ne $packagedir} { + puts ">>> appending auto_path with $packagedir" + puts $fd "lappend auto_path $packagedir" + } + #puts "Appending $::tsp::TSPPACKAGE_SPACE" + #puts $fd "lappend auto_path $::tsp::TSPPACKAGE_SPACE" + puts ">>> Load package... $packagename" puts $fd "package require $packagename" if {$callcmd ne ""} { - puts "Calling $callcmd" + puts ">>> Call $callcmd" puts $fd $callcmd } } err]} { puts "Error while preparing package $packagename\n$err" } close $fd - puts "Go" + puts ">>> Go" # shell actually hardcoded... todo implement some clever routine to find nearest kit - - if {[catch { - if {![file exists $shell]} { - puts "Shell not found $shell... searching" - # mark your shells as tclkit-8.6.6.exe to get found 866 8-6-6 all will do - # this will search for 8.6.6 shell - # or at least any 8.6 shell - set flist [glob tclkit*.exe] - set cand "" - foreach kit $flist { - set vnum [join [regexp -all -inline "\[0-9\]" $kit]] - set vstring2 [join [lrange $vnum 0 1] "."] - set vstring3 [join [lrange $vnum 0 2] "."] - if {$vstring2 eq "8.6"} { - lappend cand $kit $vstring3 + # and to run under linux + if {$::tcl_platform(platform)=="unix"} { + puts "Seems to be a native linux, calling tclsh $res_name" + #exec >@stdout tclsh resrc.tcl + # solution: + set runcmd "exec tclsh \"$res_name\" 2>@stderr" + #" + puts "running $runcmd" + if {[catch $runcmd res]} { + error "Failed to run command $runcmd: $res" + } + + puts $res + } else { + if {[catch { + if {![file exists $shell]} { + puts "Shell not found $shell... searching" + # mark your shells as tclkit-8.6.6.exe to get found 866 8-6-6 all will do + # this will search for 8.6.6 shell + # or at least any 8.6 shell + set flist [glob -nocomplain tclkit*.exe] + if {[llength $flist]==0} { + puts "Shell not found in ./ ... searching $::tccenv::tclexedir" + set flist [glob -nocomplain [file join $::tccenv::tclexedir tclkit*.exe]] + puts $flist } - if {$vstring3 eq "8.6.6"} { - # found an 866, use it - set shell $kit - puts "found $shell" - break; + set cand "" + foreach kit $flist { + set vnum [join [regexp -all -inline "\[0-9\]" [file tail $kit]]] + set vstring2 [join [lrange $vnum 0 1] "."] + set vstring3 [join [lrange $vnum 0 2] "."] + if {$vstring2 eq "8.6"} { + lappend cand $kit $vstring3 + } + if {$vstring3 eq "8.6.6"} { + # found an 866, use it + set shell $kit + puts "found $shell" + break; + } } + if {[llength $cand]==0} { + puts "Error: Shell not found" + return + } + set cand [lsort -decreasing -stride 2 $cand] + puts "Candidates $cand" + set shell [lindex $cand 0] + puts "using $shell" + } - if {[llength $cand]==0} { - puts "Error: Shell not found" - return - } - set cand [lsort -decreasing -stride 2 $cand] - puts "Candidates $cand" - set shell [lindex $cand 0] - puts "using $shell" - - } - exec $shell resrc.tcl & - } err]} { - puts "Error while preparing package $packagename\n$err" + exec $shell $res_name & + } err]} { + puts "Error while preparing package $packagename\n$err" } + } return } @@ -281,8 +397,8 @@ proc ::tsp::test_package {packagename {callcmd ""}} { if {[catch { puts "Creating new interp" set ip [interp create] - puts "appending auto_path with [file dir $tsp::PACKAGE_DIR]" - $ip eval lappend auto_path [file dir $tsp::PACKAGE_DIR] + puts "appending auto_path with [file dir $::tsp::PACKAGE_DIR]" + $ip eval lappend auto_path [file dir $::tsp::PACKAGE_DIR] puts "Loading package... $packagename" set result [$ip eval package require $packagename] if {$callcmd ne ""} { @@ -314,9 +430,9 @@ proc ::tsp::test_altpackage {packagename {callcmd ""}} { puts "Creating new interp" set ip [interp create] puts "Loading TCL package... $packagename.tclprocs.tcl" - set result [$ip eval source [file join $tsp::PACKAGE_DIR "${packagename}.tclprocs.tcl"]] + set result [$ip eval source [file join $::tsp::PACKAGE_DIR "${packagename}.tclprocs.tcl"]] puts "Loading TCL package... $packagename.puretcl.tcl" - set result [$ip eval source [file join $tsp::PACKAGE_DIR "${packagename}.puretcl.tcl"]] + set result [$ip eval source [file join $::tsp::PACKAGE_DIR "${packagename}.puretcl.tcl"]] if {$callcmd ne ""} { puts "Calling $callcmd" catch { @@ -353,13 +469,21 @@ proc ::tsp::rewrite_procnamespace {} { foreach {procname cprocname} $state(procs) { if {[lsearch $::tsp::PACKAGE_PROCS [namespace tail $procname]]<0} { # pure c implemented... there will be no valid TCL representation - set procdef [list $procname "args" [list puts "Not implemented \"$procname\""]] - lappend ::tsp::PACKAGE_PROCS $procname $procdef - set cdef [dict get $state(procdefs) $procname] - lassign $cdef cprocname rtype cprocargs - set procargs "" - foreach {ctype vname} $cprocargs { - lappend procargs $ctype + ##set procdef [list $procname "args" [list puts "Not implemented \"$procname\""]] + ##lappend ::tsp::PACKAGE_PROCS $procname $procdef + catch { + set cdef [dict get $state(procdefs) $procname] + lassign $cdef cprocname rtype cprocargs + set procargs "" + set procargsfull "" + foreach {ctype vname} $cprocargs { + lappend procargs $ctype + if {$vname!= "interp"} { + lappend procargsfull $vname + } + } + set procdef [list $procname "$procargsfull" [list puts "Not implemented \"$procname\""]] + lappend ::tsp::PACKAGE_PROCS $procname $procdef } #lappend ::tsp::COMPILED_PROCS $procname [list $rtype $procargs $cprocname] } @@ -379,34 +503,71 @@ proc ::tsp::rewrite_procnamespace {} { set state(procs) $nsprocs } -proc ::tsp::write_pkgIndex {packagename} { - # write a pkindex.tcl file to load package - if {$tsp::PACKAGE_DIR eq ""} { - set filename [file join $tsp::PACKAGE_DIR "$packagename.pkgIndex.tcl"] - } else { - set filename [file join $tsp::PACKAGE_DIR "pkgIndex.tcl"] - } - set fd [open $filename w] - puts $fd "# Package Index for $packagename generated by TSP//TCCIDE Version $::_version" - puts $fd "# Compiled Procs " - puts $fd "" +proc ::tsp::getProcIndex {packagename} { + # + set helpindex "" + lappend helpindex "# Help Index:" + lappend helpindex "# Generated at [set t [clock format [clock seconds] -format "%Y-%m-%d_%H-%M-%S"]]" + lappend helpindex "# Package Index/Loader for $packagename generated by TSP//TCCIDE Version $::_version" + lappend helpindex "" + lappend helpindex "# Compiled Procs " + lappend helpindex "" set cpr {} catch {set cpr $::tsp::PACKAGE_PROCS} foreach {procname procdef} $cpr { - lassign $procdef cproc cvars cbody - puts $fd "# ${::tsp::PACKAGE_NAMESPACE}::$cproc $cvars" + if {[string range $procname 0 1]!="__"} { + lassign $procdef cproc cvars cbody + lappend helpindex "# ${::tsp::PACKAGE_NAMESPACE}::$cproc $cvars" + } + if {$procname eq "${packagename}_pkgInit"} { + set ::tsp::PACKAGE_INIT_PROC 1 + puts "Init via $procname" + } } - puts $fd "\n# TCL Procs " - puts $fd "" + + lappend helpindex "" + lappend helpindex "# TCL Procs " + lappend helpindex "" set tclpr {} catch {set tclpr $::tsp::TCL_PROCS} foreach tcldef $tclpr { lassign $tcldef cproc cvars cbody - puts $fd "# $cproc $cvars" + lappend helpindex [string map {\n "."} "# $cproc $cvars"] + if {$cproc eq "${packagename}_pkgInit"} { + set ::tsp::PACKAGE_INIT_PROC 1 + puts "Init via $cproc" + } + } + return [join $helpindex \n] +} + +proc ::tsp::write_pkgIndex {packagename} { + # write a pkgindex.tcl file to load package + if {$::tsp::PACKAGE_DIR eq ""} { + set filename [file join $::tsp::PACKAGE_DIR "$packagename.pkgIndex.tcl"] + set loadername [file join $::tsp::PACKAGE_DIR "$packagename.${packagename}.loader.tcl"] + } else { + set filename [file join $::tsp::PACKAGE_DIR "pkgIndex.tcl"] + set loadername [file join $::tsp::PACKAGE_DIR "${packagename}.loader.tcl"] } + + set fd [open $loadername w] + + puts $fd [::tsp::getProcIndex $packagename] + set handle $::tsp::TCC_HANDLE set loadextlibs "proc ${packagename}_loadextdlls {dir} {\ncatch {\n" - append loadextlibs {set appdir [file dir [info nameofexecutable]]} + append loadextlibs { + switch -- $::tcl_platform(platform) { + windows {set appdir [file dir [info nameofexecutable]]} + unix { + set appdir [file dir [info script]] + if {$appdir==$dir} { + set appdir [pwd] + } + } + } + } append loadextlibs "\n" set libs [$handle add_library] @@ -415,6 +576,9 @@ proc ::tsp::write_pkgIndex {packagename} { lappend libs {*}$::tsp::EXTERNAL_DLLS } foreach incpath $libs { + if {![file exists [file join $::tsp::PACKAGE_DIR $incpath[info sharedlibextension]]]} { + set incpath lib$incpath + } append loadextlibs "\nset incdll \[file join \$dir $incpath\[info sharedlibextension\]\]\n" append loadextlibs "set appdll \[file join \$appdir $incpath\[info sharedlibextension\]\]\n" append loadextlibs "if {!\[file exists \$appdll\]} {\n" @@ -428,17 +592,19 @@ proc ::tsp::write_pkgIndex {packagename} { } set pkgloadlib "proc ${packagename}_loadlib {dir packagename} {\n" - if {$loadextlibs ne ""} { + if {($loadextlibs ne "")||($::tsp::LOAD_DLLS ne "")} { append pkgloadlib " ${packagename}_loadextdlls \$dir\n" + } + if {($loadextlibs ne "")||($::tsp::LOAD_TCLS ne "")} { append pkgloadlib " ${packagename}_loadext \$dir\n" } - if {$cpr ne ""} { - append pkgloadlib " if {\[catch {load \[file join \$dir \$packagename\[info sharedlibextension\]\]} err\]} {\n" + if {$::tsp::PACKAGE_PROCS ne ""} { + append pkgloadlib " if {\[catch {load \[file join \$dir \$packagename\[info sharedlibextension\]\] \$packagename} err\]} {\n" append pkgloadlib " source \[file join \$dir \${packagename}.tclprocs.tcl\]\n" append pkgloadlib " }\n" } - if {$tclpr ne ""} { + if {$::tsp::TCL_PROCS ne ""} { # load puretcl proc also append pkgloadlib " source \[file join \$dir \${packagename}.puretcl.tcl\]\n" if {$::tsp::PACKAGE_INIT_PROC>0} { @@ -461,20 +627,42 @@ proc ::tsp::write_pkgIndex {packagename} { } append pkgloadext "}\n" - - set pkgrun "package ifneeded $packagename $::tsp::PACKAGE_VERSION \[list ${packagename}_loadlib \$dir {$packagename}\]\n" + set pkgrun "#run loader here\n${packagename}_loadlib \[file dir \[info script\]\] {$packagename}\n" puts $fd $loadextlibs puts $fd $pkgloadlib puts $fd $pkgloadext puts $fd $pkgrun close $fd + + set fd [open $filename w] + + set pkgrun "package ifneeded $packagename $::tsp::PACKAGE_VERSION \[list source \[file join \$dir [file tail $loadername]\]\]" + puts $fd $pkgrun + close $fd } proc ::tsp::write_pkgAltTcl {packagename} { # write an tcl file to keep all procs as alternate to compiled procs (can't load) # and those procs, that we didn't compile - set filename [file join $tsp::PACKAGE_DIR "$packagename.tclprocs.tcl"] + + # add a little help function + if {$::tsp::PACKAGE_NAMESPACE eq ""} { + set help_proc ::${packagename}_help + } else { + set help_proc ::${::tsp::PACKAGE_NAMESPACE}::help + } + + set help_body " puts {...\n" + append help_body [::tsp::getProcIndex $packagename] + append help_body "\n}\n" + set help_procdef [list $help_proc "" $help_body] + + if {[lsearch -index 0 $::tsp::TCL_PROCS $help_proc]==-1} { + lappend ::tsp::TCL_PROCS $help_procdef + } + + set filename [file join $::tsp::PACKAGE_DIR "$packagename.tclprocs.tcl"] set fd [open $filename w] puts $fd "# TSP Pure TCL procs for loadlib failure management" puts $fd "# package $packagename" @@ -491,6 +679,7 @@ proc ::tsp::write_pkgAltTcl {packagename} { lassign $procdef procname procargs procbody if {$procname eq "${packagename}_pkgInit"} { set ::tsp::PACKAGE_INIT_PROC 1 + puts "Init via $procname" } if {$::tsp::PACKAGE_NAMESPACE ne ""} { set procname "::${::tsp::PACKAGE_NAMESPACE}::$procname" @@ -501,7 +690,7 @@ proc ::tsp::write_pkgAltTcl {packagename} { } close $fd - set filename [file join $tsp::PACKAGE_DIR "${packagename}.puretcl.tcl"] + set filename [file join $::tsp::PACKAGE_DIR "${packagename}.puretcl.tcl"] set fd [open $filename w] puts $fd "# TSP Pure TCL procs for loadlib complemenary procs" puts $fd "# package $packagename" @@ -518,10 +707,11 @@ proc ::tsp::write_pkgAltTcl {packagename} { puts $fd "}" } - foreach procdef $tsp::TCL_PROCS { + foreach procdef $::tsp::TCL_PROCS { lassign $procdef procname procargs procbody if {$procname eq "${packagename}_pkgInit"} { set ::tsp::PACKAGE_INIT_PROC 1 + puts "Init via $procname" } puts $fd "proc ${procname} {$procargs} {$procbody}\n" } @@ -576,20 +766,20 @@ proc ::tsp::compile_package {packagename {compiler tccwin32}} { return 1 } - if {$tsp::COMPILE_DIRECTIVES eq ""} { + if {$::tsp::COMPILE_DIRECTIVES eq ""} { puts "ERROR: No compiler directives found" return -1 } - if {$tsp::PACKAGE_DIR eq ""} { + if {$::tsp::PACKAGE_DIR eq ""} { puts "No packagedir given, searching in $packagename/$packagename.c" - set filename [file join $tsp::PACKAGE_DIR "$packagename.c"] + set filename [file join $::tsp::PACKAGE_DIR "$packagename.c"] if {![file exists $filename]} { - set tsp::PACKAGE_DIR $packagename + set ::tsp::PACKAGE_DIR $packagename } } - set filename [file join $tsp::PACKAGE_DIR "$packagename.c"] - set dllname [file join $tsp::PACKAGE_DIR "$packagename.dll"] + set filename [file join $::tsp::PACKAGE_DIR "$packagename.c"] + set dllname [file join $::tsp::PACKAGE_DIR "$packagename.dll"] if {![file exists $filename]} { puts "ERROR: $filename source not found" return -1 @@ -600,19 +790,19 @@ proc ::tsp::compile_package {packagename {compiler tccwin32}} { cd $::tccenv::tccexecutabledir } - set cdirect [dict get $tsp::COMPILE_DIRECTIVES $compiler] + set cdirect [dict get $::tsp::COMPILE_DIRECTIVES $compiler] puts "Compiling external $cdirect" set ::errorCode "" catch { - eval exec $cdirect + exec {*}$cdirect } err cd $wd puts "Result:\n$err\n" if {[llength $::errorCode]>1} { puts "Compiling seems to have errors, execution halted" puts "errorCode $::errorCode" - return -code error + return -code error $err } return 1 } @@ -720,8 +910,10 @@ proc version:filediff {file1 file2 {cmdEqual {version:cmdEqual}} {cmdAdd {versio proc version:cmdEqual {txt line} { } proc version:cmdAdd {txt line} { + if {[string trim $txt]!=""} { append ::actdiff "$line: +$txt\n";update incr ::afilediffs + } } proc version:cmdDel {txt line} { if {[string trim $txt]!=""} { @@ -729,6 +921,10 @@ proc version:cmdDel {txt line} { incr ::afilediffs } } - +proc version:clear {} { + set ::lfilediffs "" + set ::tfilediffs "" + set ::cfilediffs 0 +} #----------------------------------- Code to remove ----------------------------------------- diff --git a/tsp-types.tcl b/tsp-types.tcl index 0feb50a..bcb5b74 100755 --- a/tsp-types.tcl +++ b/tsp-types.tcl @@ -174,9 +174,9 @@ proc ::tsp::parse_procDefs {compUnitDict def} { set validReturnTypes $::tsp::RETURN_TYPES set validArgTypes $::tsp::VAR_TYPES - # patch for native proc withou pushcallframe/popcallframe + # patch for native proc without pushcallframe/popcallframe dict set compUnit isNative 1 - set unsupportedTypes "array" + set unsupportedTypes [list "array"] set len [llength $def] if {$len < 2} { @@ -189,12 +189,14 @@ proc ::tsp::parse_procDefs {compUnitDict def} { } set found [lsearch $validReturnTypes $type] if {$found < 0} { - ::tsp::addError compUnit "::tsp::procdef: invalid return type: $type" + ::tsp::addError compUnit "::tsp::procdef: invalid return type: $type $def" + dict set compUnit returns $type return } set unsupported [lsearch $unsupportedTypes $type] if {$unsupported>-1} { - ::tsp::addWarning compUnit "::tsp::procdef: not a native type $type" + ::tsp::addError compUnit "::tsp::procdef: invalid return type: $type $def" + dict set compUnit returns $type dict set compUnit isNative 0 return } @@ -246,9 +248,9 @@ proc ::tsp::parse_procDefs {compUnitDict def} { set type [lindex $defArgs $i] set unsupported [lsearch $unsupportedTypes $type] if {$unsupported>-1} { - ::tsp::addWarning compUnit "::tsp::procdef: not a native type $type" + ::tsp::addError compUnit "::tsp::procdef: invalid argument type $type $def" dict set compUnit isNative 0 - return + #return } set found [lsearch $validArgTypes $type] if {$found < 0} { @@ -293,10 +295,11 @@ proc ::tsp::parse_varDefs {compUnitDict def} { return } set unsupported [lsearch "array" $type] + #set unsupported -1 if {$unsupported>-1} { - ::tsp::addWarning compUnit "::tsp::procdef: not a native type $type" + #::tsp::addWarning compUnit "::tsp::procdef: not a native type $type $def" dict set compUnit isNative 0 - return + #return } set var_list [lrange $def 1 end] @@ -492,7 +495,8 @@ proc ::tsp::reset_tmpvarsUsed {compUnitDict} { proc ::tsp::get_tmpvar {compUnitDict type {varName ""}} { upvar $compUnitDict compUnit - + #set callerlevel [expr [info level]-1] + #puts "tempvar $type requested from $callerlevel: [info level $callerlevel]" if {[lsearch $::tsp::VAR_TYPES $type] < 0 || $type eq "array"} { error "::tsp::get_tmpvar - invalid var type $type\n[::tsp::currentLine compUnit]\n[::tsp::error_stacktrace]" }