From 85b7bc695629926641c7cb752fd478adfdf374f3 Mon Sep 17 00:00:00 2001 From: Marius Date: Sun, 4 Jul 2010 15:32:09 +0300 Subject: stable 2010-05-24 13:10 --- tex/context/base/supp-fil.mkiv | 464 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 464 insertions(+) create mode 100644 tex/context/base/supp-fil.mkiv (limited to 'tex/context/base/supp-fil.mkiv') diff --git a/tex/context/base/supp-fil.mkiv b/tex/context/base/supp-fil.mkiv new file mode 100644 index 000000000..872612eab --- /dev/null +++ b/tex/context/base/supp-fil.mkiv @@ -0,0 +1,464 @@ +%D \module +%D [ file=supp-fil, +%D version=1995.10.10, +%D title=\CONTEXT\ Support Macros, +%D subtitle=Files, +%D author=Hans Hagen, +%D date=\currentdate, +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] +%C +%C This module is part of the \CONTEXT\ macro||package and is +%C therefore copyrighted by \PRAGMA. See mreadme.pdf for +%C details. + +%D \TEX\ operates on files, so one wouldn't wonder that there +%D is a separate module for file support. In \CONTEXT\ files +%D are used for several purposes: +%D +%D \startitemize[packed] +%D \item general textual input +%D \item logging status information +%D \item saving registers, lists and references +%D \item buffering defered textual input +%D \stopitemize +%D +%D When dealing with files we can load them as a whole, using +%D the \type{\input} primitive or load them on a line||by||line +%D basis, using \type{\read}. Writing is always done line by +%D line, using \type{\write}. + +\writestatus{loading}{ConTeXt Support Macros / Files} + +\registerctxluafile{supp-fil}{1.001} + +\unprotect + +\ifx\undefined\f!pathseparator + \def\f!pathseparator{/} + \def\f!currentpath {.} + \def\f!parentpath {..} +\fi + +% \def\openinputfile #1#2{\immediate\openin #1="#2"\relax} \def\closeinputfile #1{\immediate\closein #1} +% \def\openoutputfile#1#2{\immediate\openout#1="#2"\relax} \def\closeoutputfile#1{\immediate\closeout#1} + +\def\openinputfile #1#2{\immediate\openin #1=#2\relax} \def\closeinputfile #1{\immediate\closein #1} +\def\openoutputfile#1#2{\immediate\openout#1=#2\relax} \def\closeoutputfile#1{\immediate\closeout#1} + +%D \macros +%D {pushendofline,popendofline} +%D +%D When we are loading files in the middle of the typesetting +%D process, for instance when we load references, we have to be +%D sure that the reading process does not generate so called +%D 'spurious spaces'. This can be prevented by assigning the +%D line ending character the \CATCODE\ comment. This is +%D accomplished by +%D +%D \starttyping +%D \pushendofline +%D ... reading ... +%D \popendofline +%D \stoptyping +%D +%D Just to be sure, we save the current meaning of \type{^^M} +%D in \type{\poppedendofline}. + +\newcount \endoflinelevel + +\ifx\newlinecode\undefined \chardef\newlinecode=`\^^M \fi + +\def\pushendofline + {\advance\endoflinelevel\plusone + \expandafter\chardef\csname :eol:\number\endoflinelevel\endcsname\catcode\newlinecode + \catcode\newlinecode\@@comment\relax} + +\def\popendofline + {\catcode\newlinecode\csname :eol:\number\endoflinelevel\endcsname + \advance\endoflinelevel\minusone} + +\def\restoreendofline + {\catcode\newlinecode\@@endofline} + +%D \macros +%D {scratchread, scratchwrite} +%D +%D We define a scratch file for reading. Keep in mind that +%D the number of files is limited to~16, so use this one when +%D possible. We also define a scratch output file. + +\ifx\undefined\scratchread \newread \scratchread \fi +\ifx\undefined\scratchwrite \newwrite\scratchwrite \fi + +%D \macros +%D {unlinkfile} +%D +%D Sometimes we want to make sure a file is deleted, so here +%D is a macro that does the job. It's named after the \PERL\ +%D one. + +\def\unlinkfile#1{\ctxlua{os.remove([[#1]])}} + +%D \macros +%D {writeln} +%D +%D This saves a few tokens: + +\def\writeln#1{\write#1{}} + +\def\doiffileexistselse #1{\ctxlua{support.doiffileexistelse([[#1]])}} +\def\lastfoundexistingfile {\ctxlua{support.lastexistingfile()}} + +%D \macros +%D {doprocessfile,fileline,fileprocessedtrue,dofinishfile} +%D +%D The next macro offers a framework for processing files on a +%D line by line basis. +%D +%D \starttyping +%D \doprocessfile \identifier {name} \action +%D \stoptyping +%D +%D The first argument can for instance be \type{\scratchread}. +%D The action must do something with \type{\fileline}, which +%D holds the current line. One can halfway step out using +%D \type{\dofinishfile} and ise \type{\iffileprocessed} to +%D see if indeed some content was found. + +\newif\iffileprocessed + +\let\fileline\empty + +\def\doprocessfile#1#2#3% + {\openinputfile{#1}{#2}% + \ifeof#1% + \fileprocessedfalse + \closeinputfile#1% + \else + \fileprocessedtrue + \gdef\dofinishfile + {\closeinputfile#1% + \global\let\doprocessline\relax}% + \gdef\doprocessline + {\ifeof#1% + \expandafter\dofinishfile + \else + \global\read#1 to \fileline + #3\relax + \expandafter\doprocessline + \fi}% + \expandafter\doprocessline + \fi} + +%D \macros +%D {pathplusfile,assignfullfilename,sanitizefilename} +%D +%D Use \type{\pathplusfile} to compose a full file name, like +%D in: +%D +%D \starttyping +%D \pathplusfile{path}{file} +%D \stoptyping +%D +%D By default, this expands into {\tt \pathplusfile{path}{file}}. + +\def\pathplusfile#1#2{#1\f!pathseparator#2} + +%D This one constructs a filename from a (possible empty) +%D path and filename. + +\def\assignfullfilename#1#2\to#3% + {\doifelsenothing{#1} + {\edef#3{#2}} + {\edef#3{#1\f!pathseparator#2}}} + +\def\sanitizefilename#1\to#2{\edef#2{\ctxlua{support.thesanitizedfilename([[#1]])}}} + +%D NEW: + +\chardef\kindoffile=0 % 0=normal 1=full path spec (or http) / set at the lua end + +\def\checkfilename#1{\ctxlua{support.checkfilename([[#1]])}} + +%D \macros +%D {input, normalinput} +%D +%D Sometimes we run into troubles when \type {\input} wants to get +%D expanded, e.g. in a \type {\write} (which happens in the metafun +%D manual when we permit long MP lines). So, instead of fixing that, +%D we go for a redefinition of \type {\input}. Of course it's better +%D to use \type {\readfile} or \type {\processfile}. + +\unexpanded\def\input{\normalinput} + +\def\inputgivenfile#1{\normalinput"#1"\relax} + +%D \macros +%D {readfile,ReadFile} +%D +%D One cannot be sure if a file exists. When no file can be +%D found, the \type{\input} primitive gives an error message +%D and switches to interactive mode. The macro \type{\readfile} +%D takes care of non||existing files. This macro has two faces. +%D +%D \starttyping +%D \ReadFile {filename} +%D \readfile {filename} {before loading} {not found} +%D \stoptyping +%D +%D Many \TEX\ implementations have laid out some strategy for +%D locating files. This can lead to unexpected results, +%D especially when one loads files that are not found in the +%D current directory. Let's give an example of this. In +%D \CONTEXT\ illustrations can be defined in an external file. +%D The resizing macro first looks if an illustration is defined +%D in the local definitions file. When no such file is found, +%D it searches for a global file and when this file is not +%D found either, the illustration itself is scanned for +%D dimensions. One can imagine what happens if an adapted, +%D localy stored illustration, is scaled according to +%D dimensions stored somewhere else. +%D +%D When some \TEX\ implementation starts looking for a file, it +%D normally first looks in the current directory. When no file +%D is found, \TEX\ starts searching on the path where format +%D and|/|or style files are stored. Depending on the implementation +%D this can considerably slow down processing speed. +%D +%D In \CONTEXT, we support a project||wise ordening of files. +%D In such an approach it seems feasible to store common files +%D in a lower directory. When for instance searching for a +%D general layout file, we therefore have to backtrack. +%D +%D These three considerations have lead to a more advanced +%D approach for loading files. +%D +%D We first present an earlier implementation of +%D \type{\readfile}. This command backtracks parent +%D directories, upto a predefined level. Users can change this +%D level (on the commandline using a directive); we default to~3. +%D +%D We use \type{\normalinput} instead of \type{\input} +%D because we want to be able to redefine the original +%D \type{\input} when needed, for instance when loading third +%D party libraries. + +\newevery \everybeforereadfile \EveryBeforeReadFile +\newevery \everyafterreadfile \EveryAfterReadFile + +\let \everyreadfile \everybeforereadfile + +\def\maxreadlevel{\ctxlua{commands.maxreadlevel()}} + +% We need to postpone loading, else we got frozen type-* files and so when +% a format is generated on a source path. + +\def\doreadfile#1#2#3% protocol path filename true false + {\edef\readfilename{\ctxlua{support.doreadfile("#1","#2","#3")}}% + \ifx\readfilename\empty + \expandafter\doreadfilenop + \else + \expandafter\doreadfileyes + \fi} + +\long\def\doreadfileyes#1#2% + {#1\relax + \the\everybeforereadfile + \relax\inputgivenfile\readfilename\relax + \the\everyafterreadfile} + +\long\def\doreadfilenop#1#2% + {#2} + +%D \macros +%D {readjobfile,readlocfile,readsysfile, +%D readfixfile,readsetfile} +%D +%D This implementation honnors the third situation, but we +%D still can get unwanted files loaded and/or can get involved +%D in extensive searching. +%D +%D Due to different needs, we decided to offer four alternative +%D loading commands. With \type{\readjobfile} we load a local +%D file and do no backtracking, while \type{\readlocfile} +%D backtracks~\number\maxreadlevel\ directories, including the current +%D one. +%D +%D System files can be anywhere and therefore +%D \type{\readsysfile} is not bound to the current directory +%D and obeys the \TEX\ implementation. +%D +%D Of the last two, \type{\readfixfile} searches on the +%D directory specified and backtracks too, while +%D \type{\readsetfile} does only search on the specified path. +%D +%D The most liberal is \type {\readfile}. + +\unexpanded\def\readjobfile #1{\doreadfile{job} {.}{#1}} % current path, no backtracking +\unexpanded\def\readlocfile #1{\doreadfile{loc} {.}{#1}} % current path, backtracking +\unexpanded\def\readsysfile #1{\doreadfile{sys} {.}{#1}} % current path, obeys tex search +\unexpanded\def\readfixfile#1#2{\doreadfile{fix}{#1}{#2}} % specified path, backtracking +\unexpanded\def\readsetfile#1#2{\doreadfile{set}{#1}{#2}} % specified path, no backtracking +\unexpanded\def\readfile #1{\doreadfile{any} {.}{#1}} +\unexpanded\def\ReadFile #1{\doreadfile{any} {.}{#1}\donothing\donothing} + +%D So now we've got ourselves five file loading commands: +%D +%D \starttyping +%D \readfile {filename} {before loading} {not found} +%D +%D \readjobfile {filename} {before loading} {not found} +%D \readlocfile {filename} {before loading} {not found} +%D \readfixfile {filename} {before loading} {not found} +%D \readsysfile {directory} {filename} {before loading} {not found} +%D \stoptyping + +\def\readtexfile#1#2#3% + {\pushcatcodetable \catcodetable \ctxcatcodes + \readfile{#1}{#2}{#3}% + \popcatcodetable} + +\def\readxmlfile#1#2#3% + {\pushcatcodetable \catcodetable \xmlcatcodes + \readfile{#1}{#2}{#3}% + \popcatcodetable} + +%D \macros +%D {doiffileelse,doiflocfileelse} +%D +%D The next alternative only looks if a file is present. No +%D loading is done. This one obeys the standard \TEX\ +%D implementation method. +%D +%D \starttyping +%D \doiffileelse {filename} {found} {not found} +%D \stoptyping +%D +%D \starttyping +%D \doiflocfileelse {filename} {before loading} {not found} +%D \stoptyping + +\def\doiffileelse {\doiffileexistselse} +\def\doiffile #1{\doiffileexistselse{#1}\firstofoneargument\gobbleoneargument} +\def\doifnotfile #1{\doiffileexistselse{#1}\gobbleoneargument\firstofoneargument} + +\def\doiflocfileelse#1% + {\makelocreadfilename{#1}% + \doiffileelse\readfilename} + +\def\makelocreadfilename#1% + {\sanitizefilename#1\to\readfilename + \checkfilename\readfilename + \ifcase\kindoffile + \edef\readfilename{\pathplusfile\f!currentpath{#1}}% + \fi} + +%D \macros +%D {doonlyonce, doinputonce, doendinputonce} +%D +%D Especially macropackages need only be loaded once. +%D Repetitive loading not only costs time, relocating registers +%D often leads to abortion of the processing because \TEX's +%D capacity is limited. One can prevent multiple execution and +%D loading by using one of both: +%D +%D \starttyping +%D \doonlyonce{actions} +%D \doinputonce{filename} +%D \doendinputonce{filename} +%D \stoptyping +%D +%D This command obeys the standard method for locating files. + +\long\def\doonlyonce#1% + {\doifundefinedelse{@@@#1@@@} + {\letgvalue{@@@#1@@@}\empty + \firstofoneargument} + {\gobbleoneargument}} + +\def\doinputonce#1% + {\doonlyonce{#1}{\doiffileelse{#1}{\inputgivenfile{#1}}\donothing}} + +\def\doendinputonce#1% + {\doifdefined{@@@#1@@@}\endinput} + +\def\forgetdoingonce#1% + {\global\letbeundefined{@@@#1@@@}} + +%D \macros +%D {doifparentfileelse} +%D +%D The test \type{\doifelse{\jobname}{filename}} does not give +%D the desired result, simply because \type{\jobname} expands +%D to characters with \CATCODE~12, while the characters in +%D \type{filename} have \CATCODE~11. So we can better use: +%D +%D \starttyping +%D \doifparentfileelse{filename}{yes}{no} +%D \stoptyping +%D +%D Since \TEXEXEC\ (and thereby \CONTEXT) supports renaming of +%D the outputfile, we also need to check on that alternative +%D name. + +\ifx\outputfilename\undefined \def\outputfilename{\jobname} \fi + +\def\doifparentfileelse#1{\ctxlua{support.doifparentfileelse([[#1]])}} + +\newcount\readingfilelevel + +%D We need to redo this: catcode sets and such + +\newtoks \everystartreadingfile +\newtoks \everystopreadingfile + +\unexpanded\def\startreadingfile% beter een every en \setnormalcatcodes + {\global\advance\readingfilelevel\plusone + \the\everystartreadingfile + \beginrestorecatcodes + \setcatcodetable\prtcatcodes} + +\unexpanded\def\stopreadingfile + {\endrestorecatcodes + \the\everystopreadingfile + \global\advance\readingfilelevel\minusone} + +%D \macros +%D {splitfilename} +%D +%D I should have made this one sooner. This macro was first needed when +%D ran into graphic with a period in the pathpart. +%D +%D \startbuffer +%D \def\showfilesplit +%D {\bgroup \tttf +%D \hbox{(full: \splitofffull)}\space +%D \hbox{(path: \splitoffpath)}\space +%D \hbox{(base: \splitoffbase)}\space +%D \hbox{(name: \splitoffname)}\space +%D \hbox{(type: \splitofftype)}\space +%D \egroup} +%D +%D \splitfilename{c:/aa/bb/cc/dd.ee.ff} \showfilesplit \endgraf +%D \splitfilename{c:/aa/bb/cc/dd.ee} \showfilesplit \endgraf +%D \splitfilename{c:/aa/bb/cc/dd} \showfilesplit \endgraf +%D +%D \splitfilename{dd.ee.ff} \showfilesplit \endgraf +%D \splitfilename{dd.ee} \showfilesplit \endgraf +%D \splitfilename{dd} \showfilesplit \endgraf +%D \stopbuffer +%D +%D \start \typebuffer \getbuffer \stop + +\def\splitoffroot{.} \chardef\splitoffkind\zerocount + +\let\splitofffull\empty +\let\splitoffpath\empty +\let\splitoffbase\empty +\let\splitoffname\empty +\let\splitofftype\empty + +\def\splitfilename#1{\ctxlua{support.splitfilename([[#1]])}} +\def\splitfiletype#1{\ctxlua{support.splitfiletype([[#1]])}} + +\protect \endinput -- cgit v1.2.3