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