Back to index

cell-binutils  2.17cvs20070401
Defines | Functions
argv.c File Reference
#include "ansidecl.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

Go to the source code of this file.

Defines

#define NULL   0
#define EOS   '\0'
#define INITIAL_MAXARGC   8 /* Number of args + NULL in initial argv */

Functions

char ** dupargv (char **argv)
void freeargv (char **vector)
char ** buildargv (const char *input)
void expandargv (int *argcp, char ***argvp)

Define Documentation

#define EOS   '\0'

Definition at line 44 of file argv.c.

#define INITIAL_MAXARGC   8 /* Number of args + NULL in initial argv */

Definition at line 47 of file argv.c.

#define NULL   0

Definition at line 40 of file argv.c.


Function Documentation

char** buildargv ( const char *  input)

Definition at line 162 of file argv.c.

{
  char *arg;
  char *copybuf;
  int squote = 0;
  int dquote = 0;
  int bsquote = 0;
  int argc = 0;
  int maxargc = 0;
  char **argv = NULL;
  char **nargv;

  if (input != NULL)
    {
      copybuf = (char *) alloca (strlen (input) + 1);
      /* Is a do{}while to always execute the loop once.  Always return an
        argv, even for null strings.  See NOTES above, test case below. */
      do
       {
         /* Pick off argv[argc] */
         while (ISBLANK (*input))
           {
             input++;
           }
         if ((maxargc == 0) || (argc >= (maxargc - 1)))
           {
             /* argv needs initialization, or expansion */
             if (argv == NULL)
              {
                maxargc = INITIAL_MAXARGC;
                nargv = (char **) malloc (maxargc * sizeof (char *));
              }
             else
              {
                maxargc *= 2;
                nargv = (char **) realloc (argv, maxargc * sizeof (char *));
              }
             if (nargv == NULL)
              {
                if (argv != NULL)
                  {
                    freeargv (argv);
                    argv = NULL;
                  }
                break;
              }
             argv = nargv;
             argv[argc] = NULL;
           }
         /* Begin scanning arg */
         arg = copybuf;
         while (*input != EOS)
           {
             if (ISSPACE (*input) && !squote && !dquote && !bsquote)
              {
                break;
              }
             else
              {
                if (bsquote)
                  {
                    bsquote = 0;
                    *arg++ = *input;
                  }
                else if (*input == '\\')
                  {
                    bsquote = 1;
                  }
                else if (squote)
                  {
                    if (*input == '\'')
                     {
                       squote = 0;
                     }
                    else
                     {
                       *arg++ = *input;
                     }
                  }
                else if (dquote)
                  {
                    if (*input == '"')
                     {
                       dquote = 0;
                     }
                    else
                     {
                       *arg++ = *input;
                     }
                  }
                else
                  {
                    if (*input == '\'')
                     {
                       squote = 1;
                     }
                    else if (*input == '"')
                     {
                       dquote = 1;
                     }
                    else
                     {
                       *arg++ = *input;
                     }
                  }
                input++;
              }
           }
         *arg = EOS;
         argv[argc] = strdup (copybuf);
         if (argv[argc] == NULL)
           {
             freeargv (argv);
             argv = NULL;
             break;
           }
         argc++;
         argv[argc] = NULL;

         while (ISSPACE (*input))
           {
             input++;
           }
       }
      while (*input != EOS);
    }
  return (argv);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char** dupargv ( char **  argv)

Definition at line 65 of file argv.c.

{
  int argc;
  char **copy;
  
  if (argv == NULL)
    return NULL;
  
  /* the vector */
  for (argc = 0; argv[argc] != NULL; argc++);
  copy = (char **) malloc ((argc + 1) * sizeof (char *));
  if (copy == NULL)
    return NULL;
  
  /* the strings */
  for (argc = 0; argv[argc] != NULL; argc++)
    {
      int len = strlen (argv[argc]);
      copy[argc] = (char *) malloc (len + 1);
      if (copy[argc] == NULL)
       {
         freeargv (copy);
         return NULL;
       }
      strcpy (copy[argc], argv[argc]);
    }
  copy[argc] = NULL;
  return copy;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void expandargv ( int argcp,
char ***  argvp 
)

Definition at line 315 of file argv.c.

{
  /* The argument we are currently processing.  */
  int i = 0;
  /* Non-zero if ***argvp has been dynamically allocated.  */
  int argv_dynamic = 0;
  /* Loop over the arguments, handling response files.  We always skip
     ARGVP[0], as that is the name of the program being run.  */
  while (++i < *argcp)
    {
      /* The name of the response file.  */
      const char *filename;
      /* The response file.  */
      FILE *f;
      /* An upper bound on the number of characters in the response
        file.  */
      long pos;
      /* The number of characters in the response file, when actually
        read.  */
      size_t len;
      /* A dynamically allocated buffer used to hold options read from a
        response file.  */
      char *buffer;
      /* Dynamically allocated storage for the options read from the
        response file.  */
      char **file_argv;
      /* The number of options read from the response file, if any.  */
      size_t file_argc;
      /* We are only interested in options of the form "@file".  */
      filename = (*argvp)[i];
      if (filename[0] != '@')
       continue;
      /* Read the contents of the file.  */
      f = fopen (++filename, "r");
      if (!f)
       continue;
      if (fseek (f, 0L, SEEK_END) == -1)
       goto error;
      pos = ftell (f);
      if (pos == -1)
       goto error;
      if (fseek (f, 0L, SEEK_SET) == -1)
       goto error;
      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
      len = fread (buffer, sizeof (char), pos, f);
      if (len != (size_t) pos
         /* On Windows, fread may return a value smaller than POS,
            due to CR/LF->CR translation when reading text files.
            That does not in-and-of itself indicate failure.  */
         && ferror (f))
       goto error;
      /* Add a NUL terminator.  */
      buffer[len] = '\0';
      /* Parse the string.  */
      file_argv = buildargv (buffer);
      /* If *ARGVP is not already dynamically allocated, copy it.  */
      if (!argv_dynamic)
       {
         *argvp = dupargv (*argvp);
         if (!*argvp)
           {
             fputs ("\nout of memory\n", stderr);
             xexit (1);
           }
       }
      /* Count the number of arguments.  */
      file_argc = 0;
      while (file_argv[file_argc] && *file_argv[file_argc])
       ++file_argc;
      /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
        NULL terminator at the end of ARGV.  */ 
      *argvp = ((char **) 
              xrealloc (*argvp, 
                       (*argcp + file_argc + 1) * sizeof (char *)));
      memmove (*argvp + i + file_argc, *argvp + i + 1, 
              (*argcp - i) * sizeof (char *));
      memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
      /* The original option has been replaced by all the new
        options.  */
      *argcp += file_argc - 1;
      /* Free up memory allocated to process the response file.  We do
        not use freeargv because the individual options in FILE_ARGV
        are now in the main ARGV.  */
      free (file_argv);
      free (buffer);
      /* Rescan all of the arguments just read to support response
        files that include other response files.  */
      --i;
    error:
      /* We're all done with the file now.  */
      fclose (f);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void freeargv ( char **  vector)

Definition at line 108 of file argv.c.

{
  register char **scan;

  if (vector != NULL)
    {
      for (scan = vector; *scan != NULL; scan++)
       {
         free (*scan);
       }
      free (vector);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function: