file-job.lua /size: 35 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
file-job
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to file-job.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
7
}
8 9
-- in retrospect dealing it's not that bad to deal with the nesting
10
-- and push/poppign at the tex end
11 12
local
next
,
rawget
,
tostring
,
tonumber
=
next
,
rawget
,
tostring
,
tonumber
13
local
gsub
,
match
,
find
=
string
.
gsub
,
string
.
match
,
string
.
find
14
local
insert
,
remove
,
concat
=
table
.
insert
,
table
.
remove
,
table
.
concat
15
local
validstring
,
formatters
=
string
.
valid
,
string
.
formatters
16
local
sortedhash
=
table
.
sortedhash
17
local
setmetatableindex
,
setmetatablenewindex
=
table
.
setmetatableindex
,
table
.
setmetatablenewindex
18 19
local
commands
=
commands
20
local
resolvers
=
resolvers
21
local
context
=
context
22 23
local
ctx_doifelse
=
commands
.
doifelse
24 25
local
implement
=
interfaces
.
implement
26 27
local
trace_jobfiles
=
false
trackers
.
register
(
"
system.jobfiles
"
,
function
(
v
)
trace_jobfiles
=
v
end
)
28 29
local
report
=
logs
.
reporter
(
"
system
"
)
30
local
report_jobfiles
=
logs
.
reporter
(
"
system
"
,
"
jobfiles
"
)
31
local
report_functions
=
logs
.
reporter
(
"
system
"
,
"
functions
"
)
32 33
local
texsetcount
=
tex
.
setcount
34
local
elements
=
interfaces
.
elements
35
local
constants
=
interfaces
.
constants
36
local
variables
=
interfaces
.
variables
37
local
settings_to_array
=
utilities
.
parsers
.
settings_to_array
38
local
allocate
=
utilities
.
storage
.
allocate
39 40
local
nameonly
=
file
.
nameonly
41
local
suffixonly
=
file
.
suffix
42
local
basename
=
file
.
basename
43
local
addsuffix
=
file
.
addsuffix
44
local
removesuffix
=
file
.
removesuffix
45
local
dirname
=
file
.
dirname
46
local
is_qualified_path
=
file
.
is_qualified_path
47 48
local
cleanpath
=
resolvers
.
cleanpath
49
local
toppath
=
resolvers
.
toppath
50
local
resolveprefix
=
resolvers
.
resolve
51 52
local
currentfile
=
luatex
.
currentfile
53 54
local
hasscheme
=
url
.
hasscheme
55 56
local
jobresolvers
=
resolvers
.
jobs
57 58
local
registerextrapath
=
resolvers
.
registerextrapath
59
local
resetextrapaths
=
resolvers
.
resetextrapaths
60
local
getextrapaths
=
resolvers
.
getextrapath
61
local
pushextrapath
=
resolvers
.
pushextrapath
62
local
popextrapath
=
resolvers
.
popextrapath
63 64
----- v_outer = variables.outer
65
local
v_text
=
variables
.
text
66
local
v_project
=
variables
.
project
67
local
v_environment
=
variables
.
environment
68
local
v_product
=
variables
.
product
69
local
v_component
=
variables
.
component
70
local
v_yes
=
variables
.
yes
71 72
-- main code .. there is some overlap .. here we have loc://
73 74
local
function
findctxfile
(
name
)
-- loc ? any ?
75
if
is_qualified_path
(
name
)
then
-- maybe when no suffix do some test for tex
76
return
name
77
elseif
not
hasscheme
(
name
)
then
78
return
resolvers
.
finders
.
byscheme
(
"
loc
"
,
name
)
or
"
"
79
else
80
return
resolvers
.
findtexfile
(
name
)
or
"
"
81
end
82
end
83 84
resolvers
.
findctxfile
=
findctxfile
85 86
implement
{
87
name
=
"
processfile
"
,
88
arguments
=
"
string
"
,
89
actions
=
function
(
name
)
90
name
=
findctxfile
(
name
)
91
if
name
~
=
"
"
then
92
context
.
input
(
name
)
93
end
94
end
95
}
96 97
implement
{
98
name
=
"
doifelseinputfile
"
,
99
arguments
=
"
string
"
,
100
actions
=
function
(
name
)
101
ctx_doifelse
(
findctxfile
(
name
)
~
=
"
"
)
102
end
103
}
104 105
implement
{
106
name
=
"
locatefilepath
"
,
107
arguments
=
"
string
"
,
108
actions
=
function
(
name
)
109
context
(
dirname
(
findctxfile
(
name
)
)
)
110
end
111
}
112 113
implement
{
114
name
=
"
usepath
"
,
115
arguments
=
"
string
"
,
116
actions
=
function
(
paths
)
117
report_jobfiles
(
"
using path: %s
"
,
paths
)
118
registerextrapath
(
paths
)
119
end
120
}
121 122
implement
{
123
name
=
"
pushpath
"
,
124
arguments
=
"
string
"
,
125
actions
=
function
(
paths
)
126
report_jobfiles
(
"
pushing path: %s
"
,
paths
)
127
pushextrapath
(
paths
)
128
end
129
}
130 131
implement
{
132
name
=
"
poppath
"
,
133
actions
=
function
(
paths
)
134
popextrapath
(
)
135
report_jobfiles
(
"
popping path
"
)
136
end
137
}
138 139
implement
{
140
name
=
"
usesubpath
"
,
141
arguments
=
"
string
"
,
142
actions
=
function
(
subpaths
)
143
report_jobfiles
(
"
using subpath: %s
"
,
subpaths
)
144
registerextrapath
(
nil
,
subpaths
)
145
end
146
}
147 148
implement
{
149
name
=
"
resetpath
"
,
150
actions
=
function
(
)
151
report_jobfiles
(
"
resetting path
"
)
152
resetextrapaths
(
)
153
end
154
}
155 156
implement
{
157
name
=
"
allinputpaths
"
,
158
actions
=
function
(
)
159
context
(
concat
(
getextrapaths
(
)
,
"
,
"
)
)
160
end
161
}
162 163
implement
{
164
name
=
"
usezipfile
"
,
165
arguments
=
"
2 strings
"
,
166
actions
=
function
(
name
,
tree
)
167
if
tree
and
tree
~
=
"
"
then
168
resolvers
.
usezipfile
(
formatters
[
"
zip:///%s?tree=%s
"
]
(
name
,
tree
)
)
169
else
170
resolvers
.
usezipfile
(
formatters
[
"
zip:///%s
"
]
(
name
)
)
171
end
172
end
173
}
174 175
-- moved from tex to lua:
176 177
local
texpatterns
=
{
"
%s.mkvi
"
,
"
%s.mkiv
"
,
"
%s.mklx
"
,
"
%s.mkxl
"
,
"
%s.tex
"
}
178
local
luapatterns
=
{
"
%s
"
.
.
utilities
.
lua
.
suffixes
.
luc
,
"
%s.lua
"
,
"
%s.lmt
"
}
179
local
cldpatterns
=
{
"
%s.cld
"
}
180
local
xmlpatterns
=
{
"
%s.xml
"
}
181 182
local
uselibrary
=
resolvers
.
uselibrary
183
local
input
=
context
.
input
184 185
-- status
186
--
187
-- these need to be synced with input stream:
188 189
local
processstack
=
{
}
190
local
processedfile
=
"
"
191
local
processedfiles
=
{
}
192 193
implement
{
194
name
=
"
processedfile
"
,
195
actions
=
function
(
)
196
context
(
processedfile
)
197
end
198
}
199 200
implement
{
201
name
=
"
processedfiles
"
,
202
actions
=
function
(
)
203
context
(
concat
(
processedfiles
,
"
,
"
)
)
204
end
205
}
206 207
implement
{
208
name
=
"
dostarttextfile
"
,
209
arguments
=
"
string
"
,
210
actions
=
function
(
name
)
211
insert
(
processstack
,
name
)
212
processedfile
=
name
213
insert
(
processedfiles
,
name
)
214
end
215
}
216 217
implement
{
218
name
=
"
dostoptextfile
"
,
219
actions
=
function
(
)
220
processedfile
=
remove
(
processstack
)
or
"
"
221
end
222
}
223 224
local
function
startprocessing
(
name
,
notext
)
225
if
not
notext
then
226
-- report("begin file %a at line %a",name,status.linenumber or 0)
227
context
.
dostarttextfile
(
name
)
228
end
229
end
230 231
local
function
stopprocessing
(
notext
)
232
if
not
notext
then
233
context
.
dostoptextfile
(
)
234
-- report("end file %a at line %a",name,status.linenumber or 0)
235
end
236
end
237 238
--
239 240
local
typestack
=
{
}
241
local
currenttype
=
v_text
242
local
nofmissing
=
0
243
local
missing
=
{
244
tex
=
setmetatableindex
(
"
number
"
)
,
245
lua
=
setmetatableindex
(
"
number
"
)
,
246
cld
=
setmetatableindex
(
"
number
"
)
,
247
xml
=
setmetatableindex
(
"
number
"
)
,
248
}
249 250
local
function
reportfailure
(
kind
,
name
)
251
nofmissing
=
nofmissing
+
1
252
missing
[
kind
]
[
name
]
=
true
253
report_jobfiles
(
"
unknown %s file %a
"
,
kind
,
name
)
254
end
255 256
--
257 258
local
function
action
(
name
,
foundname
)
259
input
(
foundname
)
260
end
261
local
function
failure
(
name
,
foundname
)
262
reportfailure
(
"
tex
"
,
name
)
263
end
264
local
function
usetexfile
(
name
,
onlyonce
,
notext
)
265
startprocessing
(
name
,
notext
)
266
uselibrary
{
267
name
=
name
,
268
patterns
=
texpatterns
,
269
action
=
action
,
270
failure
=
failure
,
271
onlyonce
=
onlyonce
,
272
}
273
stopprocessing
(
notext
)
274
end
275 276
local
function
action
(
name
,
foundname
)
277
dofile
(
foundname
)
278
end
279
local
function
failure
(
name
,
foundname
)
280
reportfailure
(
"
lua
"
,
name
)
281
end
282
local
function
useluafile
(
name
,
onlyonce
,
notext
)
283
uselibrary
{
284
name
=
name
,
285
patterns
=
luapatterns
,
286
action
=
action
,
287
failure
=
failure
,
288
onlyonce
=
onlyonce
,
289
}
290
end
291 292
local
function
action
(
name
,
foundname
)
293
dofile
(
foundname
)
294
end
295
local
function
failure
(
name
,
foundname
)
296
reportfailure
(
"
cld
"
,
name
)
297
end
298
local
function
usecldfile
(
name
,
onlyonce
,
notext
)
299
startprocessing
(
name
,
notext
)
300
uselibrary
{
301
name
=
name
,
302
patterns
=
cldpatterns
,
303
action
=
action
,
304
failure
=
failure
,
305
onlyonce
=
onlyonce
,
306
}
307
stopprocessing
(
notext
)
308
end
309 310
local
function
action
(
name
,
foundname
)
311
context
.
xmlprocess
(
foundname
,
"
main
"
,
"
"
)
312
end
313
local
function
failure
(
name
,
foundname
)
314
reportfailure
(
"
xml
"
,
name
)
315
end
316
local
function
usexmlfile
(
name
,
onlyonce
,
notext
)
317
startprocessing
(
name
,
notext
)
318
uselibrary
{
319
name
=
name
,
320
patterns
=
xmlpatterns
,
321
action
=
action
,
322
failure
=
failure
,
323
onlyonce
=
onlyonce
,
324
}
325
stopprocessing
(
notext
)
326
end
327 328
local
suffixes
=
{
329
mkvi
=
usetexfile
,
330
mkiv
=
usetexfile
,
331
mklx
=
usetexfile
,
332
mkxl
=
usetexfile
,
333
tex
=
usetexfile
,
334
luc
=
useluafile
,
335
lua
=
useluafile
,
336
cld
=
usecldfile
,
337
xml
=
usexmlfile
,
338
[
"
"
]
=
usetexfile
,
339
}
340 341
local
function
useanyfile
(
name
,
onlyonce
)
342
local
s
=
suffixes
[
suffixonly
(
name
)
]
343
context
(
function
(
)
resolvers
.
pushpath
(
name
)
end
)
344
if
s
then
345
-- s(removesuffix(name),onlyonce)
346
s
(
name
,
onlyonce
)
-- so, first with suffix, then without
347
else
348
usetexfile
(
name
,
onlyonce
)
-- e.g. ctx file
349
-- resolvers.readfilename(name)
350
end
351
context
(
resolvers
.
poppath
)
352
end
353 354
implement
{
name
=
"
usetexfile
"
,
actions
=
usetexfile
,
arguments
=
"
string
"
}
355
implement
{
name
=
"
useluafile
"
,
actions
=
useluafile
,
arguments
=
"
string
"
}
356
implement
{
name
=
"
usecldfile
"
,
actions
=
usecldfile
,
arguments
=
"
string
"
}
357
implement
{
name
=
"
usexmlfile
"
,
actions
=
usexmlfile
,
arguments
=
"
string
"
}
358 359
implement
{
name
=
"
usetexfileonce
"
,
actions
=
usetexfile
,
arguments
=
{
"
string
"
,
true
}
}
360
implement
{
name
=
"
useluafileonce
"
,
actions
=
useluafile
,
arguments
=
{
"
string
"
,
true
}
}
361
implement
{
name
=
"
usecldfileonce
"
,
actions
=
usecldfile
,
arguments
=
{
"
string
"
,
true
}
}
362
implement
{
name
=
"
usexmlfileonce
"
,
actions
=
usexmlfile
,
arguments
=
{
"
string
"
,
true
}
}
363 364
implement
{
name
=
"
useanyfile
"
,
actions
=
useanyfile
,
arguments
=
"
string
"
}
365
implement
{
name
=
"
useanyfileonce
"
,
actions
=
useanyfile
,
arguments
=
{
"
string
"
,
true
}
}
366 367
function
jobresolvers
.
usefile
(
name
,
onlyonce
,
notext
)
368
local
s
=
suffixes
[
suffixonly
(
name
)
]
369
if
s
then
370
-- s(removesuffix(name),onlyonce,notext)
371
s
(
name
,
onlyonce
,
notext
)
-- so, first with suffix, then without
372
end
373
end
374 375
-- document structure
376 377
local
textlevel
=
0
-- inaccessible for user, we need to define counter textlevel at the tex end
378 379
local
function
dummyfunction
(
)
end
380 381
local
function
startstoperror
(
)
382
report
(
"
invalid \\%s%s ... \\%s%s structure
"
,
elements
.
start
,
v_text
,
elements
.
stop
,
v_text
)
383
startstoperror
=
dummyfunction
384
end
385 386
local
stopped
387 388
local
function
starttext
(
)
389
if
textlevel
=
=
0
then
390
if
trace_jobfiles
then
391
report_jobfiles
(
"
starting text
"
)
392
end
393
context
.
dostarttext
(
)
394
end
395
textlevel
=
textlevel
+
1
396
texsetcount
(
"
global
"
,
"
textlevel
"
,
textlevel
)
397
end
398 399
local
function
stoptext
(
)
400
if
not
stopped
then
401
if
textlevel
=
=
0
then
402
startstoperror
(
)
403
elseif
textlevel
>
0
then
404
textlevel
=
textlevel
-
1
405
end
406
texsetcount
(
"
global
"
,
"
textlevel
"
,
textlevel
)
407
if
textlevel
<
=
0
then
408
if
trace_jobfiles
then
409
report_jobfiles
(
"
stopping text
"
)
410
end
411
context
.
dostoptext
(
)
412
stopped
=
true
413
end
414
end
415
end
416 417
implement
{
name
=
"
starttext
"
,
actions
=
starttext
}
418
implement
{
name
=
"
stoptext
"
,
actions
=
stoptext
}
419 420
implement
{
421
name
=
"
forcequitjob
"
,
422
arguments
=
"
string
"
,
423
actions
=
function
(
reason
)
424
if
reason
then
425
report
(
"
forcing quit: %s
"
,
reason
)
426
else
427
report
(
"
forcing quit
"
)
428
end
429
context
.
batchmode
(
)
430
while
textlevel
>
=
0
do
431
context
.
stoptext
(
)
432
end
433
end
434
}
435 436
implement
{
437
name
=
"
forceendjob
"
,
438
actions
=
function
(
)
439
report
(
[[
don't use \end to finish a document
]]
)
440
context
.
stoptext
(
)
441
end
442
}
443 444
implement
{
445
name
=
"
autostarttext
"
,
446
actions
=
function
(
)
447
if
textlevel
=
=
0
then
448
report
(
[[
auto \starttext ... \stoptext
]]
)
449
end
450
context
.
starttext
(
)
451
end
452
}
453 454
implement
{
455
name
=
"
autostoptext
"
,
456
actions
=
stoptext
457
}
458 459
-- project structure
460 461
implement
{
462
name
=
"
processfilemany
"
,
463
arguments
=
{
"
string
"
,
false
}
,
464
actions
=
useanyfile
465
}
466 467
implement
{
468
name
=
"
processfileonce
"
,
469
arguments
=
{
"
string
"
,
true
}
,
470
actions
=
useanyfile
471
}
472 473
implement
{
474
name
=
"
processfilenone
"
,
475
arguments
=
"
string
"
,
476
actions
=
dummyfunction
,
477
}
478 479
local
tree
=
{
type
=
"
text
"
,
name
=
"
"
,
branches
=
{
}
}
480
local
treestack
=
{
}
481
local
top
=
tree
.
branches
482
local
root
=
tree
483 484
local
project_stack
=
{
}
485
local
product_stack
=
{
}
486
local
component_stack
=
{
}
487
local
environment_stack
=
{
}
488 489
local
stacks
=
{
490
[
v_project
]
=
project_stack
,
491
[
v_product
]
=
product_stack
,
492
[
v_component
]
=
component_stack
,
493
[
v_environment
]
=
environment_stack
,
494
}
495 496
--
497 498
local
function
pushtree
(
what
,
name
)
499
local
t
=
{
}
500
top
[
#
top
+
1
]
=
{
type
=
what
,
name
=
name
,
branches
=
t
}
501
insert
(
treestack
,
top
)
502
top
=
t
503
end
504 505
local
function
poptree
(
)
506
top
=
remove
(
treestack
)
507
-- inspect(top)
508
end
509 510
do
511 512
local
function
log_tree
(
report
,
top
,
depth
)
513
report
(
"
%s%s: %s
"
,
depth
,
top
.
type
,
top
.
name
)
514
local
branches
=
top
.
branches
515
if
#
branches
>
0
then
516
depth
=
depth
.
.
"
"
517
for
i
=
1
,
#
branches
do
518
log_tree
(
report
,
branches
[
i
]
,
depth
)
519
end
520
end
521
end
522 523
logs
.
registerfinalactions
(
function
(
)
524
root
.
name
=
environment
.
jobname
525
--
526
logs
.
startfilelogging
(
report
,
"
used files
"
)
527
log_tree
(
report
,
root
,
"
"
)
528
logs
.
stopfilelogging
(
)
529
--
530
if
nofmissing
>
0
and
logs
.
loggingerrors
(
)
then
531
logs
.
starterrorlogging
(
report
,
"
missing files
"
)
532
for
kind
,
list
in
sortedhash
(
missing
)
do
533
for
name
in
sortedhash
(
list
)
do
534
report
(
"
%w%s %s
"
,
6
,
kind
,
name
)
535
end
536
end
537
logs
.
stoperrorlogging
(
)
538
end
539
end
)
540 541
end
542 543
local
jobstructure
=
job
.
structure
or
{
}
544
job
.
structure
=
jobstructure
545
jobstructure
.
collected
=
jobstructure
.
collected
or
{
}
546
jobstructure
.
tobesaved
=
root
547
jobstructure
.
components
=
{
}
548 549
local
function
initialize
(
)
550
local
function
collect
(
root
,
result
)
551
local
branches
=
root
.
branches
552
if
branches
then
553
for
i
=
1
,
#
branches
do
554
local
branch
=
branches
[
i
]
555
if
branch
.
type
=
=
"
component
"
then
556
result
[
#
result
+
1
]
=
branch
.
name
557
end
558
collect
(
branch
,
result
)
559
end
560
end
561
return
result
562
end
563
jobstructure
.
components
=
collect
(
jobstructure
.
collected
,
{
}
)
564
end
565 566
job
.
register
(
'
job.structure.collected
'
,
root
,
initialize
)
567 568
-- component: small unit, either or not components itself
569
-- product : combination of components
570 571
local
ctx_processfilemany
=
context
.
processfilemany
572
local
ctx_processfileonce
=
context
.
processfileonce
573
local
ctx_processfilenone
=
context
.
processfilenone
574 575
-- we need a plug in the nested loaded, push pop pseudo current dir
576 577
local
function
processfilecommon
(
name
,
action
)
578
-- experiment, might go away
579
-- if not hasscheme(name) then
580
-- local path = dirname(name)
581
-- if path ~= "" then
582
-- registerextrapath(path)
583
-- report_jobfiles("adding search path %a",path)
584
-- end
585
-- end
586
-- till here
587
action
(
name
)
588
end
589 590
local
function
processfilemany
(
name
)
processfilecommon
(
name
,
ctx_processfilemany
)
end
591
local
function
processfileonce
(
name
)
processfilecommon
(
name
,
ctx_processfileonce
)
end
592
local
function
processfilenone
(
name
)
processfilecommon
(
name
,
ctx_processfilenone
)
end
593 594
local
processors
=
utilities
.
storage
.
allocate
{
595
-- [v_outer] = {
596
-- [v_text] = { "many", processfilemany },
597
-- [v_project] = { "once", processfileonce },
598
-- [v_environment] = { "once", processfileonce },
599
-- [v_product] = { "once", processfileonce },
600
-- [v_component] = { "many", processfilemany },
601
-- },
602
[
v_text
]
=
{
603
[
v_text
]
=
{
"
many
"
,
processfilemany
}
,
604
[
v_project
]
=
{
"
once
"
,
processfileonce
}
,
-- dubious
605
[
v_environment
]
=
{
"
once
"
,
processfileonce
}
,
606
[
v_product
]
=
{
"
many
"
,
processfilemany
}
,
-- dubious
607
[
v_component
]
=
{
"
many
"
,
processfilemany
}
,
608
}
,
609
[
v_project
]
=
{
610
[
v_text
]
=
{
"
many
"
,
processfilemany
}
,
611
[
v_project
]
=
{
"
none
"
,
processfilenone
}
,
612
[
v_environment
]
=
{
"
once
"
,
processfileonce
}
,
613
[
v_product
]
=
{
"
none
"
,
processfilenone
}
,
614
[
v_component
]
=
{
"
none
"
,
processfilenone
}
,
615
}
,
616
[
v_environment
]
=
{
617
[
v_text
]
=
{
"
many
"
,
processfilemany
}
,
618
[
v_project
]
=
{
"
none
"
,
processfilenone
}
,
619
[
v_environment
]
=
{
"
once
"
,
processfileonce
}
,
620
[
v_product
]
=
{
"
none
"
,
processfilenone
}
,
621
[
v_component
]
=
{
"
none
"
,
processfilenone
}
,
622
}
,
623
[
v_product
]
=
{
624
[
v_text
]
=
{
"
many
"
,
processfilemany
}
,
625
[
v_project
]
=
{
"
once
"
,
processfileonce
}
,
626
[
v_environment
]
=
{
"
once
"
,
processfileonce
}
,
627
[
v_product
]
=
{
"
many
"
,
processfilemany
}
,
628
[
v_component
]
=
{
"
many
"
,
processfilemany
}
,
629
}
,
630
[
v_component
]
=
{
631
[
v_text
]
=
{
"
many
"
,
processfilemany
}
,
632
[
v_project
]
=
{
"
once
"
,
processfileonce
}
,
633
[
v_environment
]
=
{
"
once
"
,
processfileonce
}
,
634
[
v_product
]
=
{
"
none
"
,
processfilenone
}
,
635
[
v_component
]
=
{
"
many
"
,
processfilemany
}
,
636
}
637
}
638 639
local
start
=
{
640
[
v_text
]
=
nil
,
641
[
v_project
]
=
nil
,
642
[
v_environment
]
=
context
.
startreadingfile
,
643
[
v_product
]
=
context
.
starttext
,
644
[
v_component
]
=
context
.
starttext
,
645
}
646 647
local
stop
=
{
648
[
v_text
]
=
nil
,
649
[
v_project
]
=
nil
,
650
[
v_environment
]
=
context
.
stopreadingfile
,
651
[
v_product
]
=
context
.
stoptext
,
652
[
v_component
]
=
context
.
stoptext
,
653
}
654 655
jobresolvers
.
processors
=
processors
656 657
local
function
topofstack
(
what
)
658
local
stack
=
stacks
[
what
]
659
return
stack
and
stack
[
#
stack
]
or
environment
.
jobname
660
end
661 662
local
function
productcomponent
(
)
-- only when in product
663
local
product
=
product_stack
[
#
product_stack
]
664
if
product
and
product
~
=
"
"
then
665
local
component
=
component_stack
[
1
]
666
if
component
and
component
~
=
"
"
then
667
return
component
668
end
669
end
670
end
671 672
local
function
justacomponent
(
)
673
local
product
=
product_stack
[
#
product_stack
]
674
if
not
product
or
product
=
=
"
"
then
675
local
component
=
component_stack
[
1
]
676
if
component
and
component
~
=
"
"
then
677
return
component
678
end
679
end
680
end
681 682
jobresolvers
.
productcomponent
=
productcomponent
683
jobresolvers
.
justacomponent
=
justacomponent
684 685
function
jobresolvers
.
currentproject
(
)
return
topofstack
(
v_project
)
end
686
function
jobresolvers
.
currentproduct
(
)
return
topofstack
(
v_product
)
end
687
function
jobresolvers
.
currentcomponent
(
)
return
topofstack
(
v_component
)
end
688
function
jobresolvers
.
currentenvironment
(
)
return
topofstack
(
v_environment
)
end
689 690
local
done
=
{
}
691
local
tolerant
=
false
-- too messy, mkii user with the wrong structure should adapt
692 693
local
function
process
(
what
,
name
)
694
local
depth
=
#
typestack
695
local
process
696
--
697
name
=
resolveprefix
(
name
)
698
--
699
-- if not tolerant then
700
-- okay, would be best but not compatible with mkii
701
process
=
processors
[
currenttype
]
[
what
]
702
-- elseif depth == 0 then
703
-- -- could be a component, product or (brr) project
704
-- if trace_jobfiles then
705
-- report_jobfiles("%s : %s > %s (case 1)",depth,currenttype,v_outer)
706
-- end
707
-- process = processors[v_outer][what]
708
-- elseif depth == 1 and typestack[1] == v_text then
709
-- -- we're still not doing a component or product
710
-- if trace_jobfiles then
711
-- report_jobfiles("%s : %s > %s (case 2)",depth,currenttype,v_outer)
712
-- end
713
-- process = processors[v_outer][what]
714
-- else
715
-- process = processors[currenttype][what]
716
-- end
717
if
process
then
718
local
method
=
process
[
1
]
719
if
method
=
=
"
none
"
then
720
if
trace_jobfiles
then
721
report_jobfiles
(
"
%s : %s : %s %s %a in %s %a
"
,
depth
,
method
,
"
ignoring
"
,
what
,
name
,
currenttype
,
topofstack
(
currenttype
)
)
722
end
723
elseif
method
=
=
"
once
"
and
done
[
name
]
then
724
if
trace_jobfiles
then
725
report_jobfiles
(
"
%s : %s : %s %s %a in %s %a
"
,
depth
,
method
,
"
skipping
"
,
what
,
name
,
currenttype
,
topofstack
(
currenttype
)
)
726
end
727
else
728
-- keep in mind that we also handle "once" at the file level
729
-- so there is a double catch
730
done
[
name
]
=
true
731
local
before
=
start
[
what
]
732
local
after
=
stop
[
what
]
733
if
trace_jobfiles
then
734
report_jobfiles
(
"
%s : %s : %s %s %a in %s %a
"
,
depth
,
method
,
"
processing
"
,
what
,
name
,
currenttype
,
topofstack
(
currenttype
)
)
735
end
736
if
before
then
737
before
(
)
738
end
739
process
[
2
]
(
name
)
740
if
after
then
741
after
(
)
742
end
743
end
744
else
745
if
trace_jobfiles
then
746
report_jobfiles
(
"
%s : %s : %s %s %a in %s %a
"
,
depth
,
"
none
"
,
"
ignoring
"
,
what
,
name
,
currenttype
,
topofstack
(
currenttype
)
)
747
end
748
end
749
end
750 751
implement
{
name
=
"
useproject
"
,
actions
=
function
(
name
)
process
(
v_project
,
name
)
end
,
arguments
=
"
string
"
}
752
implement
{
name
=
"
useenvironment
"
,
actions
=
function
(
name
)
process
(
v_environment
,
name
)
end
,
arguments
=
"
string
"
}
753
implement
{
name
=
"
useproduct
"
,
actions
=
function
(
name
)
process
(
v_product
,
name
)
end
,
arguments
=
"
string
"
}
-- will be overloaded
754
implement
{
name
=
"
usecomponent
"
,
actions
=
function
(
name
)
process
(
v_component
,
name
)
end
,
arguments
=
"
string
"
}
755 756
-- todo: setsystemmode to currenttype
757
-- todo: make start/stop commands at the tex end
758 759
local
start
=
{
760
[
v_project
]
=
context
.
startprojectindeed
,
761
[
v_product
]
=
context
.
startproductindeed
,
762
[
v_component
]
=
context
.
startcomponentindeed
,
763
[
v_environment
]
=
context
.
startenvironmentindeed
,
764
}
765 766
local
stop
=
{
767
[
v_project
]
=
context
.
stopprojectindeed
,
768
[
v_product
]
=
context
.
stopproductindeed
,
769
[
v_component
]
=
context
.
stopcomponentindeed
,
770
[
v_environment
]
=
context
.
stopenvironmentindeed
,
771
}
772 773
local
function
gotonextlevel
(
what
,
name
)
-- todo: something with suffix name
774
insert
(
stacks
[
what
]
,
name
)
775
insert
(
typestack
,
currenttype
)
776
currenttype
=
what
777
pushtree
(
what
,
name
)
778
if
start
[
what
]
then
779
start
[
what
]
(
)
780
end
781
end
782 783
local
function
gotopreviouslevel
(
what
)
784
if
stop
[
what
]
then
785
stop
[
what
]
(
)
786
end
787
poptree
(
)
788
currenttype
=
remove
(
typestack
)
or
v_text
789
remove
(
stacks
[
what
]
)
-- not currenttype ... weak recovery
790
-- context.endinput() -- does not work
791
context
.
signalendofinput
(
what
)
792
end
793 794
local
function
autoname
(
name
)
795
if
name
=
=
"
*
"
then
796
-- name = nameonly(toppath() or name)
797
name
=
nameonly
(
currentfile
(
)
or
name
)
798
end
799
return
name
800
end
801 802
implement
{
name
=
"
startproject
"
,
actions
=
function
(
name
)
gotonextlevel
(
v_project
,
autoname
(
name
)
)
end
,
arguments
=
"
string
"
}
803
implement
{
name
=
"
startproduct
"
,
actions
=
function
(
name
)
gotonextlevel
(
v_product
,
autoname
(
name
)
)
end
,
arguments
=
"
string
"
}
804
implement
{
name
=
"
startcomponent
"
,
actions
=
function
(
name
)
gotonextlevel
(
v_component
,
autoname
(
name
)
)
end
,
arguments
=
"
string
"
}
805
implement
{
name
=
"
startenvironment
"
,
actions
=
function
(
name
)
gotonextlevel
(
v_environment
,
autoname
(
name
)
)
end
,
arguments
=
"
string
"
}
806 807
implement
{
name
=
"
stopproject
"
,
actions
=
function
(
)
gotopreviouslevel
(
v_project
)
end
}
808
implement
{
name
=
"
stopproduct
"
,
actions
=
function
(
)
gotopreviouslevel
(
v_product
)
end
}
809
implement
{
name
=
"
stopcomponent
"
,
actions
=
function
(
)
gotopreviouslevel
(
v_component
)
end
}
810
implement
{
name
=
"
stopenvironment
"
,
actions
=
function
(
)
gotopreviouslevel
(
v_environment
)
end
}
811 812
implement
{
name
=
"
currentproject
"
,
actions
=
function
(
)
context
(
topofstack
(
v_project
)
)
end
}
813
implement
{
name
=
"
currentproduct
"
,
actions
=
function
(
)
context
(
topofstack
(
v_product
)
)
end
}
814
implement
{
name
=
"
currentcomponent
"
,
actions
=
function
(
)
context
(
topofstack
(
v_component
)
)
end
}
815
implement
{
name
=
"
currentenvironment
"
,
actions
=
function
(
)
context
(
topofstack
(
v_environment
)
)
end
}
816 817
-- -- -- this will move -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
818
--
819
-- <?xml version='1.0' standalone='yes'?>
820
-- <exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>
821
-- <exa:variable label='mode:pragma'>nee</exa:variable>
822
-- <exa:variable label='mode:variant'>standaard</exa:variable>
823
-- </exa:variables>
824
--
825
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
826 827
local
report_examodes
=
logs
.
reporter
(
"
system
"
,
"
examodes
"
)
828 829
local
function
convertexamodes
(
str
)
830
local
x
=
xml
.
convert
(
str
)
831
for
e
in
xml
.
collected
(
x
,
"
exa:variable
"
)
do
832
local
label
=
e
.
at
and
e
.
at
.
label
833
if
label
and
label
~
=
"
"
then
834
local
data
=
xml
.
text
(
e
)
835
local
mode
=
match
(
label
,
"
^mode:(.+)$
"
)
836
if
mode
then
837
context
.
enablemode
{
formatters
[
"
%s:%s
"
]
(
mode
,
data
)
}
838
end
839
context
.
setvariable
(
"
exa:variables
"
,
label
,
(
gsub
(
data
,
"
([{}])
"
,
"
\\%1
"
)
)
)
840
end
841
end
842
end
843 844
function
environment
.
loadexamodes
(
filename
)
845
if
not
filename
or
filename
=
=
"
"
then
846
filename
=
removesuffix
(
tex
.
jobname
)
847
end
848
filename
=
resolvers
.
findfile
(
addsuffix
(
filename
,
'
ctm
'
)
)
or
"
"
849
if
filename
~
=
"
"
then
850
report_examodes
(
"
loading %a
"
,
filename
)
-- todo: message system
851
convertexamodes
(
io
.
loaddata
(
filename
)
)
852
else
853
report_examodes
(
"
no mode file %a
"
,
filename
)
-- todo: message system
854
end
855
end
856 857
implement
{
858
name
=
"
loadexamodes
"
,
859
actions
=
environment
.
loadexamodes
,
860
arguments
=
"
string
"
861
}
862 863
-- changed in mtx-context
864
-- code moved from luat-ini
865 866
-- todo: locals when mtx-context is changed
867 868
document
=
document
or
{
869
arguments
=
allocate
(
)
,
870
files
=
allocate
(
)
,
871
variables
=
allocate
(
)
,
-- for templates
872
options
=
{
873
commandline
=
{
874
environments
=
allocate
(
)
,
875
modules
=
allocate
(
)
,
876
modes
=
allocate
(
)
,
877
}
,
878
ctxfile
=
{
879
environments
=
allocate
(
)
,
880
modules
=
allocate
(
)
,
881
modes
=
allocate
(
)
,
882
}
,
883
}
,
884
functions
=
table
.
setmetatablenewindex
(
function
(
t
,
k
,
v
)
885
if
rawget
(
t
,
k
)
then
886
report_functions
(
"
overloading document function %a
"
,
k
)
887
end
888
rawset
(
t
,
k
,
v
)
889
return
v
890
end
)
,
891
}
892 893
function
document
.
setargument
(
key
,
value
)
894
document
.
arguments
[
key
]
=
value
895
end
896 897
function
document
.
setdefaultargument
(
key
,
default
)
898
local
v
=
document
.
arguments
[
key
]
899
if
v
=
=
nil
or
v
=
=
"
"
then
900
document
.
arguments
[
key
]
=
default
901
end
902
end
903 904
function
document
.
setfilename
(
i
,
name
)
905
if
name
then
906
document
.
files
[
tonumber
(
i
)
]
=
name
907
else
908
document
.
files
[
#
document
.
files
+
1
]
=
tostring
(
i
)
909
end
910
end
911 912
function
document
.
getargument
(
key
,
default
)
913
local
v
=
document
.
arguments
[
key
]
914
if
type
(
v
)
=
=
"
boolean
"
then
915
v
=
(
v
and
"
yes
"
)
or
"
no
"
916
document
.
arguments
[
key
]
=
v
917
end
918
return
v
or
default
or
"
"
919
end
920 921
function
document
.
getfilename
(
i
)
922
return
document
.
files
[
tonumber
(
i
)
]
or
"
"
923
end
924 925
implement
{
926
name
=
"
setdocumentargument
"
,
927
actions
=
document
.
setargument
,
928
arguments
=
"
2 strings
"
929
}
930 931
implement
{
932
name
=
"
setdocumentdefaultargument
"
,
933
actions
=
document
.
setdefaultargument
,
934
arguments
=
"
2 strings
"
935
}
936 937
implement
{
938
name
=
"
setdocumentfilename
"
,
939
actions
=
document
.
setfilename
,
940
arguments
=
{
"
integer
"
,
"
string
"
}
941
}
942 943
implement
{
944
name
=
"
getdocumentargument
"
,
945
actions
=
{
document
.
getargument
,
context
}
,
946
arguments
=
"
2 strings
"
947
}
948 949
implement
{
950
name
=
"
getdocumentfilename
"
,
951
actions
=
{
document
.
getfilename
,
context
}
,
952
arguments
=
"
integer
"
953
}
954 955
function
document
.
setcommandline
(
)
-- has to happen at the tex end in order to expand
956 957
-- the document[arguments|files] tables are copies
958 959
local
arguments
=
document
.
arguments
960
local
files
=
document
.
files
961
local
options
=
document
.
options
962 963
for
k
,
v
in
next
,
environment
.
arguments
do
964
k
=
gsub
(
k
,
"
^c:
"
,
"
"
)
-- already done, but better be safe than sorry
965
if
arguments
[
k
]
=
=
nil
then
966
arguments
[
k
]
=
v
967
end
968
end
969 970
-- in the new mtx=context approach we always pass a stub file so we need to
971
-- to trick the files table which actually only has one entry in a tex job
972 973
if
arguments
.
timing
then
974
context
.
usemodule
{
"
timing
"
}
975
end
976 977
if
arguments
.
usage
then
978
trackers
.
enable
(
"
system.usage
"
)
979
end
980 981
if
arguments
.
batchmode
then
982
context
.
batchmode
(
false
)
983
end
984 985
if
arguments
.
nonstopmode
then
986
context
.
nonstopmode
(
false
)
987
end
988 989
if
arguments
.
nostatistics
then
990
directives
.
enable
(
"
system.nostatistics
"
)
991
end
992 993
if
arguments
.
paranoid
then
994
context
.
setvalue
(
"
maxreadlevel
"
,
1
)
995
end
996 997
if
validstring
(
arguments
.
path
)
then
998
context
.
usepath
{
arguments
.
path
}
999
end
1000 1001
if
arguments
.
export
then
1002
context
.
setupbackend
{
export
=
v_yes
}
1003
end
1004 1005
local
inputfile
=
validstring
(
arguments
.
input
)
1006 1007
if
inputfile
and
dirname
(
inputfile
)
=
=
"
.
"
and
lfs
.
isfile
(
inputfile
)
then
1008
-- nicer in checks
1009
inputfile
=
basename
(
inputfile
)
1010
end
1011 1012
local
forcedruns
=
arguments
.
forcedruns
1013
local
kindofrun
=
arguments
.
kindofrun
1014
local
currentrun
=
arguments
.
currentrun
1015
local
maxnofruns
=
arguments
.
maxnofruns
or
arguments
.
runs
1016 1017
-- context.setupsystem {
1018
-- [constants.directory] = validstring(arguments.setuppath),
1019
-- [constants.inputfile] = inputfile,
1020
-- [constants.file] = validstring(arguments.result),
1021
-- [constants.random] = validstring(arguments.randomseed),
1022
-- -- old:
1023
-- [constants.n] = validstring(kindofrun),
1024
-- [constants.m] = validstring(currentrun),
1025
-- }
1026 1027
context
.
setupsystem
{
1028
directory
=
validstring
(
arguments
.
setuppath
)
,
1029
inputfile
=
inputfile
,
1030
file
=
validstring
(
arguments
.
result
)
,
1031
random
=
validstring
(
arguments
.
randomseed
)
,
1032
-- old:
1033
n
=
validstring
(
kindofrun
)
,
1034
m
=
validstring
(
currentrun
)
,
1035
}
1036 1037
forcedruns
=
tonumber
(
forcedruns
)
or
0
1038
kindofrun
=
tonumber
(
kindofrun
)
or
0
1039
maxnofruns
=
tonumber
(
maxnofruns
)
or
0
1040
currentrun
=
tonumber
(
currentrun
)
or
0
1041 1042
local
prerollrun
=
forcedruns
>
0
and
currentrun
>
0
and
currentrun
<
forcedruns
1043 1044
environment
.
forcedruns
=
forcedruns
1045
environment
.
kindofrun
=
kindofrun
1046
environment
.
maxnofruns
=
maxnofruns
1047
environment
.
currentrun
=
currentrun
1048
environment
.
prerollrun
=
prerollrun
1049 1050
context
.
setconditional
(
"
prerollrun
"
,
prerollrun
)
1051 1052
if
validstring
(
arguments
.
arguments
)
then
1053
context
.
setupenv
{
arguments
.
arguments
}
1054
end
1055 1056
if
arguments
.
once
then
1057
directives
.
enable
(
"
system.runonce
"
)
1058
end
1059 1060
if
arguments
.
noarrange
then
1061
context
.
setuparranging
{
variables
.
disable
}
1062
end
1063 1064
--
1065 1066
local
commandline
=
options
.
commandline
1067 1068
commandline
.
environments
=
table
.
append
(
commandline
.
environments
,
settings_to_array
(
validstring
(
arguments
.
environment
)
)
)
1069
commandline
.
modules
=
table
.
append
(
commandline
.
modules
,
settings_to_array
(
validstring
(
arguments
.
usemodule
)
)
)
1070
commandline
.
modes
=
table
.
append
(
commandline
.
modes
,
settings_to_array
(
validstring
(
arguments
.
mode
)
)
)
1071 1072
--
1073 1074
if
#
files
=
=
0
then
1075
local
list
=
settings_to_array
(
validstring
(
arguments
.
files
)
)
1076
if
list
and
#
list
>
0
then
1077
files
=
list
1078
end
1079
end
1080 1081
if
#
files
=
=
0
then
1082
files
=
{
validstring
(
arguments
.
input
)
}
1083
end
1084 1085
--
1086 1087
document
.
arguments
=
arguments
1088
document
.
files
=
files
1089 1090
end
1091 1092
-- commandline wins over ctxfile
1093 1094
local
function
apply
(
list
,
action
)
1095
if
list
then
1096
for
i
=
1
,
#
list
do
1097
action
{
list
[
i
]
}
1098
end
1099
end
1100
end
1101 1102
function
document
.
setmodes
(
)
-- was setup: *runtime:modes
1103
apply
(
document
.
options
.
ctxfile
.
modes
,
context
.
enablemode
)
1104
apply
(
document
.
options
.
commandline
.
modes
,
context
.
enablemode
)
1105
end
1106 1107
function
document
.
setmodules
(
)
-- was setup: *runtime:modules
1108
apply
(
document
.
options
.
ctxfile
.
modules
,
context
.
usemodule
)
1109
apply
(
document
.
options
.
commandline
.
modules
,
context
.
usemodule
)
1110
end
1111 1112
function
document
.
setenvironments
(
)
-- was setup: *runtime:environments
1113
apply
(
document
.
options
.
ctxfile
.
environments
,
context
.
environment
)
1114
apply
(
document
.
options
.
commandline
.
environments
,
context
.
environment
)
1115
end
1116 1117
function
document
.
setfilenames
(
)
1118
local
initialize
=
environment
.
initializefilenames
1119
if
initialize
then
1120
initialize
(
)
1121
else
1122
-- fatal error
1123
end
1124
end
1125 1126
implement
{
name
=
"
setdocumentcommandline
"
,
actions
=
document
.
setcommandline
,
onlyonce
=
true
}
1127
implement
{
name
=
"
setdocumentmodes
"
,
actions
=
document
.
setmodes
,
onlyonce
=
true
}
1128
implement
{
name
=
"
setdocumentmodules
"
,
actions
=
document
.
setmodules
,
onlyonce
=
true
}
1129
implement
{
name
=
"
setdocumentenvironments
"
,
actions
=
document
.
setenvironments
,
onlyonce
=
true
}
1130
implement
{
name
=
"
setdocumentfilenames
"
,
actions
=
document
.
setfilenames
,
onlyonce
=
true
}
1131 1132
do
1133 1134
logs
.
registerfinalactions
(
function
(
)
1135
local
foundintrees
=
resolvers
.
foundintrees
(
)
1136
if
#
foundintrees
>
0
then
1137
logs
.
startfilelogging
(
report
,
"
used files
"
)
1138
for
i
=
1
,
#
foundintrees
do
1139
report
(
"
%4i: % T
"
,
i
,
foundintrees
[
i
]
)
1140
end
1141
logs
.
stopfilelogging
(
)
1142
end
1143
end
)
1144 1145
logs
.
registerfinalactions
(
function
(
)
1146
local
files
=
document
.
files
-- or environment.files
1147
local
arguments
=
document
.
arguments
-- or environment.arguments
1148
--
1149
logs
.
startfilelogging
(
report
,
"
commandline options
"
)
1150
if
arguments
and
next
(
arguments
)
then
1151
for
argument
,
value
in
sortedhash
(
arguments
)
do
1152
report
(
"
%s=%A
"
,
argument
,
value
)
1153
end
1154
else
1155
report
(
"
no arguments
"
)
1156
end
1157
logs
.
stopfilelogging
(
)
1158
--
1159
logs
.
startfilelogging
(
report
,
"
commandline files
"
)
1160
if
files
and
#
files
>
0
then
1161
for
i
=
1
,
#
files
do
1162
report
(
"
% 4i: %s
"
,
i
,
files
[
i
]
)
1163
end
1164
else
1165
report
(
"
no files
"
)
1166
end
1167
logs
.
stopfilelogging
(
)
1168
end
)
1169 1170
end
1171 1172
if
environment
.
initex
then
1173 1174
logs
.
registerfinalactions
(
function
(
)
1175
local
startfilelogging
=
logs
.
startfilelogging
1176
local
stopfilelogging
=
logs
.
stopfilelogging
1177
startfilelogging
(
report
,
"
stored tables
"
)
1178
for
k
,
v
in
sortedhash
(
storage
.
data
)
do
1179
report
(
"
%03i %s
"
,
k
,
v
[
1
]
)
1180
end
1181
stopfilelogging
(
)
1182
startfilelogging
(
report
,
"
stored modules
"
)
1183
for
k
,
v
in
sortedhash
(
lua
.
bytedata
)
do
1184
report
(
"
%03i %s %s
"
,
k
,
v
.
name
)
1185
end
1186
stopfilelogging
(
)
1187
startfilelogging
(
report
,
"
stored attributes
"
)
1188
for
k
,
v
in
sortedhash
(
attributes
.
names
)
do
1189
report
(
"
%03i %s
"
,
k
,
v
)
1190
end
1191
stopfilelogging
(
)
1192
startfilelogging
(
report
,
"
stored catcodetables
"
)
1193
for
k
,
v
in
sortedhash
(
catcodes
.
names
)
do
1194
report
(
"
%03i % t
"
,
k
,
v
)
1195
end
1196
stopfilelogging
(
)
1197
startfilelogging
(
report
,
"
stored corenamespaces
"
)
1198
for
k
,
v
in
sortedhash
(
interfaces
.
corenamespaces
)
do
1199
report
(
"
%03i %s
"
,
k
,
v
)
1200
end
1201
stopfilelogging
(
)
1202
end
)
1203 1204
end
1205 1206
implement
{
1207
name
=
"
doifelsecontinuewithfile
"
,
1208
arguments
=
"
string
"
,
1209
actions
=
function
(
inpname
,
basetoo
)
1210
local
inpnamefull
=
addsuffix
(
inpname
,
"
tex
"
)
1211
local
inpfilefull
=
addsuffix
(
environment
.
inputfilename
,
"
tex
"
)
1212
local
continue
=
inpnamefull
=
=
inpfilefull
1213
-- if basetoo and not continue then
1214
if
not
continue
then
1215
continue
=
inpnamefull
=
=
basename
(
inpfilefull
)
1216
end
1217
if
continue
then
1218
report
(
"
continuing input file %a
"
,
inpname
)
1219
end
1220
ctx_doifelse
(
continue
)
1221
end
1222
}
1223