/[grub]/grub2/kern/misc.c
ViewVC logotype

Diff of /grub2/kern/misc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.23 by okuji, Sun Aug 21 07:22:51 2005 UTC revision 1.24 by marco_g, Mon Oct 24 10:23:46 2005 UTC
# Line 1  Line 1 
1  /* misc.c - definitions of misc functions */  /* misc.c - definitions of misc functions */
2  /*  /*
3   *  GRUB  --  GRand Unified Bootloader   *  GRUB  --  GRand Unified Bootloader
4   *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.   *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005  Free Software Foundation, Inc.
5   *   *
6   *  GRUB is free software; you can redistribute it and/or modify   *  GRUB is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by   *  it under the terms of the GNU General Public License as published by
# Line 874  grub_utf8_to_ucs4 (grub_uint32_t *dest, Line 874  grub_utf8_to_ucs4 (grub_uint32_t *dest,
874    
875    return p - dest;    return p - dest;
876  }  }
   
 grub_err_t  
 grub_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **),  
                     int *argc, char ***argv)  
 {  
   /* XXX: Fixed size buffer, perhaps this buffer should be dynamically  
      allocated.  */  
   char buffer[1024];  
   char *bp = buffer;  
   char *rd = (char *) cmdline;  
   char unputbuf;  
   int unput = 0;  
   char *args;  
   int i;  
   
   auto char getchar (void);  
   auto void unputc (char c);  
   auto void getenvvar (void);  
   auto int getarg (void);  
   
   /* Get one character from the commandline.  If the caller reads  
      beyond the end of the string a new line will be read.  This  
      function will not chech for errors, the caller has to check for  
      grub_errno.  */  
   char getchar (void)  
     {  
       int c;  
       if (unput)  
         {  
           unput = 0;  
           return unputbuf;  
         }  
   
       if (! rd)  
         {  
           getline (&rd);  
           /* Error is ignored here, the caller will check for this  
              when it reads beyond the EOL.  */  
           c = *(rd)++;  
           return c;  
         }  
   
       c = *(rd)++;  
       if (! c)  
         {  
           rd = 0;  
           return '\n';  
         }  
   
       return c;  
     }  
   
   void unputc (char c)  
     {  
       unputbuf = c;  
       unput = 1;  
     }  
   
   /* Read a variable name from the commandline and insert its content  
      into the buffer.  */  
   void getenvvar (void)  
     {  
       char varname[100];  
       char *p = varname;  
       char *val;  
       char c;  
   
       c = getchar ();  
       if (c == '{')  
         while ((c = getchar ()) != '}')  
           *(p++) = c;  
       else  
         {  
           /* XXX: An env. variable can have characters and digits in  
              its name, are more characters allowed here?  */  
           while (c && (grub_isalpha (c) || grub_isdigit (c)))  
             {  
               *(p++) = c;  
               c = getchar ();  
             }  
           unputc (c);  
         }  
       *p = '\0';  
   
       /* The variable does not exist.  */  
       val = grub_env_get (varname);  
       if (! val)  
         return;  
   
       /* Copy the contents of the variable into the buffer.  */  
       for (p = val; *p; p++)  
         *(bp++) = *p;  
     }  
   
   /* Read one argument.  Return 1 if no variables can be read anymore,  
      otherwise return 0.  If there is an error, return 1, the caller  
      has to check grub_errno.  */  
   int getarg (void)  
     {  
       char c;  
   
       /* Skip all whitespaces before an argument.  */  
       do {  
         c = getchar ();  
       } while (c == ' ' || c == '\t');  
   
       do {  
         switch (c)  
           {  
           case '"':  
             /* Double quote.  */  
             while ((c = getchar ()))  
               {  
                 if (grub_errno)  
                   return 1;  
                 /* Read in an escaped character.  */  
                 if (c == '\\')  
                   {  
                     c = getchar ();  
                     *(bp++) = c;  
                     continue;  
                   }  
                 else if (c == '"')  
                   break;  
                 /* Read a variable.  */  
                 if (c == '$')  
                   {  
                     getenvvar ();  
                     continue;  
                   }  
                 *(bp++) = c;  
               }  
             break;  
   
           case '\'':  
             /* Single quote.  */  
             while ((c = getchar ()) != '\'')  
               {  
                 if (grub_errno)  
                   return 1;  
   
                 *(bp++) = c;  
               }  
             break;  
   
           case '\n':  
             /* This was not a argument afterall.  */  
             return 1;  
   
           default:  
             /* A normal option.  */  
             while (c && (grub_isalpha (c)  
                          || grub_isdigit (c) || grub_isgraph (c)))  
               {  
                 /* Read in an escaped character.  */  
                 if (c == '\\')  
                   {  
                     c = getchar ();  
                     *(bp++) = c;  
                     c = getchar ();  
                     continue;  
                   }  
                 /* Read a variable.  */  
                 if (c == '$')  
                   {  
                     getenvvar ();  
                     c = getchar ();  
                     continue;  
                   }  
                 *(bp++) = c;  
                 c = getchar ();  
               }  
             unputc (c);  
   
             break;  
           }  
       } while (! grub_isspace (c) && c != '\'' && c != '"');  
   
       return 0;  
     }  
   
   /* Read in all arguments and count them.  */  
   *argc = 0;  
   while (1)  
     {  
       if (getarg ())  
         break;  
       *(bp++) = '\0';  
       (*argc)++;  
     }  
   
   /* Check if there were no errors.  */  
   if (grub_errno)  
     return grub_errno;  
   
   /* Reserve memory for the return values.  */  
   args = grub_malloc (bp - buffer);  
   if (! args)  
     return grub_errno;  
   grub_memcpy (args, buffer, bp - buffer);  
     
   *argv = grub_malloc (sizeof (char *) * (*argc + 1));  
   if (! *argv)  
     {  
       grub_free (args);  
       return grub_errno;  
     }  
   
   /* The arguments are separated with 0's, setup argv so it points to  
      the right values.  */  
   bp = args;  
   for (i = 0; i < *argc; i++)  
     {  
       (*argv)[i] = bp;  
       while (*bp)  
         bp++;  
       bp++;  
     }  
   
   (*argc)--;  
   return 0;  
 }  

Legend:
Removed from v.1.23  
changed lines
  Added in v.1.24

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26