OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [binutils/] [rclex.c] - Diff between revs 816 and 818

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 816 Rev 818
/* rclex.c -- lexer for Windows rc files parser  */
/* rclex.c -- lexer for Windows rc files parser  */
 
 
/* Copyright 1997, 1998, 1999, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009
/* Copyright 1997, 1998, 1999, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   Written by Kai Tietz, Onevision.
   Written by Kai Tietz, Onevision.
 
 
   This file is part of GNU Binutils.
   This file is part of GNU Binutils.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   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
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
 
 
/* This is a lexer used by the Windows rc file parser.  It basically
/* This is a lexer used by the Windows rc file parser.  It basically
   just recognized a bunch of keywords.  */
   just recognized a bunch of keywords.  */
 
 
#include "sysdep.h"
#include "sysdep.h"
#include "bfd.h"
#include "bfd.h"
#include "bucomm.h"
#include "bucomm.h"
#include "libiberty.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#include "windres.h"
#include "windres.h"
#include "rcparse.h"
#include "rcparse.h"
 
 
#include <assert.h>
#include <assert.h>
 
 
/* Whether we are in rcdata mode, in which we returns the lengths of
/* Whether we are in rcdata mode, in which we returns the lengths of
   strings.  */
   strings.  */
 
 
static int rcdata_mode;
static int rcdata_mode;
 
 
/* Whether we are supressing lines from cpp (including windows.h or
/* Whether we are supressing lines from cpp (including windows.h or
   headers from your C sources may bring in externs and typedefs).
   headers from your C sources may bring in externs and typedefs).
   When active, we return IGNORED_TOKEN, which lets us ignore these
   When active, we return IGNORED_TOKEN, which lets us ignore these
   outside of resource constructs.  Thus, it isn't required to protect
   outside of resource constructs.  Thus, it isn't required to protect
   all the non-preprocessor lines in your header files with #ifdef
   all the non-preprocessor lines in your header files with #ifdef
   RC_INVOKED.  It also means your RC file can't include other RC
   RC_INVOKED.  It also means your RC file can't include other RC
   files if they're named "*.h".  Sorry.  Name them *.rch or whatever.  */
   files if they're named "*.h".  Sorry.  Name them *.rch or whatever.  */
 
 
static int suppress_cpp_data;
static int suppress_cpp_data;
 
 
#define IGNORE_CPP(x) (suppress_cpp_data ? IGNORED_TOKEN : (x))
#define IGNORE_CPP(x) (suppress_cpp_data ? IGNORED_TOKEN : (x))
 
 
/* The first filename we detect in the cpp output.  We use this to
/* The first filename we detect in the cpp output.  We use this to
   tell included files from the original file.  */
   tell included files from the original file.  */
 
 
static char *initial_fn;
static char *initial_fn;
 
 
/* List of allocated strings.  */
/* List of allocated strings.  */
 
 
struct alloc_string
struct alloc_string
{
{
  struct alloc_string *next;
  struct alloc_string *next;
  char *s;
  char *s;
};
};
 
 
static struct alloc_string *strings;
static struct alloc_string *strings;
 
 
struct rclex_keywords
struct rclex_keywords
{
{
  const char *name;
  const char *name;
  int tok;
  int tok;
};
};
 
 
#define K(KEY)  { #KEY, KEY }
#define K(KEY)  { #KEY, KEY }
#define KRT(KEY)  { #KEY, RT_##KEY }
#define KRT(KEY)  { #KEY, RT_##KEY }
 
 
static const struct rclex_keywords keywds[] =
static const struct rclex_keywords keywds[] =
{
{
  K(ACCELERATORS), K(ALT), K(ANICURSOR), K(ANIICON), K(ASCII),
  K(ACCELERATORS), K(ALT), K(ANICURSOR), K(ANIICON), K(ASCII),
  K(AUTO3STATE), K(AUTOCHECKBOX), K(AUTORADIOBUTTON),
  K(AUTO3STATE), K(AUTOCHECKBOX), K(AUTORADIOBUTTON),
  K(BEDIT), { "BEGIN", BEG }, K(BITMAP), K(BLOCK), K(BUTTON),
  K(BEDIT), { "BEGIN", BEG }, K(BITMAP), K(BLOCK), K(BUTTON),
  K(CAPTION), K(CHARACTERISTICS), K(CHECKBOX), K(CHECKED),
  K(CAPTION), K(CHARACTERISTICS), K(CHECKBOX), K(CHECKED),
  K(CLASS), K(COMBOBOX), K(CONTROL), K(CTEXT), K(CURSOR),
  K(CLASS), K(COMBOBOX), K(CONTROL), K(CTEXT), K(CURSOR),
  K(DEFPUSHBUTTON), K(DIALOG), K(DIALOGEX), K(DISCARDABLE),
  K(DEFPUSHBUTTON), K(DIALOG), K(DIALOGEX), K(DISCARDABLE),
  K(DLGINCLUDE), K(DLGINIT),
  K(DLGINCLUDE), K(DLGINIT),
  K(EDITTEXT), K(END), K(EXSTYLE),
  K(EDITTEXT), K(END), K(EXSTYLE),
  K(FILEFLAGS), K(FILEFLAGSMASK), K(FILEOS), K(FILESUBTYPE),
  K(FILEFLAGS), K(FILEFLAGSMASK), K(FILEOS), K(FILESUBTYPE),
  K(FILETYPE), K(FILEVERSION), K(FIXED), K(FONT), K(FONTDIR),
  K(FILETYPE), K(FILEVERSION), K(FIXED), K(FONT), K(FONTDIR),
  K(GRAYED), KRT(GROUP_CURSOR), KRT(GROUP_ICON), K(GROUPBOX),
  K(GRAYED), KRT(GROUP_CURSOR), KRT(GROUP_ICON), K(GROUPBOX),
  K(HEDIT), K(HELP), K(HTML),
  K(HEDIT), K(HELP), K(HTML),
  K(ICON), K(IEDIT), K(IMPURE), K(INACTIVE),
  K(ICON), K(IEDIT), K(IMPURE), K(INACTIVE),
  K(LANGUAGE), K(LISTBOX), K(LOADONCALL), K(LTEXT),
  K(LANGUAGE), K(LISTBOX), K(LOADONCALL), K(LTEXT),
  K(MANIFEST), K(MENU), K(MENUBARBREAK), K(MENUBREAK),
  K(MANIFEST), K(MENU), K(MENUBARBREAK), K(MENUBREAK),
  K(MENUEX), K(MENUITEM), K(MESSAGETABLE), K(MOVEABLE),
  K(MENUEX), K(MENUITEM), K(MESSAGETABLE), K(MOVEABLE),
  K(NOINVERT), K(NOT),
  K(NOINVERT), K(NOT),
  K(PLUGPLAY), K(POPUP), K(PRELOAD), K(PRODUCTVERSION),
  K(PLUGPLAY), K(POPUP), K(PRELOAD), K(PRODUCTVERSION),
  K(PURE), K(PUSHBOX), K(PUSHBUTTON),
  K(PURE), K(PUSHBOX), K(PUSHBUTTON),
  K(RADIOBUTTON), K(RCDATA), K(RTEXT),
  K(RADIOBUTTON), K(RCDATA), K(RTEXT),
  K(SCROLLBAR), K(SEPARATOR), K(SHIFT), K(STATE3),
  K(SCROLLBAR), K(SEPARATOR), K(SHIFT), K(STATE3),
  K(STRINGTABLE), K(STYLE),
  K(STRINGTABLE), K(STYLE),
  K(TOOLBAR),
  K(TOOLBAR),
  K(USERBUTTON),
  K(USERBUTTON),
  K(VALUE), { "VERSION", VERSIONK }, K(VERSIONINFO),
  K(VALUE), { "VERSION", VERSIONK }, K(VERSIONINFO),
  K(VIRTKEY), K(VXD),
  K(VIRTKEY), K(VXD),
  { NULL, 0 },
  { NULL, 0 },
};
};
 
 
/* External input stream from resrc */
/* External input stream from resrc */
extern FILE *cpp_pipe;
extern FILE *cpp_pipe;
 
 
/* Lexical scanner helpers.  */
/* Lexical scanner helpers.  */
static int rclex_lastch = -1;
static int rclex_lastch = -1;
static size_t rclex_tok_max = 0;
static size_t rclex_tok_max = 0;
static size_t rclex_tok_pos = 0;
static size_t rclex_tok_pos = 0;
static char *rclex_tok = NULL;
static char *rclex_tok = NULL;
 
 
static int
static int
rclex_translatekeyword (const char *key)
rclex_translatekeyword (const char *key)
{
{
  if (key && ISUPPER (key[0]))
  if (key && ISUPPER (key[0]))
    {
    {
      const struct rclex_keywords *kw = &keywds[0];
      const struct rclex_keywords *kw = &keywds[0];
 
 
      do
      do
        {
        {
          if (! strcmp (kw->name, key))
          if (! strcmp (kw->name, key))
            return kw->tok;
            return kw->tok;
          ++kw;
          ++kw;
        }
        }
      while (kw->name != NULL);
      while (kw->name != NULL);
    }
    }
  return STRING;
  return STRING;
}
}
 
 
/* Handle a C preprocessor line.  */
/* Handle a C preprocessor line.  */
 
 
static void
static void
cpp_line (void)
cpp_line (void)
{
{
  const char *s = rclex_tok;
  const char *s = rclex_tok;
  int line;
  int line;
  char *send, *fn;
  char *send, *fn;
  size_t len, mlen;
  size_t len, mlen;
 
 
  ++s;
  ++s;
  while (ISSPACE (*s))
  while (ISSPACE (*s))
    ++s;
    ++s;
 
 
  /* Check for #pragma code_page ( DEFAULT | <nr>).  */
  /* Check for #pragma code_page ( DEFAULT | <nr>).  */
  len = strlen (s);
  len = strlen (s);
  mlen = strlen ("pragma");
  mlen = strlen ("pragma");
  if (len > mlen && memcmp (s, "pragma", mlen) == 0 && ISSPACE (s[mlen]))
  if (len > mlen && memcmp (s, "pragma", mlen) == 0 && ISSPACE (s[mlen]))
    {
    {
      const char *end;
      const char *end;
 
 
      s += mlen + 1;
      s += mlen + 1;
      while (ISSPACE (*s))
      while (ISSPACE (*s))
        ++s;
        ++s;
      len = strlen (s);
      len = strlen (s);
      mlen = strlen ("code_page");
      mlen = strlen ("code_page");
      if (len <= mlen || memcmp (s, "code_page", mlen) != 0)
      if (len <= mlen || memcmp (s, "code_page", mlen) != 0)
        /* FIXME: We ought to issue a warning message about an unrecognised pragma.  */
        /* FIXME: We ought to issue a warning message about an unrecognised pragma.  */
        return;
        return;
      s += mlen;
      s += mlen;
      while (ISSPACE (*s))
      while (ISSPACE (*s))
        ++s;
        ++s;
      if (*s != '(')
      if (*s != '(')
        /* FIXME: We ought to issue an error message about a malformed pragma.  */
        /* FIXME: We ought to issue an error message about a malformed pragma.  */
        return;
        return;
      ++s;
      ++s;
      while (ISSPACE (*s))
      while (ISSPACE (*s))
        ++s;
        ++s;
      if (*s == 0 || (end = strchr (s, ')')) == NULL)
      if (*s == 0 || (end = strchr (s, ')')) == NULL)
        /* FIXME: We ought to issue an error message about a malformed pragma.  */
        /* FIXME: We ought to issue an error message about a malformed pragma.  */
        return;
        return;
      len = (size_t) (end - s);
      len = (size_t) (end - s);
      fn = xmalloc (len + 1);
      fn = xmalloc (len + 1);
      if (len)
      if (len)
        memcpy (fn, s, len);
        memcpy (fn, s, len);
      fn[len] = 0;
      fn[len] = 0;
      while (len > 0 && (fn[len - 1] > 0 && fn[len - 1] <= 0x20))
      while (len > 0 && (fn[len - 1] > 0 && fn[len - 1] <= 0x20))
        fn[--len] = 0;
        fn[--len] = 0;
      if (! len || (len == strlen ("DEFAULT") && strcasecmp (fn, "DEFAULT") == 0))
      if (! len || (len == strlen ("DEFAULT") && strcasecmp (fn, "DEFAULT") == 0))
        wind_current_codepage = wind_default_codepage;
        wind_current_codepage = wind_default_codepage;
      else if (len > 0)
      else if (len > 0)
        {
        {
          rc_uint_type ncp;
          rc_uint_type ncp;
 
 
          if (fn[0] == '0' && (fn[1] == 'x' || fn[1] == 'X'))
          if (fn[0] == '0' && (fn[1] == 'x' || fn[1] == 'X'))
              ncp = (rc_uint_type) strtol (fn + 2, NULL, 16);
              ncp = (rc_uint_type) strtol (fn + 2, NULL, 16);
          else
          else
              ncp = (rc_uint_type) strtol (fn, NULL, 10);
              ncp = (rc_uint_type) strtol (fn, NULL, 10);
          if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
          if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
            fatal (_("invalid value specified for pragma code_page.\n"));
            fatal (_("invalid value specified for pragma code_page.\n"));
          wind_current_codepage = ncp;
          wind_current_codepage = ncp;
        }
        }
      free (fn);
      free (fn);
      return;
      return;
    }
    }
 
 
  line = strtol (s, &send, 0);
  line = strtol (s, &send, 0);
  if (*send != '\0' && ! ISSPACE (*send))
  if (*send != '\0' && ! ISSPACE (*send))
    return;
    return;
 
 
  /* Subtract 1 because we are about to count the newline.  */
  /* Subtract 1 because we are about to count the newline.  */
  rc_lineno = line - 1;
  rc_lineno = line - 1;
 
 
  s = send;
  s = send;
  while (ISSPACE (*s))
  while (ISSPACE (*s))
    ++s;
    ++s;
 
 
  if (*s != '"')
  if (*s != '"')
    return;
    return;
 
 
  ++s;
  ++s;
  send = strchr (s, '"');
  send = strchr (s, '"');
  if (send == NULL)
  if (send == NULL)
    return;
    return;
 
 
  fn = xmalloc (send - s + 1);
  fn = xmalloc (send - s + 1);
  strncpy (fn, s, send - s);
  strncpy (fn, s, send - s);
  fn[send - s] = '\0';
  fn[send - s] = '\0';
 
 
  free (rc_filename);
  free (rc_filename);
  rc_filename = fn;
  rc_filename = fn;
 
 
  if (! initial_fn)
  if (! initial_fn)
    {
    {
      initial_fn = xmalloc (strlen (fn) + 1);
      initial_fn = xmalloc (strlen (fn) + 1);
      strcpy (initial_fn, fn);
      strcpy (initial_fn, fn);
    }
    }
 
 
  /* Allow the initial file, regardless of name.  Suppress all other
  /* Allow the initial file, regardless of name.  Suppress all other
     files if they end in ".h" (this allows included "*.rc").  */
     files if they end in ".h" (this allows included "*.rc").  */
  if (strcmp (initial_fn, fn) == 0
  if (strcmp (initial_fn, fn) == 0
      || strcmp (fn + strlen (fn) - 2, ".h") != 0)
      || strcmp (fn + strlen (fn) - 2, ".h") != 0)
    suppress_cpp_data = 0;
    suppress_cpp_data = 0;
  else
  else
    suppress_cpp_data = 1;
    suppress_cpp_data = 1;
}
}
 
 
/* Allocate a string of a given length.  */
/* Allocate a string of a given length.  */
 
 
static char *
static char *
get_string (int len)
get_string (int len)
{
{
  struct alloc_string *as;
  struct alloc_string *as;
 
 
  as = xmalloc (sizeof *as);
  as = xmalloc (sizeof *as);
  as->s = xmalloc (len);
  as->s = xmalloc (len);
 
 
  as->next = strings;
  as->next = strings;
  strings = as;
  strings = as;
 
 
  return as->s;
  return as->s;
}
}
 
 
/* Handle a quoted string.  The quotes are stripped.  A pair of quotes
/* Handle a quoted string.  The quotes are stripped.  A pair of quotes
   in a string are turned into a single quote.  Adjacent strings are
   in a string are turned into a single quote.  Adjacent strings are
   merged separated by whitespace are merged, as in C.  */
   merged separated by whitespace are merged, as in C.  */
 
 
static char *
static char *
handle_quotes (rc_uint_type *len)
handle_quotes (rc_uint_type *len)
{
{
  const char *input = rclex_tok;
  const char *input = rclex_tok;
  char *ret, *s;
  char *ret, *s;
  const char *t;
  const char *t;
  int ch;
  int ch;
  int num_xdigits;
  int num_xdigits;
 
 
  ret = get_string (strlen (input) + 1);
  ret = get_string (strlen (input) + 1);
 
 
  s = ret;
  s = ret;
  t = input;
  t = input;
  if (*t == '"')
  if (*t == '"')
    ++t;
    ++t;
  while (*t != '\0')
  while (*t != '\0')
    {
    {
      if (*t == '\\')
      if (*t == '\\')
        {
        {
          ++t;
          ++t;
          switch (*t)
          switch (*t)
            {
            {
            case '\0':
            case '\0':
              rcparse_warning ("backslash at end of string");
              rcparse_warning ("backslash at end of string");
              break;
              break;
 
 
            case '\"':
            case '\"':
              rcparse_warning ("use \"\" to put \" in a string");
              rcparse_warning ("use \"\" to put \" in a string");
              *s++ = '"';
              *s++ = '"';
              ++t;
              ++t;
              break;
              break;
 
 
            case 'a':
            case 'a':
              *s++ = ESCAPE_B; /* Strange, but true...  */
              *s++ = ESCAPE_B; /* Strange, but true...  */
              ++t;
              ++t;
              break;
              break;
 
 
            case 'b':
            case 'b':
              *s++ = ESCAPE_B;
              *s++ = ESCAPE_B;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'f':
            case 'f':
              *s++ = ESCAPE_F;
              *s++ = ESCAPE_F;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'n':
            case 'n':
              *s++ = ESCAPE_N;
              *s++ = ESCAPE_N;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'r':
            case 'r':
              *s++ = ESCAPE_R;
              *s++ = ESCAPE_R;
              ++t;
              ++t;
              break;
              break;
 
 
            case 't':
            case 't':
              *s++ = ESCAPE_T;
              *s++ = ESCAPE_T;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'v':
            case 'v':
              *s++ = ESCAPE_V;
              *s++ = ESCAPE_V;
              ++t;
              ++t;
              break;
              break;
 
 
            case '\\':
            case '\\':
              *s++ = *t++;
              *s++ = *t++;
              break;
              break;
 
 
            case '0': case '1': case '2': case '3':
            case '0': case '1': case '2': case '3':
            case '4': case '5': case '6': case '7':
            case '4': case '5': case '6': case '7':
              ch = *t - '0';
              ch = *t - '0';
              ++t;
              ++t;
              if (*t >= '0' && *t <= '7')
              if (*t >= '0' && *t <= '7')
                {
                {
                  ch = (ch << 3) | (*t - '0');
                  ch = (ch << 3) | (*t - '0');
                  ++t;
                  ++t;
                  if (*t >= '0' && *t <= '7')
                  if (*t >= '0' && *t <= '7')
                    {
                    {
                      ch = (ch << 3) | (*t - '0');
                      ch = (ch << 3) | (*t - '0');
                      ++t;
                      ++t;
                    }
                    }
                }
                }
              *s++ = ch;
              *s++ = ch;
              break;
              break;
 
 
            case 'x': case 'X':
            case 'x': case 'X':
              ++t;
              ++t;
              ch = 0;
              ch = 0;
              /* We only handle single byte chars here.  Make sure
              /* We only handle single byte chars here.  Make sure
                 we finish an escape sequence like "/xB0ABC" after
                 we finish an escape sequence like "/xB0ABC" after
                 the first two digits.  */
                 the first two digits.  */
              num_xdigits = 2;
              num_xdigits = 2;
              while (num_xdigits--)
              while (num_xdigits--)
                {
                {
                  if (*t >= '0' && *t <= '9')
                  if (*t >= '0' && *t <= '9')
                    ch = (ch << 4) | (*t - '0');
                    ch = (ch << 4) | (*t - '0');
                  else if (*t >= 'a' && *t <= 'f')
                  else if (*t >= 'a' && *t <= 'f')
                    ch = (ch << 4) | (*t - 'a' + 10);
                    ch = (ch << 4) | (*t - 'a' + 10);
                  else if (*t >= 'A' && *t <= 'F')
                  else if (*t >= 'A' && *t <= 'F')
                    ch = (ch << 4) | (*t - 'A' + 10);
                    ch = (ch << 4) | (*t - 'A' + 10);
                  else
                  else
                    break;
                    break;
                  ++t;
                  ++t;
                }
                }
              *s++ = ch;
              *s++ = ch;
              break;
              break;
 
 
            default:
            default:
              rcparse_warning ("unrecognized escape sequence");
              rcparse_warning ("unrecognized escape sequence");
              *s++ = '\\';
              *s++ = '\\';
              *s++ = *t++;
              *s++ = *t++;
              break;
              break;
            }
            }
        }
        }
      else if (*t != '"')
      else if (*t != '"')
        *s++ = *t++;
        *s++ = *t++;
      else if (t[1] == '\0')
      else if (t[1] == '\0')
        break;
        break;
      else if (t[1] == '"')
      else if (t[1] == '"')
        {
        {
          *s++ = '"';
          *s++ = '"';
          t += 2;
          t += 2;
        }
        }
      else
      else
        {
        {
          ++t;
          ++t;
          if (! ISSPACE (*t))
          if (! ISSPACE (*t))
            rcparse_warning ("unexpected character after '\"'");
            rcparse_warning ("unexpected character after '\"'");
          while (ISSPACE (*t))
          while (ISSPACE (*t))
            {
            {
              if ((*t) == '\n')
              if ((*t) == '\n')
                ++rc_lineno;
                ++rc_lineno;
              ++t;
              ++t;
            }
            }
          if (*t == '\0')
          if (*t == '\0')
            break;
            break;
          assert (*t == '"');
          assert (*t == '"');
          ++t;
          ++t;
        }
        }
    }
    }
 
 
  *s = '\0';
  *s = '\0';
 
 
  *len = s - ret;
  *len = s - ret;
 
 
  return ret;
  return ret;
}
}
 
 
/* Allocate a unicode string of a given length.  */
/* Allocate a unicode string of a given length.  */
 
 
static unichar *
static unichar *
get_unistring (int len)
get_unistring (int len)
{
{
  return (unichar *) get_string (len * sizeof (unichar));
  return (unichar *) get_string (len * sizeof (unichar));
}
}
 
 
/* Handle a quoted unicode string.  The quotes are stripped.  A pair of quotes
/* Handle a quoted unicode string.  The quotes are stripped.  A pair of quotes
   in a string are turned into a single quote.  Adjacent strings are
   in a string are turned into a single quote.  Adjacent strings are
   merged separated by whitespace are merged, as in C.  */
   merged separated by whitespace are merged, as in C.  */
 
 
static unichar *
static unichar *
handle_uniquotes (rc_uint_type *len)
handle_uniquotes (rc_uint_type *len)
{
{
  const char *input = rclex_tok;
  const char *input = rclex_tok;
  unichar *ret, *s;
  unichar *ret, *s;
  const char *t;
  const char *t;
  int ch;
  int ch;
  int num_xdigits;
  int num_xdigits;
 
 
  ret = get_unistring (strlen (input) + 1);
  ret = get_unistring (strlen (input) + 1);
 
 
  s = ret;
  s = ret;
  t = input;
  t = input;
  if ((*t == 'L' || *t == 'l') && t[1] == '"')
  if ((*t == 'L' || *t == 'l') && t[1] == '"')
    t += 2;
    t += 2;
  else if (*t == '"')
  else if (*t == '"')
    ++t;
    ++t;
  while (*t != '\0')
  while (*t != '\0')
    {
    {
      if (*t == '\\')
      if (*t == '\\')
        {
        {
          ++t;
          ++t;
          switch (*t)
          switch (*t)
            {
            {
            case '\0':
            case '\0':
              rcparse_warning ("backslash at end of string");
              rcparse_warning ("backslash at end of string");
              break;
              break;
 
 
            case '\"':
            case '\"':
              rcparse_warning ("use \"\" to put \" in a string");
              rcparse_warning ("use \"\" to put \" in a string");
              break;
              break;
 
 
            case 'a':
            case 'a':
              *s++ = ESCAPE_B; /* Strange, but true...  */
              *s++ = ESCAPE_B; /* Strange, but true...  */
              ++t;
              ++t;
              break;
              break;
 
 
            case 'b':
            case 'b':
              *s++ = ESCAPE_B;
              *s++ = ESCAPE_B;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'f':
            case 'f':
              *s++ = ESCAPE_F;
              *s++ = ESCAPE_F;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'n':
            case 'n':
              *s++ = ESCAPE_N;
              *s++ = ESCAPE_N;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'r':
            case 'r':
              *s++ = ESCAPE_R;
              *s++ = ESCAPE_R;
              ++t;
              ++t;
              break;
              break;
 
 
            case 't':
            case 't':
              *s++ = ESCAPE_T;
              *s++ = ESCAPE_T;
              ++t;
              ++t;
              break;
              break;
 
 
            case 'v':
            case 'v':
              *s++ = ESCAPE_V;
              *s++ = ESCAPE_V;
              ++t;
              ++t;
              break;
              break;
 
 
            case '\\':
            case '\\':
              *s++ = (unichar) *t++;
              *s++ = (unichar) *t++;
              break;
              break;
 
 
            case '0': case '1': case '2': case '3':
            case '0': case '1': case '2': case '3':
            case '4': case '5': case '6': case '7':
            case '4': case '5': case '6': case '7':
              ch = *t - '0';
              ch = *t - '0';
              ++t;
              ++t;
              if (*t >= '0' && *t <= '7')
              if (*t >= '0' && *t <= '7')
                {
                {
                  ch = (ch << 3) | (*t - '0');
                  ch = (ch << 3) | (*t - '0');
                  ++t;
                  ++t;
                  if (*t >= '0' && *t <= '7')
                  if (*t >= '0' && *t <= '7')
                    {
                    {
                      ch = (ch << 3) | (*t - '0');
                      ch = (ch << 3) | (*t - '0');
                      ++t;
                      ++t;
                    }
                    }
                }
                }
              *s++ = (unichar) ch;
              *s++ = (unichar) ch;
              break;
              break;
 
 
            case 'x': case 'X':
            case 'x': case 'X':
              ++t;
              ++t;
              ch = 0;
              ch = 0;
              /* We only handle two byte chars here.  Make sure
              /* We only handle two byte chars here.  Make sure
                 we finish an escape sequence like "/xB0ABC" after
                 we finish an escape sequence like "/xB0ABC" after
                 the first two digits.  */
                 the first two digits.  */
              num_xdigits = 4;
              num_xdigits = 4;
              while (num_xdigits--)
              while (num_xdigits--)
                {
                {
                  if (*t >= '0' && *t <= '9')
                  if (*t >= '0' && *t <= '9')
                    ch = (ch << 4) | (*t - '0');
                    ch = (ch << 4) | (*t - '0');
                  else if (*t >= 'a' && *t <= 'f')
                  else if (*t >= 'a' && *t <= 'f')
                    ch = (ch << 4) | (*t - 'a' + 10);
                    ch = (ch << 4) | (*t - 'a' + 10);
                  else if (*t >= 'A' && *t <= 'F')
                  else if (*t >= 'A' && *t <= 'F')
                    ch = (ch << 4) | (*t - 'A' + 10);
                    ch = (ch << 4) | (*t - 'A' + 10);
                  else
                  else
                    break;
                    break;
                  ++t;
                  ++t;
                }
                }
              *s++ = (unichar) ch;
              *s++ = (unichar) ch;
              break;
              break;
 
 
            default:
            default:
              rcparse_warning ("unrecognized escape sequence");
              rcparse_warning ("unrecognized escape sequence");
              *s++ = '\\';
              *s++ = '\\';
              *s++ = (unichar) *t++;
              *s++ = (unichar) *t++;
              break;
              break;
            }
            }
        }
        }
      else if (*t != '"')
      else if (*t != '"')
        *s++ = (unichar) *t++;
        *s++ = (unichar) *t++;
      else if (t[1] == '\0')
      else if (t[1] == '\0')
        break;
        break;
      else if (t[1] == '"')
      else if (t[1] == '"')
        {
        {
          *s++ = '"';
          *s++ = '"';
          t += 2;
          t += 2;
        }
        }
      else
      else
        {
        {
          ++t;
          ++t;
          assert (ISSPACE (*t));
          assert (ISSPACE (*t));
          while (ISSPACE (*t))
          while (ISSPACE (*t))
            {
            {
              if ((*t) == '\n')
              if ((*t) == '\n')
                ++rc_lineno;
                ++rc_lineno;
              ++t;
              ++t;
            }
            }
          if (*t == '\0')
          if (*t == '\0')
            break;
            break;
          assert (*t == '"');
          assert (*t == '"');
          ++t;
          ++t;
        }
        }
    }
    }
 
 
  *s = '\0';
  *s = '\0';
 
 
  *len = s - ret;
  *len = s - ret;
 
 
  return ret;
  return ret;
}
}
 
 
/* Discard all the strings we have allocated.  The parser calls this
/* Discard all the strings we have allocated.  The parser calls this
   when it no longer needs them.  */
   when it no longer needs them.  */
 
 
void
void
rcparse_discard_strings (void)
rcparse_discard_strings (void)
{
{
  struct alloc_string *as;
  struct alloc_string *as;
 
 
  as = strings;
  as = strings;
  while (as != NULL)
  while (as != NULL)
    {
    {
      struct alloc_string *n;
      struct alloc_string *n;
 
 
      free (as->s);
      free (as->s);
      n = as->next;
      n = as->next;
      free (as);
      free (as);
      as = n;
      as = n;
    }
    }
 
 
  strings = NULL;
  strings = NULL;
}
}
 
 
/* Enter rcdata mode.  */
/* Enter rcdata mode.  */
void
void
rcparse_rcdata (void)
rcparse_rcdata (void)
{
{
  rcdata_mode = 1;
  rcdata_mode = 1;
}
}
 
 
/* Go back to normal mode from rcdata mode.  */
/* Go back to normal mode from rcdata mode.  */
void
void
rcparse_normal (void)
rcparse_normal (void)
{
{
  rcdata_mode = 0;
  rcdata_mode = 0;
}
}
 
 
static void
static void
rclex_tok_add_char (int ch)
rclex_tok_add_char (int ch)
{
{
  if (! rclex_tok || rclex_tok_max <= rclex_tok_pos)
  if (! rclex_tok || rclex_tok_max <= rclex_tok_pos)
    {
    {
      char *h = xmalloc (rclex_tok_max + 9);
      char *h = xmalloc (rclex_tok_max + 9);
 
 
      if (! h)
      if (! h)
        abort ();
        abort ();
      if (rclex_tok)
      if (rclex_tok)
        {
        {
          memcpy (h, rclex_tok, rclex_tok_pos + 1);
          memcpy (h, rclex_tok, rclex_tok_pos + 1);
          free (rclex_tok);
          free (rclex_tok);
        }
        }
      else
      else
        rclex_tok_pos = 0;
        rclex_tok_pos = 0;
      rclex_tok_max += 8;
      rclex_tok_max += 8;
      rclex_tok = h;
      rclex_tok = h;
    }
    }
  if (ch != -1)
  if (ch != -1)
    rclex_tok[rclex_tok_pos++] = (char) ch;
    rclex_tok[rclex_tok_pos++] = (char) ch;
  rclex_tok[rclex_tok_pos] = 0;
  rclex_tok[rclex_tok_pos] = 0;
}
}
 
 
static int
static int
rclex_readch (void)
rclex_readch (void)
{
{
  int r = -1;
  int r = -1;
 
 
  if ((r = rclex_lastch) != -1)
  if ((r = rclex_lastch) != -1)
    rclex_lastch = -1;
    rclex_lastch = -1;
  else
  else
    {
    {
      char ch;
      char ch;
      do
      do
        {
        {
          if (! cpp_pipe || feof (cpp_pipe)
          if (! cpp_pipe || feof (cpp_pipe)
              || fread (&ch, 1, 1,cpp_pipe) != 1)
              || fread (&ch, 1, 1,cpp_pipe) != 1)
            break;
            break;
          r = ((int) ch) & 0xff;
          r = ((int) ch) & 0xff;
        }
        }
      while (r == 0 || r == '\r');
      while (r == 0 || r == '\r');
  }
  }
  rclex_tok_add_char (r);
  rclex_tok_add_char (r);
  return r;
  return r;
}
}
 
 
static int
static int
rclex_peekch (void)
rclex_peekch (void)
{
{
  int r;
  int r;
 
 
  if ((r = rclex_lastch) == -1)
  if ((r = rclex_lastch) == -1)
    {
    {
      if ((r = rclex_readch ()) != -1)
      if ((r = rclex_readch ()) != -1)
        {
        {
          rclex_lastch = r;
          rclex_lastch = r;
          if (rclex_tok_pos > 0)
          if (rclex_tok_pos > 0)
            rclex_tok[--rclex_tok_pos] = 0;
            rclex_tok[--rclex_tok_pos] = 0;
        }
        }
    }
    }
  return r;
  return r;
}
}
 
 
static void
static void
rclex_string (void)
rclex_string (void)
{
{
  int c;
  int c;
 
 
  while ((c = rclex_peekch ()) != -1)
  while ((c = rclex_peekch ()) != -1)
    {
    {
      if (c == '\n')
      if (c == '\n')
        break;
        break;
      if (c == '\\')
      if (c == '\\')
        {
        {
          rclex_readch ();
          rclex_readch ();
          if ((c = rclex_peekch ()) == -1 || c == '\n')
          if ((c = rclex_peekch ()) == -1 || c == '\n')
            break;
            break;
          rclex_readch ();
          rclex_readch ();
        }
        }
      else if (rclex_readch () == '"')
      else if (rclex_readch () == '"')
        {
        {
          /* PR 6714
          /* PR 6714
             Skip any whitespace after the end of the double quotes.  */
             Skip any whitespace after the end of the double quotes.  */
          do
          do
            {
            {
              c = rclex_peekch ();
              c = rclex_peekch ();
              if (ISSPACE (c))
              if (ISSPACE (c))
                rclex_readch ();
                rclex_readch ();
              else
              else
                c = -1;
                c = -1;
            }
            }
          while (c != -1);
          while (c != -1);
 
 
          if (rclex_peekch () == '"')
          if (rclex_peekch () == '"')
            rclex_readch ();
            rclex_readch ();
          else
          else
            break;
            break;
        }
        }
    }
    }
}
}
 
 
static rc_uint_type
static rc_uint_type
read_digit (int ch)
read_digit (int ch)
{
{
  rc_uint_type base = 10;
  rc_uint_type base = 10;
  rc_uint_type ret, val;
  rc_uint_type ret, val;
  int warned = 0;
  int warned = 0;
 
 
  ret = 0;
  ret = 0;
  if (ch == '0')
  if (ch == '0')
    {
    {
      base = 8;
      base = 8;
      switch (rclex_peekch ())
      switch (rclex_peekch ())
        {
        {
        case 'o': case 'O':
        case 'o': case 'O':
          rclex_readch ();
          rclex_readch ();
          base = 8;
          base = 8;
          break;
          break;
 
 
        case 'x': case 'X':
        case 'x': case 'X':
          rclex_readch ();
          rclex_readch ();
          base = 16;
          base = 16;
          break;
          break;
        }
        }
    }
    }
  else
  else
    ret = (rc_uint_type) (ch - '0');
    ret = (rc_uint_type) (ch - '0');
  while ((ch = rclex_peekch ()) != -1)
  while ((ch = rclex_peekch ()) != -1)
    {
    {
      if (ISDIGIT (ch))
      if (ISDIGIT (ch))
        val = (rc_uint_type) (ch - '0');
        val = (rc_uint_type) (ch - '0');
      else if (ch >= 'a' && ch <= 'f')
      else if (ch >= 'a' && ch <= 'f')
        val = (rc_uint_type) ((ch - 'a') + 10);
        val = (rc_uint_type) ((ch - 'a') + 10);
      else if (ch >= 'A' && ch <= 'F')
      else if (ch >= 'A' && ch <= 'F')
        val = (rc_uint_type) ((ch - 'A') + 10);
        val = (rc_uint_type) ((ch - 'A') + 10);
      else
      else
        break;
        break;
      rclex_readch ();
      rclex_readch ();
      if (! warned && val >= base)
      if (! warned && val >= base)
        {
        {
          warned = 1;
          warned = 1;
          rcparse_warning ("digit exceeds base");
          rcparse_warning ("digit exceeds base");
        }
        }
      ret *= base;
      ret *= base;
      ret += val;
      ret += val;
    }
    }
  return ret;
  return ret;
}
}
 
 
/* yyparser entry method.  */
/* yyparser entry method.  */
 
 
int
int
yylex (void)
yylex (void)
{
{
  char *s;
  char *s;
  unichar *us;
  unichar *us;
  rc_uint_type length;
  rc_uint_type length;
  int ch;
  int ch;
 
 
  /* Make sure that rclex_tok is initialized.  */
  /* Make sure that rclex_tok is initialized.  */
  if (! rclex_tok)
  if (! rclex_tok)
    rclex_tok_add_char (-1);
    rclex_tok_add_char (-1);
 
 
  do
  do
    {
    {
      do
      do
        {
        {
          /* Clear token.  */
          /* Clear token.  */
          rclex_tok_pos = 0;
          rclex_tok_pos = 0;
          rclex_tok[0] = 0;
          rclex_tok[0] = 0;
 
 
          if ((ch = rclex_readch ()) == -1)
          if ((ch = rclex_readch ()) == -1)
            return -1;
            return -1;
          if (ch == '\n')
          if (ch == '\n')
            ++rc_lineno;
            ++rc_lineno;
        }
        }
      while (ch <= 0x20);
      while (ch <= 0x20);
 
 
      switch (ch)
      switch (ch)
        {
        {
        case '#':
        case '#':
          while ((ch = rclex_peekch ()) != -1 && ch != '\n')
          while ((ch = rclex_peekch ()) != -1 && ch != '\n')
            rclex_readch ();
            rclex_readch ();
          cpp_line ();
          cpp_line ();
          ch = IGNORED_TOKEN;
          ch = IGNORED_TOKEN;
          break;
          break;
 
 
        case '{':
        case '{':
          ch = IGNORE_CPP (BEG);
          ch = IGNORE_CPP (BEG);
          break;
          break;
 
 
        case '}':
        case '}':
          ch = IGNORE_CPP (END);
          ch = IGNORE_CPP (END);
          break;
          break;
 
 
        case '0': case '1': case '2': case '3': case '4':
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
        case '5': case '6': case '7': case '8': case '9':
          yylval.i.val = read_digit (ch);
          yylval.i.val = read_digit (ch);
          yylval.i.dword = 0;
          yylval.i.dword = 0;
          switch (rclex_peekch ())
          switch (rclex_peekch ())
            {
            {
            case 'l': case 'L':
            case 'l': case 'L':
              rclex_readch ();
              rclex_readch ();
              yylval.i.dword = 1;
              yylval.i.dword = 1;
              break;
              break;
            }
            }
          ch = IGNORE_CPP (NUMBER);
          ch = IGNORE_CPP (NUMBER);
          break;
          break;
        case '"':
        case '"':
          rclex_string ();
          rclex_string ();
          ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDSTRING : SIZEDSTRING));
          ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDSTRING : SIZEDSTRING));
          if (ch == IGNORED_TOKEN)
          if (ch == IGNORED_TOKEN)
            break;
            break;
          s = handle_quotes (&length);
          s = handle_quotes (&length);
          if (! rcdata_mode)
          if (! rcdata_mode)
            yylval.s = s;
            yylval.s = s;
          else
          else
            {
            {
              yylval.ss.length = length;
              yylval.ss.length = length;
              yylval.ss.s = s;
              yylval.ss.s = s;
          }
          }
          break;
          break;
        case 'L': case 'l':
        case 'L': case 'l':
          if (rclex_peekch () == '"')
          if (rclex_peekch () == '"')
            {
            {
              rclex_readch ();
              rclex_readch ();
              rclex_string ();
              rclex_string ();
              ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDUNISTRING : SIZEDUNISTRING));
              ch = IGNORE_CPP ((! rcdata_mode ? QUOTEDUNISTRING : SIZEDUNISTRING));
              if (ch == IGNORED_TOKEN)
              if (ch == IGNORED_TOKEN)
                break;
                break;
              us = handle_uniquotes (&length);
              us = handle_uniquotes (&length);
              if (! rcdata_mode)
              if (! rcdata_mode)
                yylval.uni = us;
                yylval.uni = us;
              else
              else
                {
                {
                  yylval.suni.length = length;
                  yylval.suni.length = length;
                  yylval.suni.s = us;
                  yylval.suni.s = us;
              }
              }
              break;
              break;
            }
            }
          /* Fall through.  */
          /* Fall through.  */
        default:
        default:
          if (ISIDST (ch) || ch=='$')
          if (ISIDST (ch) || ch=='$')
            {
            {
              while ((ch = rclex_peekch ()) != -1
              while ((ch = rclex_peekch ()) != -1
                     && (ISIDNUM (ch) || ch == '$' || ch == '.'
                     && (ISIDNUM (ch) || ch == '$' || ch == '.'
                         || ch == ':' || ch == '\\' || ch == '/'
                         || ch == ':' || ch == '\\' || ch == '/'
                         || ch == '_' || ch == '-')
                         || ch == '_' || ch == '-')
                    )
                    )
                rclex_readch ();
                rclex_readch ();
              ch = IGNORE_CPP (rclex_translatekeyword (rclex_tok));
              ch = IGNORE_CPP (rclex_translatekeyword (rclex_tok));
              if (ch == STRING)
              if (ch == STRING)
                {
                {
                  s = get_string (strlen (rclex_tok) + 1);
                  s = get_string (strlen (rclex_tok) + 1);
                  strcpy (s, rclex_tok);
                  strcpy (s, rclex_tok);
                  yylval.s = s;
                  yylval.s = s;
                }
                }
              else if (ch == BLOCK)
              else if (ch == BLOCK)
                {
                {
                  const char *hs = NULL;
                  const char *hs = NULL;
 
 
                  switch (yylex ())
                  switch (yylex ())
                  {
                  {
                  case STRING:
                  case STRING:
                  case QUOTEDSTRING:
                  case QUOTEDSTRING:
                    hs = yylval.s;
                    hs = yylval.s;
                    break;
                    break;
                  case SIZEDSTRING:
                  case SIZEDSTRING:
                    hs = yylval.s = yylval.ss.s;
                    hs = yylval.s = yylval.ss.s;
                    break;
                    break;
                  }
                  }
                  if (! hs)
                  if (! hs)
                    {
                    {
                      rcparse_warning ("BLOCK expects a string as argument.");
                      rcparse_warning ("BLOCK expects a string as argument.");
                      ch = IGNORED_TOKEN;
                      ch = IGNORED_TOKEN;
                    }
                    }
                  else if (! strcmp (hs, "StringFileInfo"))
                  else if (! strcmp (hs, "StringFileInfo"))
                    ch = BLOCKSTRINGFILEINFO;
                    ch = BLOCKSTRINGFILEINFO;
                  else if (! strcmp (hs, "VarFileInfo"))
                  else if (! strcmp (hs, "VarFileInfo"))
                    ch = BLOCKVARFILEINFO;
                    ch = BLOCKVARFILEINFO;
                }
                }
              break;
              break;
            }
            }
          ch = IGNORE_CPP (ch);
          ch = IGNORE_CPP (ch);
          break;
          break;
        }
        }
    }
    }
  while (ch == IGNORED_TOKEN);
  while (ch == IGNORED_TOKEN);
 
 
  return ch;
  return ch;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.