Hello, See below...
Le 09/05/2016 21:27, Gavin Smith a écrit : > On 9 May 2016 at 20:21, Gavin Smith <gavinsmith0...@gmail.com> wrote: > >>> I guess that with all those changes, but except for the space that is a >>> deep tex engine limitation, only the Devil could find a valid filename >>> not working. >>> >>> Vincent. >>> > > I was going to say, I don't think it's important to support spaces in > filenames. (texi2dvi "My Manual.texi" won't work, for example.) The > main problem is spaces in higher-level directories, but they shouldn't > be a problem any more now we use absolute paths less. I'd say that > supporting unusual filenames isn't important. There was already > support for tildes (~) in filenames (Debian used them for some > reason), but the other characters are easy to avoid by avoiding using > them in the filename. Nonetheless it's good that you found a way to > support them - it makes texi2dvi slightly more robust for unexpected > circumstances. It's good that much of this code isn't used if the > filename doesn't contain any unusual characters; this reduces the > likelihood of something breaking. I definitely 200% support your point that we should not change the simple \input FILENAME way when there is no need for that. So, I have modified the patch so that the condition to trigger the complex way is that the filename contain TeX special character, previously that condition was that the filename contains non-alphanumeric characters which is far broader. In a nutshell, if the filename contains only alphanumeric or '+' or '-', the new patch will just \input FILENAME, but if the filename contains '%' or '#', then it will use the TeX tricks. I also fixed some comments and added '_' into the list of handled TeX special characters, for consistency with handling also '$'. Modern tex engines seem to already do appropriate catcoding for the math special char ($_^) but this behaviour is unspecified, so good to have this explicitely. Vincent.
Index: texi2dvi =================================================================== --- texi2dvi (revision 7159) +++ texi2dvi (working copy) @@ -905,38 +905,86 @@ fi } +find_egroup_char() +{ + _filename=$1 + shift + while test $# -gt 0; do + case "$_filename" in + *"${1:0:1}"*) + shift;; + *) + echo "$1" + return 0 + ;; + esac + done + return -1 +} + # run_tex - Run TeX as "$tex $in_input", taking care of errors and logs. run_tex () { make_tex_cmd - tex_cmd=`(LC_ALL=C - if (echo "$in_input" | grep [^a-zA-Z0-9/.]) >/dev/null ; then - # If the filename has funny characters, change the TeX category codes of - # some characters within a group, and use \expandafter to input the file - # outside of the group. + _run_tex_in_input="$in_input" + _run_tex_in_input_funnies=`echo "$in_input" | $SED 's![} #$%&^_{~]!!g'` + if test "$_run_tex_in_input_funnies" != "$in_input"; then + # If the filename has funny characters, change the TeX category codes of + # some characters within a group, and use \expandafter to input the file + # outside of the group. - # Make > an end group character, as it's unlikely to appear in - # a filename. - tex_cmd="$tex_cmd '${escape}bgroup${escape}catcode62=2'" - # make letter { } $ # ~ ^ & - for w in 123 125 36 35 126 136 26; do - # TODO: check if letter actually in filename in order - # to simplifiy TeX command line. - tex_cmd="$tex_cmd '${escape}catcode$w=11${escape}relax'" - done - # Set \toks0 to "\input FILENAME\relax" - tex_cmd="$tex_cmd'${escape}toks0${escape}bgroup" - tex_cmd="$tex_cmd${escape}input $in_input${escape}relax>" - tex_cmd="$tex_cmd${escape}expandafter${escape}egroup" - tex_cmd="$tex_cmd${escape}the${escape}toks0${escape}relax'" - else - # In the case of a simple filename, just pass the filename - # with no funny tricks. - tex_cmd="$tex_cmd '${escape}input' '$in_input'" + + + tex_cmd="$tex_cmd '${escape}bgroup'" + + # seek for _run_tex_egroup_char as a character for egroup (catcode 2) + _run_tex_egroup_char= + # make other TeX special characters + for w in '}125' ' 32' '#35' '$36' %37 '&38' ^94 _95 '{123' '~126'; do + case "$_run_tex_in_input" in + *"${w:0:1}"*) + tex_cmd="$tex_cmd '${escape}catcode${w:1}=12${escape}relax'" + ;; + *) + if test -z "$_run_tex_egroup_char" -a "$w" != ' 32'; then + _run_tex_egroup_char="$w" + fi + ;; + esac + done + + # If the previous loop has failed to find an egroup character we + # try a few more, which don't have any special TeX meaning, but + # are unlikely in a file name. This is sure to succeed under MSW + # as > < | and " are forbidden in file names. + if test -z "$_run_tex_egroup_char"; then + _run_tex_egroup_char=`find_egroup_char "$_run_tex_in_input" '>62' '<60' '|124' '/47' '"34'` fi - echo "$tex_cmd")` + if test "$_run_tex_egroup_char" != '}125'; then + tex_cmd="$tex_cmd '${escape}catcode${_run_tex_egroup_char:1}=2${escape}relax'" + fi + + # Some explicit escaping is needed for the when the FILENAME + # contains a ^^XX quadrigram or a simple quote + _run_tex_in_input=`echo "$_run_tex_in_input" | \ +$SED 's!\\^\\^\\([0-9A-F]\\{2\\}\\)!\\\\string^\\\\string^\\1!g; \ +s!\\('"'"'\\+\\)!'"'"'"\\1"'"'"'!g'` + + # Set \toks0 to "\input FILENAME\relax" + tex_cmd="$tex_cmd '${escape}toks0${escape}bgroup" + tex_cmd="$tex_cmd${escape}input' '$_run_tex_in_input' '${escape}relax${_run_tex_egroup_char:0:1}" + tex_cmd="$tex_cmd${escape}expandafter${escape}egroup" + tex_cmd="$tex_cmd${escape}the${escape}toks0${escape}relax'" + else + # Some sh trick is needed in case that the filename contains a simple quote + _run_tex_in_input=`echo "$_run_tex_in_input" | $SED 's!\\('"'"'\\+\\)!'"'"'"\\1"'"'"'!g'` + # In the case of a simple filename, just pass the filename with no + # TeX funny tricks. + tex_cmd="$tex_cmd '${escape}input' '$_run_tex_in_input'" + fi + verbose "$0: Running $tex_cmd ..." if eval "$tex_cmd" >&5; then case $out_lang in