1if 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
10
11
12local next , rawget , tostring , tonumber = next , rawget , tostring , tonumber
13local gsub , match , find = string . gsub , string . match , string . find
14local insert , remove , concat = table . insert , table . remove , table . concat
15local validstring , formatters = string . valid , string . formatters
16local sortedhash = table . sortedhash
17local setmetatableindex , setmetatablenewindex = table . setmetatableindex , table . setmetatablenewindex
18
19local commands = commands
20local resolvers = resolvers
21local context = context
22
23local ctx_doifelse = commands . doifelse
24
25local implement = interfaces . implement
26
27local trace_jobfiles = false trackers . register ( " system.jobfiles " , function ( v ) trace_jobfiles = v end )
28
29local report = logs . reporter ( " system " )
30local report_jobfiles = logs . reporter ( " system " , " jobfiles " )
31local report_functions = logs . reporter ( " system " , " functions " )
32
33local texsetcount = tex . setcount
34local elements = interfaces . elements
35local constants = interfaces . constants
36local variables = interfaces . variables
37local settings_to_array = utilities . parsers . settings_to_array
38local allocate = utilities . storage . allocate
39
40local nameonly = file . nameonly
41local suffixonly = file . suffix
42local basename = file . basename
43local addsuffix = file . addsuffix
44local removesuffix = file . removesuffix
45local dirname = file . dirname
46local is_qualified_path = file . is_qualified_path
47
48local cleanpath = resolvers . cleanpath
49local toppath = resolvers . toppath
50local resolveprefix = resolvers . resolve
51
52local currentfile = luatex . currentfile
53
54local hasscheme = url . hasscheme
55
56local jobresolvers = resolvers . jobs
57
58local registerextrapath = resolvers . registerextrapath
59local resetextrapaths = resolvers . resetextrapaths
60local getextrapaths = resolvers . getextrapath
61local pushextrapath = resolvers . pushextrapath
62local popextrapath = resolvers . popextrapath
63
64
65local v_text = variables . text
66local v_project = variables . project
67local v_environment = variables . environment
68local v_product = variables . product
69local v_component = variables . component
70local v_yes = variables . yes
71
72
73
74local function findctxfile ( name )
75 if is_qualified_path ( name ) then
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
82end
83
84resolvers . findctxfile = findctxfile
85
86implement {
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
97implement {
98 name = " doifelseinputfile " ,
99 arguments = " string " ,
100 actions = function ( name )
101 ctx_doifelse ( findctxfile ( name ) ~ = " " )
102 end
103}
104
105implement {
106 name = " locatefilepath " ,
107 arguments = " string " ,
108 actions = function ( name )
109 context ( dirname ( findctxfile ( name ) ) )
110 end
111}
112
113implement {
114 name = " usepath " ,
115 arguments = " string " ,
116 actions = function ( paths )
117 report_jobfiles ( " using path: %s " , paths )
118 registerextrapath ( paths )
119 end
120}
121
122implement {
123 name = " pushpath " ,
124 arguments = " string " ,
125 actions = function ( paths )
126 report_jobfiles ( " pushing path: %s " , paths )
127 pushextrapath ( paths )
128 end
129}
130
131implement {
132 name = " poppath " ,
133 actions = function ( paths )
134 popextrapath ( )
135 report_jobfiles ( " popping path " )
136 end
137}
138
139implement {
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
148implement {
149 name = " resetpath " ,
150 actions = function ( )
151 report_jobfiles ( " resetting path " )
152 resetextrapaths ( )
153 end
154}
155
156implement {
157 name = " allinputpaths " ,
158 actions = function ( )
159 context ( concat ( getextrapaths ( ) , " , " ) )
160 end
161}
162
163implement {
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
176
177local texpatterns = { " %s.mkvi " , " %s.mkiv " , " %s.mklx " , " %s.mkxl " , " %s.tex " }
178local luapatterns = { " %s " . . utilities . lua . suffixes . luc , " %s.lua " , " %s.lmt " }
179local cldpatterns = { " %s.cld " }
180local xmlpatterns = { " %s.xml " }
181
182local uselibrary = resolvers . uselibrary
183local input = context . input
184
185
186
187
188
189local processstack = { }
190local processedfile = " "
191local processedfiles = { }
192
193implement {
194 name = " processedfile " ,
195 actions = function ( )
196 context ( processedfile )
197 end
198}
199
200implement {
201 name = " processedfiles " ,
202 actions = function ( )
203 context ( concat ( processedfiles , " , " ) )
204 end
205}
206
207implement {
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
217implement {
218 name = " dostoptextfile " ,
219 actions = function ( )
220 processedfile = remove ( processstack ) or " "
221 end
222}
223
224local function startprocessing ( name , notext )
225 if not notext then
226
227 context . dostarttextfile ( name )
228 end
229end
230
231local function stopprocessing ( notext )
232 if not notext then
233 context . dostoptextfile ( )
234
235 end
236end
237
238
239
240local typestack = { }
241local currenttype = v_text
242local nofmissing = 0
243local missing = {
244 tex = setmetatableindex ( " number " ) ,
245 lua = setmetatableindex ( " number " ) ,
246 cld = setmetatableindex ( " number " ) ,
247 xml = setmetatableindex ( " number " ) ,
248}
249
250local function reportfailure ( kind , name )
251 nofmissing = nofmissing + 1
252 missing [ kind ] [ name ] = true
253 report_jobfiles ( " unknown %s file %a " , kind , name )
254end
255
256
257
258local function action ( name , foundname )
259 input ( foundname )
260end
261local function failure ( name , foundname )
262 reportfailure ( " tex " , name )
263end
264local 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 )
274end
275
276local function action ( name , foundname )
277 dofile ( foundname )
278end
279local function failure ( name , foundname )
280 reportfailure ( " lua " , name )
281end
282local function useluafile ( name , onlyonce , notext )
283 uselibrary {
284 name = name ,
285 patterns = luapatterns ,
286 action = action ,
287 failure = failure ,
288 onlyonce = onlyonce ,
289 }
290end
291
292local function action ( name , foundname )
293 dofile ( foundname )
294end
295local function failure ( name , foundname )
296 reportfailure ( " cld " , name )
297end
298local 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 )
308end
309
310local function action ( name , foundname )
311 context . xmlprocess ( foundname , " main " , " " )
312end
313local function failure ( name , foundname )
314 reportfailure ( " xml " , name )
315end
316local 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 )
326end
327
328local 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
341local function useanyfile ( name , onlyonce )
342 local s = suffixes [ suffixonly ( name ) ]
343 context ( function ( ) resolvers . pushpath ( name ) end )
344 if s then
345
346 s ( name , onlyonce )
347 else
348 usetexfile ( name , onlyonce )
349
350 end
351 context ( resolvers . poppath )
352end
353
354implement { name = " usetexfile " , actions = usetexfile , arguments = " string " }
355implement { name = " useluafile " , actions = useluafile , arguments = " string " }
356implement { name = " usecldfile " , actions = usecldfile , arguments = " string " }
357implement { name = " usexmlfile " , actions = usexmlfile , arguments = " string " }
358
359implement { name = " usetexfileonce " , actions = usetexfile , arguments = { " string " , true } }
360implement { name = " useluafileonce " , actions = useluafile , arguments = { " string " , true } }
361implement { name = " usecldfileonce " , actions = usecldfile , arguments = { " string " , true } }
362implement { name = " usexmlfileonce " , actions = usexmlfile , arguments = { " string " , true } }
363
364implement { name = " useanyfile " , actions = useanyfile , arguments = " string " }
365implement { name = " useanyfileonce " , actions = useanyfile , arguments = { " string " , true } }
366
367function jobresolvers . usefile ( name , onlyonce , notext )
368 local s = suffixes [ suffixonly ( name ) ]
369 if s then
370
371 s ( name , onlyonce , notext )
372 end
373end
374
375
376
377local textlevel = 0
378
379local function dummyfunction ( ) end
380
381local function startstoperror ( )
382 report ( " invalid \\%s%s ... \\%s%s structure " , elements . start , v_text , elements . stop , v_text )
383 startstoperror = dummyfunction
384end
385
386local stopped
387
388local 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 )
397end
398
399local 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
415end
416
417implement { name = " starttext " , actions = starttext }
418implement { name = " stoptext " , actions = stoptext }
419
420implement {
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
436implement {
437 name = " forceendjob " ,
438 actions = function ( )
439 report ( [[ don't use \end to finish a document ]] )
440 context . stoptext ( )
441 end
442}
443
444implement {
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
454implement {
455 name = " autostoptext " ,
456 actions = stoptext
457}
458
459
460
461implement {
462 name = " processfilemany " ,
463 arguments = { " string " , false } ,
464 actions = useanyfile
465}
466
467implement {
468 name = " processfileonce " ,
469 arguments = { " string " , true } ,
470 actions = useanyfile
471}
472
473implement {
474 name = " processfilenone " ,
475 arguments = " string " ,
476 actions = dummyfunction ,
477}
478
479local tree = { type = " text " , name = " " , branches = { } }
480local treestack = { }
481local top = tree . branches
482local root = tree
483
484local project_stack = { }
485local product_stack = { }
486local component_stack = { }
487local environment_stack = { }
488
489local 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
498local function pushtree ( what , name )
499 local t = { }
500 top [ # top + 1 ] = { type = what , name = name , branches = t }
501 insert ( treestack , top )
502 top = t
503end
504
505local function poptree ( )
506 top = remove ( treestack )
507
508end
509
510do
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
541end
542
543local jobstructure = job . structure or { }
544job . structure = jobstructure
545jobstructure . collected = jobstructure . collected or { }
546jobstructure . tobesaved = root
547jobstructure . components = { }
548
549local 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 , { } )
564end
565
566job . register ( ' job.structure.collected ' , root , initialize )
567
568
569
570
571local ctx_processfilemany = context . processfilemany
572local ctx_processfileonce = context . processfileonce
573local ctx_processfilenone = context . processfilenone
574
575
576
577local function processfilecommon ( name , action )
578
579
580
581
582
583
584
585
586
587 action ( name )
588end
589
590local function processfilemany ( name ) processfilecommon ( name , ctx_processfilemany ) end
591local function processfileonce ( name ) processfilecommon ( name , ctx_processfileonce ) end
592local function processfilenone ( name ) processfilecommon ( name , ctx_processfilenone ) end
593
594local processors = utilities . storage . allocate {
595
596
597
598
599
600
601
602 [ v_text ] = {
603 [ v_text ] = { " many " , processfilemany } ,
604 [ v_project ] = { " once " , processfileonce } ,
605 [ v_environment ] = { " once " , processfileonce } ,
606 [ v_product ] = { " many " , processfilemany } ,
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
639local 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
647local 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
655jobresolvers . processors = processors
656
657local function topofstack ( what )
658 local stack = stacks [ what ]
659 return stack and stack [ # stack ] or environment . jobname
660end
661
662local function productcomponent ( )
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
670end
671
672local 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
680end
681
682jobresolvers . productcomponent = productcomponent
683jobresolvers . justacomponent = justacomponent
684
685function jobresolvers . currentproject ( ) return topofstack ( v_project ) end
686function jobresolvers . currentproduct ( ) return topofstack ( v_product ) end
687function jobresolvers . currentcomponent ( ) return topofstack ( v_component ) end
688function jobresolvers . currentenvironment ( ) return topofstack ( v_environment ) end
689
690local done = { }
691local tolerant = false
692
693local function process ( what , name )
694 local depth = # typestack
695 local process
696
697 name = resolveprefix ( name )
698
699
700
701 process = processors [ currenttype ] [ what ]
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
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
729
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
749end
750
751implement { name = " useproject " , actions = function ( name ) process ( v_project , name ) end , arguments = " string " }
752implement { name = " useenvironment " , actions = function ( name ) process ( v_environment , name ) end , arguments = " string " }
753implement { name = " useproduct " , actions = function ( name ) process ( v_product , name ) end , arguments = " string " }
754implement { name = " usecomponent " , actions = function ( name ) process ( v_component , name ) end , arguments = " string " }
755
756
757
758
759local start = {
760 [ v_project ] = context . startprojectindeed ,
761 [ v_product ] = context . startproductindeed ,
762 [ v_component ] = context . startcomponentindeed ,
763 [ v_environment ] = context . startenvironmentindeed ,
764}
765
766local stop = {
767 [ v_project ] = context . stopprojectindeed ,
768 [ v_product ] = context . stopproductindeed ,
769 [ v_component ] = context . stopcomponentindeed ,
770 [ v_environment ] = context . stopenvironmentindeed ,
771}
772
773local function gotonextlevel ( what , 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
781end
782
783local 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 ] )
790
791 context . signalendofinput ( what )
792end
793
794local function autoname ( name )
795 if name = = " * " then
796
797 name = nameonly ( currentfile ( ) or name )
798 end
799 return name
800end
801
802implement { name = " startproject " , actions = function ( name ) gotonextlevel ( v_project , autoname ( name ) ) end , arguments = " string " }
803implement { name = " startproduct " , actions = function ( name ) gotonextlevel ( v_product , autoname ( name ) ) end , arguments = " string " }
804implement { name = " startcomponent " , actions = function ( name ) gotonextlevel ( v_component , autoname ( name ) ) end , arguments = " string " }
805implement { name = " startenvironment " , actions = function ( name ) gotonextlevel ( v_environment , autoname ( name ) ) end , arguments = " string " }
806
807implement { name = " stopproject " , actions = function ( ) gotopreviouslevel ( v_project ) end }
808implement { name = " stopproduct " , actions = function ( ) gotopreviouslevel ( v_product ) end }
809implement { name = " stopcomponent " , actions = function ( ) gotopreviouslevel ( v_component ) end }
810implement { name = " stopenvironment " , actions = function ( ) gotopreviouslevel ( v_environment ) end }
811
812implement { name = " currentproject " , actions = function ( ) context ( topofstack ( v_project ) ) end }
813implement { name = " currentproduct " , actions = function ( ) context ( topofstack ( v_product ) ) end }
814implement { name = " currentcomponent " , actions = function ( ) context ( topofstack ( v_component ) ) end }
815implement { name = " currentenvironment " , actions = function ( ) context ( topofstack ( v_environment ) ) end }
816
817
818
819
820
821
822
823
824
825
826
827local report_examodes = logs . reporter ( " system " , " examodes " )
828
829local 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
842end
843
844function 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 )
851 convertexamodes ( io . loaddata ( filename ) )
852 else
853 report_examodes ( " no mode file %a " , filename )
854 end
855end
856
857implement {
858 name = " loadexamodes " ,
859 actions = environment . loadexamodes ,
860 arguments = " string "
861}
862
863
864
865
866
867
868document = document or {
869 arguments = allocate ( ) ,
870 files = allocate ( ) ,
871 variables = allocate ( ) ,
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
893function document . setargument ( key , value )
894 document . arguments [ key ] = value
895end
896
897function document . setdefaultargument ( key , default )
898 local v = document . arguments [ key ]
899 if v = = nil or v = = " " then
900 document . arguments [ key ] = default
901 end
902end
903
904function 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
910end
911
912function 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 " "
919end
920
921function document . getfilename ( i )
922 return document . files [ tonumber ( i ) ] or " "
923end
924
925implement {
926 name = " setdocumentargument " ,
927 actions = document . setargument ,
928 arguments = " 2 strings "
929}
930
931implement {
932 name = " setdocumentdefaultargument " ,
933 actions = document . setdefaultargument ,
934 arguments = " 2 strings "
935}
936
937implement {
938 name = " setdocumentfilename " ,
939 actions = document . setfilename ,
940 arguments = { " integer " , " string " }
941}
942
943implement {
944 name = " getdocumentargument " ,
945 actions = { document . getargument , context } ,
946 arguments = " 2 strings "
947}
948
949implement {
950 name = " getdocumentfilename " ,
951 actions = { document . getfilename , context } ,
952 arguments = " integer "
953}
954
955function document . setcommandline ( )
956
957
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: " , " " )
965 if arguments [ k ] = = nil then
966 arguments [ k ] = v
967 end
968 end
969
970
971
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
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
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027 context . setupsystem {
1028 directory = validstring ( arguments . setuppath ) ,
1029 inputfile = inputfile ,
1030 file = validstring ( arguments . result ) ,
1031 random = validstring ( arguments . randomseed ) ,
1032
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
1090end
1091
1092
1093
1094local function apply ( list , action )
1095 if list then
1096 for i = 1 , # list do
1097 action { list [ i ] }
1098 end
1099 end
1100end
1101
1102function document . setmodes ( )
1103 apply ( document . options . ctxfile . modes , context . enablemode )
1104 apply ( document . options . commandline . modes , context . enablemode )
1105end
1106
1107function document . setmodules ( )
1108 apply ( document . options . ctxfile . modules , context . usemodule )
1109 apply ( document . options . commandline . modules , context . usemodule )
1110end
1111
1112function document . setenvironments ( )
1113 apply ( document . options . ctxfile . environments , context . environment )
1114 apply ( document . options . commandline . environments , context . environment )
1115end
1116
1117function document . setfilenames ( )
1118 local initialize = environment . initializefilenames
1119 if initialize then
1120 initialize ( )
1121 else
1122
1123 end
1124end
1125
1126implement { name = " setdocumentcommandline " , actions = document . setcommandline , onlyonce = true }
1127implement { name = " setdocumentmodes " , actions = document . setmodes , onlyonce = true }
1128implement { name = " setdocumentmodules " , actions = document . setmodules , onlyonce = true }
1129implement { name = " setdocumentenvironments " , actions = document . setenvironments , onlyonce = true }
1130implement { name = " setdocumentfilenames " , actions = document . setfilenames , onlyonce = true }
1131
1132do
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
1147 local arguments = document . 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
1170end
1171
1172if 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
1204end
1205
1206implement {
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
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 |