Hello,

Here are some fixes to GRUB (cvs checkout 1999-05-30).
For details see ChangeLog.

* Handle input of '\' correctly.

* Fix some problems with Linux' /sbin/grub.

  With these fixes and I_AM_VERY_BRAVE #defined in grub/asmstub.c I
  successfully booted a Multiboot Kernel from floppy without NATIVE
  grub.

  Next step (after 3 weeks vacation :-) will be a first try on
  Harddisk. 

* Add some code to enable TAB expansion completing unique input text
  for DEVICES & FILE/DIRNAMES.

Patch attached.

Klaus Reichl

-- 
Klaus Reichl                        voice: +43 (1) 27722 / 3884
Alcatel Austria AG/RTPM             fax:   +43 (1) 27722 / 3955
Scheydgasse 41                      inet:  [EMAIL PROTECTED]
A-1210 Wien, Austria/Europe

diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/ChangeLog grub/ChangeLog
--- cvsgrub/ChangeLog   Sun May 23 22:31:54 1999
+++ grub/ChangeLog      Mon May 31 00:44:30 1999
@@ -1,4 +1,8 @@
+1999-05-23  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * docs/.cvsignore: New file. 
+
 1999-05-21  OKUJI Yoshinori  <[EMAIL PROTECTED]>
 
        * docs/TODO: Moved to ...
        * TODO: ... here.
@@ -7,8 +11,35 @@
        * docs/COPYING: Removed.
        * docs/Makefile.am (EXTRA_DIST): Get rid of BUGS.
        * Makefile.am (EXTRA_DIST): Set to BUGS.
        
+1999-05-20  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * grub/disk_io.c (print_a_completion): New function which saves
+       what has been printed to `unique_string' and printf it.
+       (print_completions): Use it.
+       * grub/fsys_ext2fs.c: ditto
+       * grub/fsys_fat.c: ditto
+       * grub/fsys_ffs.c: ditto.
+       * grub/shared.h (print_a_completion): Declare it.
+       * grub/main.c (main): if (hold) add some printfs to show user what
+       to do.
+
+1999-05-18  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * grub/cmdline.c: Add (char *) cast to grub_read.
+       * grub/asmstub.c: Don't try /dev/fd1 under linux, if there is no
+         second floppy drive, the kernel has strange behaviour.
+       Probe 4 (not 2) IDE devices, continue on error, disks may be
+         connected sparse to the controllers.
+       Add code for ENOMEDIUM on `fopen', don't brake the loop if we have
+         this to find e.g. 2nd disk on 2nd controller.
+       Put nwrite under I_AM_VERY_BRAVE to avoid
+         compiler warning.
+       Add prototype for _llseek to avoid compiler warning.
+       Implement some `od' like code under #ifdef DEBUG_BIOSDISK_WRITE
+       Implement a trace wrapper over open under #ifdef DEBUG_OPEN
+       
 1999-05-17  OKUJI Yoshinori  <[EMAIL PROTECTED]>
 
        * acinclude.m4 (grub_ASM_EXT_C): Do not overrun the comman
        shift. Reported by Pavel Roskin <[EMAIL PROTECTED]>.
@@ -51,8 +82,28 @@
        * e2fs_stage1_5/Makefile.am (IMPORTANT_SIZE_LIMIT): Set to 81920.
        * fat_stage1_5/Makefile.am (IMPORTANT_SIZE_LIMIT): Likewise.
        * ffs_stage1_5/Makefile.am (IMPORTANT_SIZE_LIMIT): Set to 7168.
        
+1999-05-08  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * shared_src/disk_io.c (unique): New static to be able to
+       probagate the fact the a completion is unique.
+       (set_device): If user says "(<TAB>" let
+       disk_choice find all disks we have.
+       If user says "([fh][d]TAB" ditto.
+       (print_completions): Show only the disks we have according to the
+       string the user specifies.  If its unique insert the text in users
+       input buffer.
+       (print_completions): If `open_partition' succeeds, add ")/" into 
+       users input buffer.
+
+       * shared_src/char_io.c (get_cmdline): Handle situation where
+       `print_completion' adds something in input cmd line.
+
+1999-05-08  Klaus Reichl  <[EMAIL PROTECTED]>
+
+       * shared_src/stage2.c (get_line_from_config): Fixed handling of '\\'. 
+
 1999-05-03  Gordon Matzigkeit  <[EMAIL PROTECTED]>
 
        From Pavel Roskin:
        * shared_src/shared.h: Redeclare.
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/docs/.cvsignore 
grub/docs/.cvsignore
--- cvsgrub/docs/.cvsignore     Thu Jan  1 01:00:00 1970
+++ grub/docs/.cvsignore        Mon May 31 01:03:04 1999
@@ -0,0 +1,3 @@
+*.info*
+version.texi
+stamp-vti
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/grub/asmstub.c 
grub/grub/asmstub.c
--- cvsgrub/grub/asmstub.c      Mon May 31 00:14:04 1999
+++ grub/grub/asmstub.c Mon May 31 00:47:42 1999
@@ -17,8 +17,16 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* Some debugging hooks */
+
+/* define for a trace of device opens */
+#define DEBUG_OPEN
+
+/* set this for debugging BIOSDISK_WRITE */
+/* #define DEBUG_BIOSDISK_WRITE */
+
 /* Try to use glibc's transparant LFS support. */
 #define _LARGEFILE_SOURCE 1
 
 /* Simulator entry point. */
@@ -37,8 +45,9 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <time.h>
 #include <errno.h>
+#include <string.h>
 
 #ifdef __linux__
 # include <sys/ioctl.h>                /* ioctl */
 # include <linux/hdreg.h>      /* HDIO_GETGEO */
@@ -131,26 +140,53 @@
   memset (device_map, 0, NUM_DISKS * sizeof (char *));
 
   /* Floppies.  */
   device_map[0] = strdup ("/dev/fd0");
+#ifndef __linux__
+  /* FIXME: leave linux out for now /dev/fd1 blocks for long time
+     if there is no second floppy ? */
   device_map[1] = strdup ("/dev/fd1");
+#endif
 
   /* IDE disks.  */
-  for (i = 0; i < 2; i++)
+  for (i = 0; i < 4; i++)
     {
       char name[10];
       FILE *fp;
       char buf[512];
+      
 #ifdef __linux__
       char unit = 'a' + i;
 #else
       char unit = '0' + i;
 #endif
 
       sprintf (name, "/dev/hd%c", unit);
       fp = fopen (name, "r");
-      if (! fp)
-       break;
+      if (!fp)
+       {
+         switch (errno)
+           {
+#ifdef ENOMEDIUM
+           case ENOMEDIUM:
+#if 0
+/* At the moment, this finds only CDROMs, which can't be read anyway,
+   so leave it out.
+   Code should be reactivated if `removable disks' and CDROMs are supported */
+             /* register it, it may be inserted */
+             device_map[i + 0x80] = strdup (name);
+#endif
+             break;
+#endif /* ENOMEDIUM */
+           default:
+             /* break case and leave */
+             break;
+           }
+         /* continue: there may be more disks sitting sparse on the
+            controllers */
+         continue;
+       }
+
       /* Attempt to read the first sector.  */
       if (fread (buf, 1, 512, fp) != 512)
        break;
 
@@ -456,8 +492,36 @@
     }
 #endif
 }
 
+#ifdef DEBUG_OPEN
+/* Wrapper for open: trace for the user what we do */
+static int
+asmstub_open (const char * dev, int flags)
+{
+  int res;
+  int nflags = flags;
+  int dont_know_flags = 0;
+
+  fprintf (stderr, "\r\ngrub: Trying to open (%s, %s",
+          dev, (((nflags & 3) == O_RDWR) ? (nflags &= ~O_RDWR, "O_RDWR")
+                : ((nflags & 3) == O_RDONLY) ? "O_RDONLY"
+                : ""));
+  fprintf (stderr, "%s", (nflags & O_SYNC ? (nflags &= ~O_SYNC, "|O_SYNC")
+                         : (nflags == 0) ? ""
+                         : (dont_know_flags = 1, "")));
+  if (dont_know_flags || nflags)
+    fprintf (stderr, "|%08x", nflags);
+  fprintf (stderr, ") = ");
+
+  res = open (dev, flags);
+  fprintf (stderr, "%d", res);
+  if (res == -1)
+    fprintf (stderr, " (errno = %d - %s)", errno, strerror (errno));
+  return res;
+}
+#define open asmstub_open
+#endif /* DEBUG_OPEN */
 
 /* Low-level disk I/O.  Our stubbed version just returns a file
    descriptor, not the actual geometry. */
 int
@@ -467,8 +531,12 @@
      then severely abuse the GEOMETRY->flags field to pass a file
      descriptor to biosdisk.  Thank God nobody's looking at this comment,
      or my reputation would be ruined. --Gord */
 
+  if (disks[drive].flags == -1)
+    /* some earlier call set this guy to error */
+    return -1;
+
   /* See if we have a cached device. */
   if (! disks[drive].flags)
     {
       /* The unpartitioned device name: /dev/XdX */
@@ -479,17 +547,48 @@
        return -1;
 
       /* Open read/write, or read-only if that failed. */
       disks[drive].flags = open (devname, O_RDWR);
-      if (! disks[drive].flags)
-       disks[drive].flags = open (devname, O_RDONLY);
+      if (disks[drive].flags == -1)
+       {
+         if ((errno == EACCES || errno == EROFS))
+           {
+             disks[drive].flags = open (devname, O_RDONLY);
+             if (disks[drive].flags == -1)
+               {
+                 /* code below assumes == 0 */
+                 disks[drive].flags = 0;
+               }
+           }
+         else if (errno == ENODEV)
+           {
+             /* this is OK, leave -1 in */ 
+             return -1;
+           }
+         else if  (errno == ENXIO)
+           {
+             /* maybe a removable volume - like a floppy */
+             disks[drive].flags = 0;
+             return -1;
+           }
+         else
+           {
+             /* show user what else can be wrong and exit */
+             fprintf (stderr, "get_diskinfo: Can't open %s: %s\n", 
+                      devname, strerror (errno));
+             exit (1);
+           }
+       }
 
-      /* Attempt to read the first sector.  */
-      if (read (disks[drive].flags, buf, 512) != 512)
+      if (disks[drive].flags)
        {
-         close (disks[drive].flags);
-         disks[drive].flags = 0;
-         return -1;
+         /* Attempt to read the first sector.  */
+         if (read (disks[drive].flags, buf, 512) != 512)
+           {
+             close (disks[drive].flags);
+             disks[drive].flags = 0;
+             return -1;
+           }
        }
 
       if (disks[drive].flags)
        {
@@ -540,8 +639,33 @@
   *geometry = disks[drive];
   return 0;
 }
 
+#ifdef DEBUG_BIOSDISK_WRITE
+/* like od -v -A x -x */
+static void
+od (unsigned char * p, int size)
+{
+  unsigned addr = 0;
+  int    i;
+
+  while (size)
+    {
+      fprintf (stderr, "%06x ", addr);
+      for (i = 0; i < 8; i++)
+       {
+         fprintf (stderr, "%04x%s", 
+                  *((unsigned short *) p),
+                  ((i == 7) ? "" : " "));
+         p += sizeof (unsigned short);
+         size -= sizeof (unsigned short);
+       }
+      fprintf (stderr, "\n\r");
+    }
+  fprintf (stderr, "%06x\n", addr);
+}
+#endif /* DEBUG_BIOSDISK_WRITE */
+
 /* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
    error occurs, otherwise return LEN.  */
 static int
 nread (int fd, char *buf, size_t len)
@@ -566,8 +690,9 @@
   
   return size;
 }
 
+#ifdef I_AM_VERY_BRAVE
 /* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
    error occurs, otherwise return LEN.  */
 static int
 nwrite (int fd, char *buf, size_t len)
@@ -591,8 +716,9 @@
     }
   
   return size;
 }
+#endif /* I_AM_VERY_BRAVE */
 
 int
 biosdisk (int subfunc, int drive, struct geometry *geometry,
          int sector, int nsec, int segment)
@@ -608,8 +734,9 @@
 #ifdef __linux__
   /* FIXME: only use this section if libc doesn't have large file support */
   {
     loff_t offset, result;
+    static int _llseek (uint fd, ulong hi, ulong lo, loff_t * res, uint wh);
     _syscall5 (int, _llseek, uint, fd, ulong, hi, ulong, lo,
               loff_t *, res, uint, wh);
 
     offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
@@ -636,8 +763,20 @@
     case BIOSDISK_WRITE:
       if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
        return -1;
       break;
+#endif
+#ifdef DEBUG_BIOSDISK_WRITE
+    case BIOSDISK_WRITE:
+      fprintf (stderr, "\r\n");
+      fprintf (stderr, "grub: Don't know how to BIOSDISK_WRITE yet\r\n");
+      fprintf (stderr, "grub;   drive: %d, sector: %d\r\n", drive, sector);
+      fprintf (stderr, "grub: od -v -A x -x %08x\r\n", segment << 4);
+      od ((unsigned char *) (segment << 4), nsec * 512);
+      fprintf (stderr, "grub: Press a key to continue\r");
+      getkey ();
+      /* fake things did OK */
+      fprintf (stderr, "\r\ngrub: Fake OK\r\n");
 #endif
     default:
       grub_printf ("unknown subfunc %d\n", subfunc);
       break;
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/grub/main.c grub/grub/main.c
--- cvsgrub/grub/main.c Sat May  8 21:27:27 1999
+++ grub/grub/main.c    Thu May 20 21:21:05 1999
@@ -172,10 +172,19 @@
     }
   while (c != EOF);
 
   /* Wait until the HOLD variable is cleared by an attached debugger. */
-  while (hold)
-    sleep (1);
+  if (hold)
+    {
+      printf ("Use:\n"
+             "  gdb %s\n"
+             "  attach %d\n", program_name, getpid ());
+      while (hold)
+       {
+         sleep (1);
+       }
+    }
+  
 
   /* Transfer control to the stage2 simulator. */
   exit (grub_stage2 ());
 }
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/char_io.c 
grub/shared_src/char_io.c
--- cvsgrub/shared_src/char_io.c        Tue May 18 20:37:15 1999
+++ grub/shared_src/char_io.c   Tue May 18 22:19:06 1999
@@ -275,8 +275,12 @@
                if (i <= j)
                  i = j + 1;
                /* print possible completions */
                print_completions (cmdline + i);
+               /* if somebody in print_completions has added something, 
+                  account for that */
+               while (cmdline[lpos])
+                 lpos++, llen_old++;
              }
            else if (commands)
              printf (commands);
            else
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/cmdline.c 
grub/shared_src/cmdline.c
--- cvsgrub/shared_src/cmdline.c        Tue May 18 20:37:15 1999
+++ grub/shared_src/cmdline.c   Thu May 20 22:45:46 1999
@@ -465,9 +465,9 @@
                          while (*(str++));      /* find string */
                          while ((*(str++) = *(ptr++)) != 0);    /* do copy */
                        }
 
-                     grub_read (RAW_ADDR (0x100000), -1);
+                     grub_read ((char *) RAW_ADDR (0x100000), -1);
 
                      buf_track = -1;
 
                      if (!errnum
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/disk_io.c 
grub/shared_src/disk_io.c
--- cvsgrub/shared_src/disk_io.c        Tue May 18 20:37:16 1999
+++ grub/shared_src/disk_io.c   Fri May 21 00:18:41 1999
@@ -573,8 +573,12 @@
 
 
 /* XX used for device completion in 'set_device' and 'print_completions' */
 static int incomplete, disk_choice;
+#ifndef STAGE1_5
+static int unique;
+static char unique_string[128]; /* XXX Don't know yet */ 
+#endif
 static enum
   {
     PART_UNSPECIFIED = 0,
     PART_DISK,
@@ -594,14 +598,33 @@
   part_choice = PART_UNSPECIFIED;
   current_drive = saved_drive;
   current_partition = 0xFFFFFF;
 
+  if (*device == '(' && !*(device + 1))
+    /* user has given '(' only, let disk_choice handle what disks we have */
+    return device + 1;
+
   if (*device == '(' && *(++device))
     {
       if (*device != ',' && *device != ')')
        {
          char ch = *device;
 
+         if (*device == 'f' || *device == 'h')
+           {
+             /* user has given '([fh]', check for resp. add 'd' and 
+                let disk_choice handle what disks we have */
+             if (!*(device + 1))
+               {
+                 device++;
+                 *device++ = 'd';
+                 *device = '\0';
+                 return device;
+               }
+             else if (*(device + 1) == 'd' && !*(device + 2))
+               return device + 2;
+           }
+
          if ((*device == 'f' || *device == 'h')
              && (device += 2, (*(device - 1) != 'd')))
            errnum = ERR_NUMBER_PARSING;
 
@@ -879,8 +902,37 @@
 #endif /* STAGE1_5 */
 
 #ifndef STAGE1_5
 /*
+ *  print_a_completion saves what has been printed to unique_string
+ *  printf's with a leading ' '
+ */
+
+void
+print_a_completion (char *filename)
+{
+  char * f = filename;
+  char * u = unique_string;
+
+  if (! *u && unique == 0)
+    {
+      /* copy first string, this is unique */
+      while ((*u++ = *f++))
+       ;
+    }
+  else
+    {
+      while (*u && (*u == *f))
+       u++, f++;
+      /* mismatch, strip it */
+      *u = '\0';
+    }
+  unique++;
+
+  printf (" %s", filename);
+}
+
+/*
  *  This lists the possible completions of a device string, filename, or
  *  any sane combination of the two.
  */
 
@@ -888,8 +940,11 @@
 print_completions (char *filename)
 {
   char *ptr = filename;
 
+  *unique_string = '\0';
+  unique = 0;
+
   if (*filename == '/' || (ptr = set_device (filename)) || incomplete)
     {
       errnum = 0;
 
@@ -902,19 +957,47 @@
              struct geometry geom;
 
              printf (" Possible disks are: ");
 
-             for (i = 0; i < 2; i++)
+             for (i = (ptr && (*(ptr-2) == 'h' && *(ptr-1) == 'd') ? 1 : 0); 
+                  i < (ptr && (*(ptr-2) == 'f' && *(ptr-1) == 'd') ? 1 : 2); 
+                  i++)
                {
                  for (j = 0; j < 8; j++)
                    {
                      disk_no = (i * 0x80) + j;
                      if ((disk_choice || disk_no == current_drive) &&
                          ! get_diskinfo (disk_no, &geom))
-                       printf (" %cd%d", (i ? 'h' : 'f'), j);
+                       {
+                         char dev_name [4];
+
+                         dev_name[0] = (i ? 'h' : 'f');
+                         dev_name[1] = 'd';
+                         dev_name[2] = '0' + j;
+                         dev_name[3] = '\0';
+                         print_a_completion (dev_name);
+                       }
                    }
                }
 
+             ptr = filename;
+             while (*ptr != '(')
+               ptr--;
+             ptr++;
+             {
+               char *u = unique_string;
+               while ((*ptr++ = *u++))
+                 ;
+               ptr--;
+             }
+             ptr--;
+             if ((*(ptr - 2) == 'h') && (*(ptr - 1) == 'd')
+                 && ('0' <= *ptr && *ptr <= '8'))
+               *(ptr + 1) = ',', *(ptr + 2) = '\0';
+             if ((*(ptr - 2) == 'f') && (*(ptr - 1) == 'd')
+                 && ('0' <= *ptr && *ptr <= '8'))
+               *(ptr + 1) = ')', *(ptr + 2) = '\0';
+
              putchar ('\n');
            }
          else
            {
@@ -926,17 +1009,42 @@
                }
              else
                {
                  if (open_partition ())
-                   check_and_print_mount ();
+                   {
+                     check_and_print_mount ();
+                     /* XXX: Can talk about linux only, do we need
+                        to know about syntax here? */
+                     ptr = filename;
+                     while (*ptr)
+                       ptr++;
+                     if (*(ptr - 1) != ')')
+                       *ptr++ = ')';
+                     *ptr++ = '/';
+                     *ptr = '\0';
+                   }
                }
            }
        }
       else if (*ptr == '/')
        {
          /* filename completions */
          printf (" Possible files are:");
          dir (filename);
+         {
+           char *u = unique_string;
+
+           if (*u)
+             {
+               while (*ptr++)
+                 ;
+               while (*ptr != '/')
+                 ptr--;
+               ptr++;
+               while ((*ptr++ = *u++))
+                 ;
+             }
+         }
        }
       else
        errnum = ERR_BAD_FILENAME;
     }
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/fsys_ext2fs.c 
grub/shared_src/fsys_ext2fs.c
--- cvsgrub/shared_src/fsys_ext2fs.c    Tue May 18 20:37:16 1999
+++ grub/shared_src/fsys_ext2fs.c       Fri May 21 00:00:08 1999
@@ -756,9 +756,9 @@
                  && (!*dirname || str_chk <= 0))
                {
                  if (print_possibilities > 0)
                    print_possibilities = -print_possibilities;
-                 printf ("  %s", dp->name);
+                 print_a_completion (dp->name);
                }
 # endif
 
              dp->name[dp->name_len] = saved_c;
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/fsys_fat.c 
grub/shared_src/fsys_fat.c
--- cvsgrub/shared_src/fsys_fat.c       Mon Mar 15 03:08:09 1999
+++ grub/shared_src/fsys_fat.c  Fri May 21 00:00:08 1999
@@ -239,9 +239,9 @@
          && (!*dirname || substring (dirname, filename) <= 0))
        {
          if (print_possibilities > 0)
            print_possibilities = -print_possibilities;
-         printf ("  %s", filename);
+         print_a_completion (filename);
        }
 # endif /* STAGE1_5 */
     }
   while (substring (dirname, filename) != 0 ||
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/fsys_ffs.c 
grub/shared_src/fsys_ffs.c
--- cvsgrub/shared_src/fsys_ffs.c       Sun Mar 28 00:35:35 1999
+++ grub/shared_src/fsys_ffs.c  Fri May 21 00:00:01 1999
@@ -251,9 +251,9 @@
        {
          if (print_possibilities > 0)
            print_possibilities = -print_possibilities;
 
-         printf ("  %s", dp->d_name);
+         print_a_completion (dp->d_name);
        }
 #endif /* STAGE1_5 */
     }
   while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/shared.h 
grub/shared_src/shared.h
--- cvsgrub/shared_src/shared.h Sat May  8 21:27:27 1999
+++ grub/shared_src/shared.h    Thu May 20 22:45:30 1999
@@ -511,8 +511,9 @@
 /* Display statistics on the current active device. */
 void print_fsys_type (void);
 
 /* Display device and filename completions. */
+void print_a_completion (char *filename);
 void print_completions (char *filename);
 
 /* Copies the current partition data to the desired address. */
 void copy_current_part_entry (char *buf);
diff -u4 -r --new-file --exclude-from diff.exclude cvsgrub/shared_src/stage2.c 
grub/shared_src/stage2.c
--- cvsgrub/shared_src/stage2.c Sun May  2 23:30:41 1999
+++ grub/shared_src/stage2.c    Tue May 18 22:25:51 1999
@@ -469,9 +469,9 @@
 
   while (grub_read (&c, 1))
     {
       /* translate characters first! */
-      if (c == '\\')
+      if ((c == '\\') && !literal)
        {
          literal = 1;
          continue;
        }

Reply via email to