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 job 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 |