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

Reply via email to