-
Notifications
You must be signed in to change notification settings - Fork 0
/
bash.tcl
332 lines (297 loc) · 13.1 KB
/
bash.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# -*- coding: utf-8 -*-
#
# Licensed under the GNU General Public License, version 2.
# See the file http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
# Functions related to bash script languae (ebuild files are written with bash language). mostly used in ebuild.tcl
global geName geVersion geSuffix geSuffixVer geRevision
global gCommandLineList gFunctionSepList gPkgZipName
global xFunctionDefinitions
source predefined_functions.tcl
source String.tcl
namespace eval ::bash {
proc GetGentooVariables {} {
global xbashvar gEbuildFile
global geName geVersion geSuffix geSuffixVer geRevision
set geName ""
set geVersion ""
set Suffix ""
set geSuffix ""
set geSuffixVer ""
set Revision ""
set geRevision ""
regexp "^.*/(\[^/]*)$" $gEbuildFile xx gEbuildFile
set Rest $gEbuildFile
regexp "^(.*)(-(r\[0-9]*)).ebuild$" $Rest dummy Rest Revision geRevision
regexp "^(.*)(_(alpha|beta|pre|rc|p)(\[0-9]*)?)?$" $Rest dummy Rest Suffix geSuffix geSuffixVer
regexp "^(.*)-(\[0-9].*)$" $Rest dummy geName geVersion
#variables you can utilize but never set
set xbashvar [linsert $xbashvar end P "$geName-$geVersion$Suffix" \
PN "$geName" \
PV "$geVersion$Suffix" \
PR "$geRevision" \
PVR "$geVersion$Suffix$Revision" \
PF "$geName-$geVersion$Suffix$Revision" \
S "$geName-$geVersion$Suffix" \
T "/tmp" \
GAMES_BINDIR "usr/bin" \
ROOT [::func::FS installDIR] \
D "" DISTDIR "" FILESDIR "" WORKDIR "" INHERITED "" \
INSDESTTREE "" DESTTREE "/usr" "~diropts~" 0755 "~exeopts~" 0755 \
"~insopts~" 0644 "~libopts~" 0644]
}
# Clean Bash Variables...
proc cleanBashVar {a} {
regsub -all "\\$\{\[^\{\}]+\}" $a "" a
regsub -all "\[\{\}/]" $a "" a
regsub -all "," $a " " a
return $a
}
# Clean Bash Variables...
proc cleanBashVar2 {a} {
regsub -all "\\$\{\[^\{\}]+\}" $a "" a
regsub -all "," $a " " a
return $a
}
proc Parse_PkgZipName {line} {
#get bash variables
set ZipName -1
if {[regexp "^\[ \t]*SRC_URI=(.*)$" $line]} {
set line [lindex [::String::BashLine2TclList $line] 0]
regexp "/(\[^\/]+)\.tar\.?.?.?.?.?(\[ \t]|$)" $line xx ZipName
regsub "\\$" $ZipName "\\\\$" ZipName
}
return $ZipName
}
proc Parse_Inherit {line} {
#get bash variables
set thelist -1
regexp "^\[ \t]*inherit\[ \t]*(.*)$" $line xx thelist
return $thelist
}
#Get bash variable value
proc GetValue {var} {
global xbashvar xbashlocalvar
foreach {var1 value} $xbashlocalvar { if {$var == $var1} {return $value} }
foreach {var1 value} $xbashvar { if {$var == $var1} {return $value} }
return ""
}
proc SetVar {VarName Value} {
global xbashvar
if {$Value == ""} return
set ind [lsearch -exact $xbashvar $VarName]
if {$ind == -1} {
set xbashvar [linsert $xbashvar end $VarName $Value]
} else {
set xbashvar [lreplace $xbashvar [expr $ind+1] [expr $ind+1] $Value]
}
}
proc ParseVariable {{str ""}} {
global xbashvar xbashlocalvar gPkgZipName gline gDebug_NewVariable
#get bash variables
set my_gline $gline
if {$str != ""} {set my_gline $str}
if {[regexp "^\[ \t]*\[A-Za-z0-9\_\-]+=" $my_gline]} {
if {$str == ""} {
set line2 [lindex [::String::BashLine2TclList $my_gline] 0]
} else {
set line2 $my_gline
}
regsub -all "\\\\\{" $line2 "\{" line2
regsub -all "\\\\\}" $line2 "\}" line2
if {[regexp "^(\[A-Za-z0-9\_\-]+)=(.*)$" $line2 dummy Variable Value]} {
if {$Variable == "S"} {regsub "^\\$\\{?WORKDIR\\}?/$gPkgZipName/" $Value "" Value}
if {$Variable == "S"} {regsub "^\\$\\{?WORKDIR\\}?/$gPkgZipName" $Value "" Value}
if {$Variable == "S"} {regsub "^\\$\\{?WORKDIR\\}?/" $Value "" Value}
if {$Variable == "S"} {regsub "^\\$\\{?WORKDIR\\}?" $Value "" Value}
regexp "^\'(.*)\'$" $Value xx Value
set Value [::bash::PutBashVarValue $Value]
if {$Variable == "SRC_URI"} {
set Value2 $Value
while {[regsub -all "(^|\[ \t])\[^ \t]+/" $Value2 "\\1" Value2]} {}
set ind [lsearch -exact $xbashvar "A"]
if {$gDebug_NewVariable} {puts "A <-> $Value2"}
if {$ind == -1} {
set xbashvar [linsert $xbashvar end "A" $Value2]
} else {
set xbashvar [lreplace $xbashvar [expr $ind+1] [expr $ind+1] $Value2]
}
}
#Unknown Value
if {[regexp "\\$\\(.*" $Value]} {
if {[string length $Value] > 25} {
::cache::Add "# Unknown Variable: $Variable = $Value"
set Value "~~unknown~~"
}
}
#local function variables
set ind [lsearch -exact $xbashlocalvar $Variable]
if {$ind != -1} {
set xbashlocalvar [lreplace $xbashlocalvar [expr $ind+1] [expr $ind+1] $Value]
if {$gDebug_NewVariable} {puts "LOC: $Variable <--> $Value"}
return
}
set ind [lsearch -exact $xbashvar $Variable]
if {$gDebug_NewVariable} {puts "$Variable <-> $Value"}
if {$ind == -1} {set xbashvar [linsert $xbashvar end $Variable $Value]; return}
set xbashvar [lreplace $xbashvar [expr $ind+1] [expr $ind+1] $Value]
}
}
}
proc ParseFunctionDefinition {} {
global xFunctionDefinitions gline gDebug_ShowFunctionDef
set Body ""
if {[regexp "^\[ \t]*(\[^ \t]+)\[ \t]*\\(\\)\[ \t]*\{\[ \t]*$" $gline dummy FunctionName]} {
while { [::ebuild::GetNewLine] >= 0 } {
if {[regexp "^\[ \t]*$" $gline]} continue
if {[regexp "^\[ \t]*\}" $gline]} break
set Body [linsert $Body end $gline]
}
if {$gDebug_ShowFunctionDef} { puts "\[33mFunction <$FunctionName> :\[0m $Body" }
set xFunctionDefinitions [linsert $xFunctionDefinitions end $FunctionName $Body]
}
}
#Support output rediretion and piping..
proc CheckFunctionSeperators {line} {
global gCommandLineList gFunctionSepList gFuncInd
set gCommandLineList [::String::BashLine2TclList $line]
set gFunctionSepList [lsearch -all -regexp $gCommandLineList "(^\\|\\|$|^\\&\\&$|^;$)"]
set gFuncInd 0
}
proc GetNextFunction {} {
#line string list
global gCommandLineList
#function end points
global gFunctionSepList
#current function point
global gFuncInd
global gRet
::cache::StatusGet
set sep ""
if {$gFuncInd == 0} {
set a 0
} else {
if {[lindex $gFunctionSepList [expr $gFuncInd-1]] == ""} {return "~~-1~~"}
set a [expr "[lindex $gFunctionSepList [expr $gFuncInd-1]]+1"]
set sep [lindex $gCommandLineList [lindex $gFunctionSepList [expr $gFuncInd-1]]]
}
set b [expr "[lindex $gFunctionSepList $gFuncInd]-1"]
if {[lindex $gFunctionSepList $gFuncInd] == ""} {set b "end"}
set gFuncInd [expr "1+$gFuncInd"]
::cache::StatusUpdate
if {$sep == "\&\&" && $gRet == 0} {return "~~-1~~"}
if {$sep == "\|\|" && $gRet == 1} {return "~~-1~~"}
#skip unimportant functions..
if {[regexp "^(die|ewarn|einfo|eerror|ebegin|eend|enewuser|enewgroup)$" [lindex $gCommandLineList $a]]} {
return [GetNextFunction]
}
return [lrange $gCommandLineList $a $b]
}
#Puts bash variable's value
proc PutBashVarValue {line} {
global xbashvar xbashlocalvar
set ddd $line
set bashvarlist "$xbashvar $xbashlocalvar"
regsub "^\\$\\{?S\\}?/" $line "" line
regsub "^\\$\\{?S\\}?" $line "" line
regsub "^\\$\\{?DISTDIR\\}?/" $line "" line
regsub "^\\$\\{?DISTDIR\\}?" $line "" line
regsub "^\\$\\{?FILESDIR\\}?/" $line "" line
regsub "^\\$\\{?FILESDIR\\}?" $line "" line
regsub "^\\$\\{?WORKDIR\\}?/" $line "" line
regsub "^\\$\\{?WORKDIR\\}?" $line "" line
foreach {var value} $bashvarlist {
if {$value == "~~unknown~~"} continue
#1) Simply put the value
if {[regexp " " $value]} {
regsub -all "=\\$\\{$var\\}" $line "=\"$value\"" line
}
regsub -all "\\$\\{$var\\}" $line "$value" line
# PARAMETER SUBSTITUTION
#2) Ignore Default values
regsub -all "\\$\\{$var:?(-|=)\[^\\}\\{]+\\}" $line "$value" line
#3) ${parameter+alt_value}
while {1} {
if {[regexp "^(.*)\\$\\{$var:?\\+(\[^\\}\\{]+)\\}(.*)$" $line xx x1 x2 x3]} {
set line "$x1$x2$x3"
} else break
}
#4) ${var:pos:len}
while {1} {
if {[regexp "^(.*)\\$\\{$var:(\[^:a-zA-Z]+):(\[^:a-zA-Z]+)\\}(.*)$" $line xx x1 x2 x3 x4]} {
set line "$x1[string range $value $x2 [expr $x2+$x3-1]]$x4"
} else break
}
#5) ${var:pos}
while {1} {
if {[regexp "^(.*)\\$\\{$var:(\[^:a-zA-Z]+)\\}(.*)$" $line xx x1 x2 x3]} {
set line "$x1[string range $value $x2 end]$x3"
} else break
}
#6) ${var/pattern/replacement}
while {1} {
if {[regexp "^(.*)\\$\\{$var/(\[^/\\}\\{%]*)/(\[^/\\}\\{%]*)\\}(.*)$" $line xx x1 x2 x3 x4]} {
regsub {\-} $x2 {\\-} x2
regsub {\-} $x3 {\\-} x3
regsub $x2 $value $x3 value2
set line "$x1$value2$x4"
} else break
}
#7) ${var//pattern/replacement}
while {1} {
if {[regexp "^(.*)\\$\\{$var//(\[^/\\}\\{%]*)/(\[^/\\}\\{%]*)\\}(.*)$" $line xx x1 x2 x3 x4]} {
regsub {\-} $x2 {\\-} x2
regsub {\-} $x3 {\\-} x3
regsub -all $x2 $value $x3 value2
set line "$x1$value2$x4"
} else break
}
#8) $(Myfunctions)
regsub -all "@" $line "~~ed~~" line
regsub -all "#" $line "~~slash~~" line
regsub -all "(^|\[^\\\\])\\$\\(" $line "\\1@" line
regsub -all "(\[^\\\\])\\)" $line "\\1#" line
while {1} {
if {[regexp "^(.*)@(\[^@]+)#(.*)$" $line xx x1 x2 x3]} {
regsub -all "~~ed~~" $x2 "@" x2
regsub -all "~~slash~~" $x2 "#" x2
set xx [::ebuild2pisi::RunCodeBlock "\{[::String::BashLine2TclList $x2]\}"]
if {[::cache::GetUnknownCF]} {
set line "$x1\$\($x2\)$x3"
} else {
set line "$x1$xx$x3"
}
} else break
}
regsub -all "@" $line "\$\(" line
regsub -all "#" $line "\)" line
regsub -all "~~ed~~" $line "@" line
regsub -all "~~slash~~" $line "#" line
#9) `Myfunctions`
while {1} {
if {[regexp "^(\[^`]*)`(\[^`]+)`(.*)$" $line xx x1 x2 x3]} {
set xx [::ebuild2pisi::RunCodeBlock "\{[::String::BashLine2TclList $x2]\}"]
if {[::cache::GetUnknownCF]} {
set line "$x1~~@qu~~$x2~~@qu~~$x3"
} else {
set line "$x1$xx$x3"
}
} else break
}
regsub -all "~~@qu~~" $line "`" line
}
#Simply put values
foreach {var value} $bashvarlist { regsub -all "\\$[set var](\[^A-Za-z0-9\_\-]|$)" $line "$value\\2" line }
return $line
}
proc GetFunctionBody {FunctionName} {
global xFunctionDefinitions
foreach {FunctionName1 Body} $xFunctionDefinitions { if {$FunctionName == $FunctionName1} {return $Body} }
return ""
}
proc IsFunctionDefined {FunctionName} {
global xFunctionDefinitions
if {$FunctionName == "epatch"} {return 0}
foreach {FunctionName1 Body} $xFunctionDefinitions { if {$FunctionName == $FunctionName1} {return 1}}
return 0
}
}