Hello Gavin, Answering to myself: I had been a bit too hasty, patch #7 sent preivously was working properly, but the naming of variable _run_tex_in_input_funnies was not corresponding any longer to its content, so I have slightly modified the code for it to have the same meaning as before (as in patch #6).
Vincent. >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 -n "$_run_tex_in_input_funnies" ; 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