##
##
## Cmd.tcl : Behandlung von TCL Standart-Kommandos
##
## !! ACHTUNG !! NS share with "Agent" -> "Cmd"
##
#############################################################################
namespace eval ::Cmd {
variable OtInfo [ join { O T _ I N F O } "" ]
variable OtLObjNum [ join { O T _ L O B J _ N U M } "" ]
variable OtHeader [ join { O T _ H E A D E R } "" ]
variable IS_PROC_FOUND
variable CMP_O [::Env::Get CMP_O]
namespace import ::Agent::MRep::LReadArray
}
## --------------------------------------------------------------------------------
proc ::Cmd::Init {} {
variable IS_PROC_FOUND
array set IS_PROC_FOUND [ LReadArray IS_PROC_FOUND ]
}
## --------------------------------------------------------------------------------
proc ::Cmd::Done { Space } {
global STACK
return "${Space} if ( result != TCL_OK ) goto $STACK(Done);"
}
proc ::Cmd::DoneNULL { OBJ Space } {
return "${Space} if ( $OBJ == NULL ) { result = TCL_ERROR ; goto Done; }"
}
## --------------------------------------------------------------------------------
proc ::Cmd::_OtC {Space TList} {
global RET
append RET ${Space} [ ::Parse::Get [ lindex $TList 1 ] ]
}
## --------------------------------------------------------------------------------
proc ::Cmd::Analyse4 { Char Space Cnt } {
global BREAK STACK RET OBJ
set BoolEval $STACK(BoolEval)
set ExprEval $STACK(ExprEval)
set RefEval $STACK(RefEval)
set BREAK 0
## lock RefEval
if { $RefEval && [ lsearch {R K L B A I } $Char ] != -1 } {
set BREAK 1
return
}
## should be joined
set FLAG 0
if {[ lsearch { L A T I U F R V XE XX } $Char ] != -1 } {
if {![catch { join $STACK(Txt) } _Txt]} {
set FLAG 1
::Mem::Push Txt $_Txt
}
}
set Txt $STACK(Txt)
append LC " /* " [ ::CBE::C-String $Txt ] " */"
switch -exact -- $Char {
K {
::Tok::L-Dyn $Cnt $Space $LC
}
L {
::Tok::L-Sta $Cnt $Space $LC
}
B {
if { $STACK(Static) } {
set BREAK 1
} elseif { $STACK(ListEval) } {
lappend RET [ ::Static::Get2Num $Txt U ]
} else {
append RET "${Space}$OBJ = [ ::Static::Get2 U ]; $LC"
}
}
S {
if { $ExprEval } {
::Tok::SM $Cnt $Space $LC
} elseif { $BoolEval } {
::Tok::SB $Cnt $Space $LC
} else {
set SetEval2 $STACK(SetEval)
::Mem::Push SetEval 0
::Tok::S $Cnt $Space $LC $SetEval2
::Mem::Pop SetEval
}
}
T {
::Tok::T $Cnt $Space $LC $Txt
}
F {
::Tok::F $Cnt $Space $LC $Txt
}
U {
append RET "${Space}$OBJ = [ ::Static::Get2 NO REX ] ; $LC"
}
I {
append RET "${Space}$OBJ = [ ::Static::Get2 NO $STACK(CmdName) ] ; $LC"
}
C -
D {
if { $STACK(Static) } {
set BREAK 1
} elseif { $BoolEval && !$ExprEval } {
::Tok::CB $Char $Cnt $Space $LC
} else {
::Tok::CD $Char $Cnt $Space
}
}
A {
## Array referenzen sind IMMER(nicht mehr!!) statisch
## Die dynamischen Array-De-Referenzen werden bei <V> erledigt
if {[ ::Is::OnlyT [ lindex [ ::Parse::Get $Cnt ] 1 ] ]} {
append RET "${Space}$OBJ = [ ::Static::Get2 ]; $LC"
} else {
::Tok::S $Cnt $Space $LC 0
}
}
R {
set ProcLevel $STACK(ProcLevel)
if { $ProcLevel } { ::CmpLoc::Set $ProcLevel $Cnt }
if { $STACK(ListEval) } {
lappend RET [ ::Static::Get2Num $Txt ]
} else {
append RET "${Space}$OBJ = [ ::Static::Get2 ]; $LC"
}
}
V {
::Tok::V $Cnt $Space $LC
}
M {
## expr 1 + [OO]
## eval format $X
##
::Decl::DelObj
::Tok::M $Cnt $Txt [ string range $Space 0 end-2 ]
}
XE {
::Tok::XE $Cnt $Space $LC
}
XF {
## statische expression ohne {}'s
## dynamische expression mit separaten {} => expr {[incr List]} + 1
if { $BoolEval || $ExprEval } {
set C_Cnt [ ::Parse::Get $Cnt ] ; ## C_Cnt
if {[ ::Is::OnlyC $C_Cnt ]} {
set Ts_Cnt [ ::Parse::Get $C_Cnt ]
::Mem::PushROBJno
if { $ExprEval } {
::Tok::SM $Ts_Cnt $Space $LC
} else {
::Tok::SB $Ts_Cnt $Space $LC
}
::Mem::PopROBJ
}
} else {
set BREAK 1
}
}
XX {
if { $STACK(ListEval) } {
lappend RET [ ::Static::Get2Num $Txt ]
} elseif { $RefEval } {
::Tok::XX $Cnt $Space $LC
} else {
append RET "${Space}$OBJ = [ ::Static::Get2Txt $Txt ]; $LC"
}
}
XY {
if { $RefEval } {
::Tok::XX $Cnt $Space $LC
} else {
::Tok::XY $Cnt $Space
}
}
}
if { $FLAG } { ::Mem::Pop Txt }
}
## --------------------------------------------------------------------------------
proc ::Cmd::Analyse3OBJ { Cnt Space } {
::Mem::PushOBJ
::Cmd::Analyse3 $Cnt $Space
return [ ::Mem::PopOBJ ]
}
OtC_Is {
OtC_Global {
/* ARVTISKLJDMCUF */
static char *OTCHAR[]={ "T", "C", "F", "V", "S", "R", "A", "L", "D", "K", "M", "U", "I", "B" };
static Tcl_Obj *OTOBJ[14];
static char *OACHAR[]={ "XX", "XY", "XE", "XF" };
static Tcl_Obj *OAOBJ[4];
static Tcl_Obj *A4, *Eins;
} ; ## OtC_Global
OtC_Init {
pInit(OTOBJ,OTCHAR,14);
pInit(OAOBJ,OACHAR,4);
A4 = Tcl_NewStringObj("Analyse4",-1);
Tcl_IncrRefCount(A4);
Tcl_IncrRefCount(A4);
Eins = Tcl_NewBooleanObj(1);
Tcl_IncrRefCount(Eins);
Tcl_IncrRefCount(Eins);
}
proc ::Cmd::Analyse3 { Cnt Space } {
global BREAK STACK OBJ
## INIT
append Space " "
if { $STACK(ListEval) || $STACK(RefEval) || ( $STACK(BoolEval) && !$STACK(ExprEval) ) } {
# do nothing
} elseif { $STACK(BoolEval) } {
set OBJ [ ::Decl::GetObj b ]
} else {
set OBJ [ ::Decl::GetObj l ]
}
::Mem::IncrLevel
::Mem::Push Txt [ ::TclBE::Tok $Cnt 0 ]
## C
OtC_Register {Tcl_Obj *cnt *spa *obj=NULL *olist[4]}
OtC_Register {int ret token area}
OtC_Register {char *str}
OtC_Register {int len}
OtC {
SET_OBJ_TCL(cnt,Cnt);
SET_OBJ_TCL(spa,Space);
str = Tcl_GetByteArrayFromObj(cnt,&len);
ret = pOnlyBack ( str, len, "XYEF", 4, "TCFVSRALDKMUIB", 14, &token, &area, pOT_ONLY );
if (ret) {
obj = OTOBJ[token];
goto Write;
}
ret = pOnlyBack ( str, len, "XYEF", 4, NULL, 0, &token, &area, pOT_ONLY );
if (ret) {
obj = OAOBJ[area];
goto Write;
}
goto Error;
Write:
olist[0] = A4; /* Analyse4 */
olist[1] = obj; /* $Char */
olist[2] = spa; /* $Space */
olist[3] = cnt; /* $Tok */
result = Ot_EvalObjv(interp,4,olist,"punknown",-1,0);
if ( result != TCL_OK ) goto Done;
goto End;
Error:
SET_TCL_OBJ(BREAK,Eins);
End:
}
::Mem::Pop Txt
::Mem::DecrLevel
}
} { ; ##OtC_Is else
proc ::Cmd::Analyse3 { Cnt Space } {
global BREAK STACK OBJ
## INIT
append Space " "
if { $STACK(ListEval) || $STACK(RefEval) || ( $STACK(BoolEval) && !$STACK(ExprEval) ) } {
# do nothing
} elseif { $STACK(BoolEval) } {
set OBJ [ ::Decl::GetObj b ]
} else {
set OBJ [ ::Decl::GetObj l ]
}
::Mem::IncrLevel
::Mem::Push Txt [ ::TclBE::Tok $Cnt 0 ]
## alloc [ llength $TList ] Objects
if {[ regexp {^§[XYEF][[:digit:]]+-([ARVTISKLDMCUF])[[:digit:]]+§$} $Cnt DUMMY Char ]} {
Analyse4 $Char $Space $Cnt
} elseif {[ regexp {^§([XYEF])[[:digit:]]+§$} $Cnt DUMMY Char ]} {
Analyse4 X$Char $Space $Cnt
} elseif {[ regexp {^§X0-B[NXUOC][[:digit:]]+§$} $Cnt ]} {
Analyse4 B $Space $Cnt
} else {
set BREAK 1
}
::Mem::Pop Txt
::Mem::DecrLevel
}
} ;## end OtC_If
## --------------------------------------------------------------------------------
## Start of a new proc "::Decl::ResetObj l" at level 0
##
proc ::Cmd::Analyse2 {Space TList} {
global BREAK STACK
## MAIN
set ListEval $STACK(ListEval)
## reset Level
if { !$ListEval } {
::Decl::ResetObj l
}
## alloc
foreach Cnt $TList {
Analyse3 $Cnt $Space
if {$BREAK} break
}
## Obj not needed
if { $BREAK && !$ListEval } {
::Decl::FreeObj l
}
## Write the length
return [ ::Decl::GetLen l ]
}
## --------------------------------------------------------------------------------
## Analyse 1 ist IMMER erfolgreich
##
proc ::Cmd::Analyse1 { Space TList { Name {} } } {
variable CMP_O
global BREAK STACK RET LLevel
set F [ expr { $STACK(CmdTyp) == "BUILDIN" ? $CMP_O : 0 } ]
set FLAGS [ expr { $STACK(Area) == "G" ? "TCL_GLOBAL_ONLY" : "0" } ]
::Mem::Push RefEval 0
::Mem::PushRET
::Mem::PushDREF
set Len [ Analyse2 $Space $TList ]
set LDREF [ ::Mem::PopDREF ]
set LRET [ ::Mem::PopRET ]
::Mem::Pop RefEval
if { $BREAK } {
if { !$STACK(Static) } {
::Warning "compile as STRING <$STACK(Txt)>"
if { $STACK(Area) == "G" } { append FLAGS "|TCL_EVAL_DIRECT" }
set BREAK 0
append RET "${Space}result = Tcl_EvalObjEx(interp,[ ::Static::Get2 ],$FLAGS);" \
[ ::Cmd::Done $Space ]
}
return
} else {
append RET $LRET
}
## Write some DBG messages
append RET [ ::Print::DbgRet $Space $Len ]
switch -exact -- $F {
1 {
if { $Name != {} } {
set Str $Name
} else {
set Str "Tcl_[string totitle $STACK(CmdName) ]ObjCmd"
}
append RET "${Space}result = Ot_ObjInvoke(interp,$Len,l$LLevel,$Str);"
}
0 -
default {
append RET "${Space}result = Ot_EvalObjv(interp,$Len,l$LLevel,\"punknown\",-1,$FLAGS);"
}
}
append RET [ ::Mem::Dref $Space $LDREF ]
append RET [ ::Cmd::Done $Space ]
}
## --------------------------------------------------------------------------------
proc ::Cmd::Analyse { Cnt Space } {
global BuildIn
variable IS_PROC_FOUND
variable COMMANDS
## Get some Info
set TList [ ::Parse::Get $Cnt ]
set To [ lindex $TList 0 ]
if {[ ::Is::OnlyB $To ]} {
set To [ ::TclBE::BChar $To ]
} else {
set To [ ::Parse::Get $To ]
}
set Ta [ namespace tail $To ]
if { "::$Ta" == $To } { set To $Ta }
::Mem::Push CmdName $To
::Mem::PushOBJ
## check
if {[ info exists IS_PROC_FOUND($Cnt) ]} {
::Mem::Push CmdTyp [ lindex $IS_PROC_FOUND($Cnt) 0 ]
Analyse1 $Space $TList
} elseif {[ info exists BuildIn($To) ]} {
set Tt "::CBE::[ string totitle $To ]"
if {[ info exists COMMANDS($Tt) ]} {
global BREAK RET STACK
::Mem::Push CmdTyp BUILDIN
::Mem::PushRET
$Tt $Space $TList
set LRET [ ::Mem::PopRET ]
if { $BREAK } {
## 1. uplevel error => no message
## 2. during AreaY no error
if { $BREAK == 1 && !$STACK(Static) } {
::Warning "compile as TOKEN LIST <$STACK(Txt)>"
}
set BREAK 0
Analyse1 $Space $TList
} else {
append RET $LRET
}
} elseif { $To == "after" } {
## hat ClientData => keine Optimierung
::Mem::Push CmdTyp NO
Analyse1 $Space $TList
} elseif { $To == "fileevent" } {
::Mem::Push CmdTyp BUILDIN
Analyse1 $Space $TList Tcl_FileEventObjCmd
} else {
::Mem::Push CmdTyp BUILDIN
Analyse1 $Space $TList
}
} elseif {[ string equal -length 3 $To "OtC" ]} {
switch -exact $To {
OtC {
::Mem::Push CmdTyp NO
global RET
append RET ${Space} [ ::CBE::OtC [ ::Parse::Get [ lindex $TList 1 ] ] ]
}
OtC_Register {
::Mem::Push CmdTyp NO
::Decl::Add [ join [ ::Parse::Get [ lindex $TList 1 ] ] ]
}
OtC_Global {
::Mem::Push CmdTyp NO
lappend ::Print::Include [ join [ ::Parse::Get [ lindex $TList 1 ] ] ]
}
OtC_Init {
::Mem::Push CmdTyp NO
lappend ::Print::CInit [ join [ ::Parse::Get [ lindex $TList 1 ] ] ]
}
OtC_Is {
global BREAK RET STACK
::Mem::Push CmdTyp NO
::Mem::PushRET
::CBE::OtCEval $Space [ lindex $TList 1 ]
set LRET [ ::Mem::PopRET ]
if { $BREAK } {
::ErrorI "can't compile <$STACK(Txt)>"
} else {
append RET $LRET
}
}
OtC_Target {
set TGT [::Parse::Get [ lindex $TList 1 ]]
global BREAK RET STACK
::Mem::Push CmdTyp NO
::Mem::PushRET
::CBE::OtCEval $Space [ lindex $TList 2 ]
set LRET [ ::Mem::PopRET ]
if { $BREAK } {
::ErrorI "can't compile <$STACK(Txt)>"
} else {
append RET \n "#ifdef OTTARGET_$TGT" \n \
$LRET \n \
"#endif /* $TGT */"
}
}
defaut {
::Mem::Push CmdTyp NO
Analyse1 $Space $TList
}
}
} else {
::Mem::Push CmdTyp NO
Analyse1 $Space $TList
}
::Mem::PopOBJ
::Mem::Pop CmdName CmdTyp
}