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 hasscheme = url . hasscheme
53
54local jobresolvers = resolvers . jobs
55
56local registerextrapath = resolvers . registerextrapath
57local resetextrapaths = resolvers . resetextrapaths
58local getextrapaths = resolvers . getextrapath
59local pushextrapath = resolvers . pushextrapath
60local popextrapath = resolvers . popextrapath
61
62
63local v_text = variables . text
64local v_project = variables . project
65local v_environment = variables . environment
66local v_product = variables . product
67local v_component = variables . component
68local v_yes = variables . yes
69
70
71
72local function findctxfile ( name )
73 if is_qualified_path ( name ) then
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
80end
81
82resolvers . findctxfile = findctxfile
83
84implement {
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
95implement {
96 name = " doifelseinputfile " ,
97 arguments = " string " ,
98 actions = function ( name )
99 ctx_doifelse ( findctxfile ( name ) ~ = " " )
100 end
101}
102
103implement {
104 name = " locatefilepath " ,
105 arguments = " string " ,
106 actions = function ( name )
107 context ( dirname ( findctxfile ( name ) ) )
108 end
109}
110
111implement {
112 name = " usepath " ,
113 arguments = " string " ,
114 actions = function ( paths )
115 report_jobfiles ( " using path: %s " , paths )
116 registerextrapath ( paths )
117 end
118}
119
120implement {
121 name = " pushpath " ,
122 arguments = " string " ,
123 actions = function ( paths )
124 report_jobfiles ( " pushing path: %s " , paths )
125 pushextrapath ( paths )
126 end
127}
128
129implement {
130 name = " poppath " ,
131 actions = function ( paths )
132 popextrapath ( )
133 report_jobfiles ( " popping path " )
134 end
135}
136
137implement {
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
146implement {
147 name = " resetpath " ,
148 actions = function ( )
149 report_jobfiles ( " resetting path " )
150 resetextrapaths ( )
151 end
152}
153
154implement {
155 name = " allinputpaths " ,
156 actions = function ( )
157 context ( concat ( getextrapaths ( ) , " , " ) )
158 end
159}
160
161implement {
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
174
175local texpatterns = { " %s.mkvi " , " %s.mkiv " , " %s.mklx " , " %s.mkxl " , " %s.tex " }
176local luapatterns = { " %s " . . utilities . lua . suffixes . luc , " %s.lua " , " %s.lmt " }
177local cldpatterns = { " %s.cld " }
178local xmlpatterns = { " %s.xml " }
179
180local uselibrary = resolvers . uselibrary
181local input = context . input
182
183
184
185
186
187local processstack = { }
188local processedfile = " "
189local processedfiles = { }
190
191implement {
192 name = " processedfile " ,
193 actions = function ( )
194 context ( processedfile )
195 end
196}
197
198implement {
199 name = " processedfiles " ,
200 actions = function ( )
201 context ( concat ( processedfiles , " , " ) )
202 end
203}
204
205implement {
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
215implement {
216 name = " dostoptextfile " ,
217 actions = function ( )
218 processedfile = remove ( processstack ) or " "
219 end
220}
221
222local function startprocessing ( name , notext )
223 if not notext then
224
225 context . dostarttextfile ( name )
226 end
227end
228
229local function stopprocessing ( notext )
230 if not notext then
231 context . dostoptextfile ( )
232
233 end
234end
235
236
237
238local typestack = { }
239local currenttype = v_text
240local nofmissing = 0
241local missing = {
242 tex = setmetatableindex ( " number " ) ,
243 lua = setmetatableindex ( " number " ) ,
244 cld = setmetatableindex ( " number " ) ,
245 xml = setmetatableindex ( " number " ) ,
246}
247
248local function reportfailure ( kind , name )
249 nofmissing = nofmissing + 1
250 missing [ kind ] [ name ] = true
251 report_jobfiles ( " unknown %s file %a " , kind , name )
252end
253
254
255
256local function action ( name , foundname )
257 input ( foundname )
258end
259local function failure ( name , foundname )
260 reportfailure ( " tex " , name )
261end
262local 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 )
272end
273
274local function action ( name , foundname )
275 dofile ( foundname )
276end
277local function failure ( name , foundname )
278 reportfailure ( " lua " , name )
279end
280local function useluafile ( name , onlyonce , notext )
281 uselibrary {
282 name = name ,
283 patterns = luapatterns ,
284 action = action ,
285 failure = failure ,
286 onlyonce = onlyonce ,
287 }
288end
289
290local function action ( name , foundname )
291 dofile ( foundname )
292end
293local function failure ( name , foundname )
294 reportfailure ( " cld " , name )
295end
296local 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 )
306end
307
308local function action ( name , foundname )
309 context . xmlprocess ( foundname , " main " , " " )
310end
311local function failure ( name , foundname )
312 reportfailure ( " xml " , name )
313end
314local 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 )
324end
325
326local 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
339local function useanyfile ( name , onlyonce )
340 local s = suffixes [ suffixonly ( name ) ]
341 context ( function ( ) resolvers . pushpath ( name ) end )
342 if s then
343
344 s ( name , onlyonce )
345 else
346 usetexfile ( name , onlyonce )
347
348 end
349 context ( resolvers . poppath )
350end
351
352implement { name = " usetexfile " , actions = usetexfile , arguments = " string " }
353implement { name = " useluafile " , actions = useluafile , arguments = " string " }
354implement { name = " usecldfile " , actions = usecldfile , arguments = " string " }
355implement { name = " usexmlfile " , actions = usexmlfile , arguments = " string " }
356
357implement { name = " usetexfileonce " , actions = usetexfile , arguments = { " string " , true } }
358implement { name = " useluafileonce " , actions = useluafile , arguments = { " string " , true } }
359implement { name = " usecldfileonce " , actions = usecldfile , arguments = { " string " , true } }
360implement { name = " usexmlfileonce " , actions = usexmlfile , arguments = { " string " , true } }
361
362implement { name = " useanyfile " , actions = useanyfile , arguments = " string " }
363implement { name = " useanyfileonce " , actions = useanyfile , arguments = { " string " , true } }
364
365function jobresolvers . usefile ( name , onlyonce , notext )
366 local s = suffixes [ suffixonly ( name ) ]
367 if s then
368
369 s ( name , onlyonce , notext )
370 end
371end
372
373
374
375local textlevel = 0
376
377local function dummyfunction ( ) end
378
379local function startstoperror ( )
380 report ( " invalid \\%s%s ... \\%s%s structure " , elements . start , v_text , elements . stop , v_text )
381 startstoperror = dummyfunction
382end
383
384local stopped
385
386local 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 )
395end
396
397local 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
413end
414
415implement { name = " starttext " , actions = starttext }
416implement { name = " stoptext " , actions = stoptext }
417
418implement {
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
434implement {
435 name = " forceendjob " ,
436 actions = function ( )
437 report ( [[ don't use \end to finish a document ]] )
438 context . stoptext ( )
439 end
440}
441
442implement {
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
452implement {
453 name = " autostoptext " ,
454 actions = stoptext
455}
456
457
458
459implement {
460 name = " processfilemany " ,
461 arguments = { " string " , false } ,
462 actions = useanyfile
463}
464
465implement {
466 name = " processfileonce " ,
467 arguments = { " string " , true } ,
468 actions = useanyfile
469}
470
471implement {
472 name = " processfilenone " ,
473 arguments = " string " ,
474 actions = dummyfunction ,
475}
476
477local tree = { type = " text " , name = " " , branches = { } }
478local treestack = { }
479local top = tree . branches
480local root = tree
481
482local project_stack = { }
483local product_stack = { }
484local component_stack = { }
485local environment_stack = { }
486
487local 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
496local function pushtree ( what , name )
497 local t = { }
498 top [ # top + 1 ] = { type = what , name = name , branches = t }
499 insert ( treestack , top )
500 top = t
501end
502
503local function poptree ( )
504 top = remove ( treestack )
505
506end
507
508do
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
539end
540
541local jobstructure = job . structure or { }
542job . structure = jobstructure
543jobstructure . collected = jobstructure . collected or { }
544jobstructure . tobesaved = root
545jobstructure . components = { }
546
547local 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 , { } )
562end
563
564job . register ( ' job.structure.collected ' , root , initialize )
565
566
567
568
569local ctx_processfilemany = context . processfilemany
570local ctx_processfileonce = context . processfileonce
571local ctx_processfilenone = context . processfilenone
572
573
574
575local function processfilecommon ( name , action )
576
577
578
579
580
581
582
583
584
585 action ( name )
586end
587
588local function processfilemany ( name ) processfilecommon ( name , ctx_processfilemany ) end
589local function processfileonce ( name ) processfilecommon ( name , ctx_processfileonce ) end
590local function processfilenone ( name ) processfilecommon ( name , ctx_processfilenone ) end
591
592local processors = utilities . storage . allocate {
593
594
595
596
597
598
599
600 [ v_text ] = {
601 [ v_text ] = { " many " , processfilemany } ,
602 [ v_project ] = { " once " , processfileonce } ,
603 [ v_environment ] = { " once " , processfileonce } ,
604 [ v_product ] = { " many " , processfilemany } ,
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
637local 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
645local 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
653jobresolvers . processors = processors
654
655local function topofstack ( what )
656 local stack = stacks [ what ]
657 return stack and stack [ # stack ] or environment . jobname
658end
659
660local function productcomponent ( )
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
668end
669
670local 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
678end
679
680jobresolvers . productcomponent = productcomponent
681jobresolvers . justacomponent = justacomponent
682
683function jobresolvers . currentproject ( ) return topofstack ( v_project ) end
684function jobresolvers . currentproduct ( ) return topofstack ( v_product ) end
685function jobresolvers . currentcomponent ( ) return topofstack ( v_component ) end
686function jobresolvers . currentenvironment ( ) return topofstack ( v_environment ) end
687
688local done = { }
689local tolerant = false
690
691local function process ( what , name )
692 local depth = # typestack
693 local process
694
695 name = resolveprefix ( name )
696
697
698
699 process = processors [ currenttype ] [ what ]
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
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
727
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
747end
748
749implement { name = " useproject " , actions = function ( name ) process ( v_project , name ) end , arguments = " string " }
750implement { name = " useenvironment " , actions = function ( name ) process ( v_environment , name ) end , arguments = " string " }
751implement { name = " useproduct " , actions = function ( name ) process ( v_product , name ) end , arguments = " string " }
752implement { name = " usecomponent " , actions = function ( name ) process ( v_component , name ) end , arguments = " string " }
753
754
755
756
757local start = {
758 [ v_project ] = context . startprojectindeed ,
759 [ v_product ] = context . startproductindeed ,
760 [ v_component ] = context . startcomponentindeed ,
761 [ v_environment ] = context . startenvironmentindeed ,
762}
763
764local stop = {
765 [ v_project ] = context . stopprojectindeed ,
766 [ v_product ] = context . stopproductindeed ,
767 [ v_component ] = context . stopcomponentindeed ,
768 [ v_environment ] = context . stopenvironmentindeed ,
769}
770
771local function gotonextlevel ( what , 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
779end
780
781local 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 ] )
788
789 context . signalendofinput ( what )
790end
791
792local function autoname ( name )
793 if name = = " * " then
794 name = nameonly ( toppath ( ) or name )
795 end
796 return name
797end
798
799implement { name = " startproject " , actions = function ( name ) gotonextlevel ( v_project , autoname ( name ) ) end , arguments = " string " }
800implement { name = " startproduct " , actions = function ( name ) gotonextlevel ( v_product , autoname ( name ) ) end , arguments = " string " }
801implement { name = " startcomponent " , actions = function ( name ) gotonextlevel ( v_component , autoname ( name ) ) end , arguments = " string " }
802implement { name = " startenvironment " , actions = function ( name ) gotonextlevel ( v_environment , autoname ( name ) ) end , arguments = " string " }
803
804implement { name = " stopproject " , actions = function ( ) gotopreviouslevel ( v_project ) end }
805implement { name = " stopproduct " , actions = function ( ) gotopreviouslevel ( v_product ) end }
806implement { name = " stopcomponent " , actions = function ( ) gotopreviouslevel ( v_component ) end }
807implement { name = " stopenvironment " , actions = function ( ) gotopreviouslevel ( v_environment ) end }
808
809implement { name = " currentproject " , actions = function ( ) context ( topofstack ( v_project ) ) end }
810implement { name = " currentproduct " , actions = function ( ) context ( topofstack ( v_product ) ) end }
811implement { name = " currentcomponent " , actions = function ( ) context ( topofstack ( v_component ) ) end }
812implement { name = " currentenvironment " , actions = function ( ) context ( topofstack ( v_environment ) ) end }
813
814
815
816
817
818
819
820
821
822
823
824local report_examodes = logs . reporter ( " system " , " examodes " )
825
826local 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
839end
840
841function 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 )
848 convertexamodes ( io . loaddata ( filename ) )
849 else
850 report_examodes ( " no mode file %a " , filename )
851 end
852end
853
854implement {
855 name = " loadexamodes " ,
856 actions = environment . loadexamodes ,
857 arguments = " string "
858}
859
860
861
862
863
864
865document = document or {
866 arguments = allocate ( ) ,
867 files = allocate ( ) ,
868 variables = allocate ( ) ,
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
890function document . setargument ( key , value )
891 document . arguments [ key ] = value
892end
893
894function document . setdefaultargument ( key , default )
895 local v = document . arguments [ key ]
896 if v = = nil or v = = " " then
897 document . arguments [ key ] = default
898 end
899end
900
901function 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
907end
908
909function 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 " "
916end
917
918function document . getfilename ( i )
919 return document . files [ tonumber ( i ) ] or " "
920end
921
922implement {
923 name = " setdocumentargument " ,
924 actions = document . setargument ,
925 arguments = " 2 strings "
926}
927
928implement {
929 name = " setdocumentdefaultargument " ,
930 actions = document . setdefaultargument ,
931 arguments = " 2 strings "
932}
933
934implement {
935 name = " setdocumentfilename " ,
936 actions = document . setfilename ,
937 arguments = { " integer " , " string " }
938}
939
940implement {
941 name = " getdocumentargument " ,
942 actions = { document . getargument , context } ,
943 arguments = " 2 strings "
944}
945
946implement {
947 name = " getdocumentfilename " ,
948 actions = { document . getfilename , context } ,
949 arguments = " integer "
950}
951
952function document . setcommandline ( )
953
954
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: " , " " )
962 if arguments [ k ] = = nil then
963 arguments [ k ] = v
964 end
965 end
966
967
968
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
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
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020 context . setupsystem {
1021 directory = validstring ( arguments . setuppath ) ,
1022 inputfile = inputfile ,
1023 file = validstring ( arguments . result ) ,
1024 random = validstring ( arguments . randomseed ) ,
1025
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
1083end
1084
1085
1086
1087local function apply ( list , action )
1088 if list then
1089 for i = 1 , # list do
1090 action { list [ i ] }
1091 end
1092 end
1093end
1094
1095function document . setmodes ( )
1096 apply ( document . options . ctxfile . modes , context . enablemode )
1097 apply ( document . options . commandline . modes , context . enablemode )
1098end
1099
1100function document . setmodules ( )
1101 apply ( document . options . ctxfile . modules , context . usemodule )
1102 apply ( document . options . commandline . modules , context . usemodule )
1103end
1104
1105function document . setenvironments ( )
1106 apply ( document . options . ctxfile . environments , context . environment )
1107 apply ( document . options . commandline . environments , context . environment )
1108end
1109
1110function document . setfilenames ( )
1111 local initialize = environment . initializefilenames
1112 if initialize then
1113 initialize ( )
1114 else
1115
1116 end
1117end
1118
1119implement { name = " setdocumentcommandline " , actions = document . setcommandline , onlyonce = true }
1120implement { name = " setdocumentmodes " , actions = document . setmodes , onlyonce = true }
1121implement { name = " setdocumentmodules " , actions = document . setmodules , onlyonce = true }
1122implement { name = " setdocumentenvironments " , actions = document . setenvironments , onlyonce = true }
1123implement { name = " setdocumentfilenames " , actions = document . setfilenames , onlyonce = true }
1124
1125do
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
1140 local arguments = document . 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
1163end
1164
1165if 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
1197end
1198
1199implement {
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
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 |