(socket_connection): Remove AI_ADDRCONFIG.
[bpt/emacs.git] / lib-src / ebrowse.c
index b274a64..ea230a9 100644 (file)
@@ -1,17 +1,13 @@
 /* ebrowse.c --- parsing files for the ebrowse C++ browser
 
-   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-                2000, 2001
-      Free Software Foundation Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+                 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
-   Author: Gerd Moellmann <gerd@gnu.org>
-   Maintainer: FSF
-   
    This file is part of GNU Emacs.
 
    GNU Emacs is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GNU Emacs is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GNU Emacs; see the file COPYING.  If not, write to
-   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   along with GNU Emacs; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
 #include <string.h>
+#endif
+
 #include <ctype.h>
 #include <assert.h>
 #include "getopt.h"
 
+/* The SunOS compiler doesn't have SEEK_END.  */
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
 /* Conditionalize function prototypes.  */
 
 #ifdef PROTOTYPES              /* From config.h.  */
@@ -274,6 +283,8 @@ struct link
 struct alias
 {
   struct alias *next;          /* Next in list.  */
+  struct sym *namesp;          /* Namespace in which defined.  */
+  struct link *aliasee;                /* List of aliased namespaces (A::B::C...).  */
   char name[1];                        /* Alias name.  */
 };
 
@@ -298,7 +309,6 @@ struct sym
   char *filename;              /* File in which it can be found.  */
   char *sfilename;             /* File in which members can be found.  */
   struct sym *namesp;          /* Namespace in which defined. .  */
-  struct alias *namesp_aliases;        /* List of aliases for namespaces.  */
   char name[1];                 /* Name of the class.  */
 };
 
@@ -394,7 +404,7 @@ int inbuffer_size;
 
 #define BUFFER_POS() (in - inbuffer)
 
-/* If current lookahead is CSTRING, the following points to the 
+/* If current lookahead is CSTRING, the following points to the
    first character in the string constant.  Used for recognizing
    extern "C".  */
 
@@ -415,6 +425,10 @@ struct sym *class_table[TABLE_SIZE];
 
 struct member *member_table[TABLE_SIZE];
 
+/* Hash table for namespace aliases */
+
+struct alias *namespace_alias_table[TABLE_SIZE];
+
 /* The special class symbol used to hold global functions,
    variables etc.  */
 
@@ -486,7 +500,7 @@ void add_define P_ ((char *, char *, int));
 void mark_inherited_virtual P_ ((void));
 void leave_namespace P_ ((void));
 void enter_namespace P_ ((char *));
-void register_namespace_alias P_ ((char *, char *));
+void register_namespace_alias P_ ((char *, struct link *));
 void insert_keyword P_ ((char *, int));
 void re_init_scanner P_ ((void));
 void init_scanner P_ ((void));
@@ -503,7 +517,7 @@ struct member *find_member P_ ((struct sym *, char *, int, int, unsigned));
 struct member *add_member P_ ((struct sym *, char *, int, int, unsigned));
 void mark_virtual P_ ((struct sym *));
 void mark_virtual P_ ((struct sym *));
-struct sym *make_namespace P_ ((char *));
+struct sym *make_namespace P_ ((char *, struct sym *));
 char *sym_scope P_ ((struct sym *));
 char *sym_scope_1 P_ ((struct sym *));
 int skip_to P_ ((int));
@@ -519,6 +533,8 @@ struct sym *parse_qualified_ident_or_type P_ ((char **));
 void parse_qualified_param_ident_or_type P_ ((char **));
 int globals P_ ((int));
 void yyerror P_ ((char *, char *));
+void usage P_ ((int)) NO_RETURN;
+void version P_ (()) NO_RETURN;
 
 
 \f
@@ -550,7 +566,7 @@ xmalloc (nbytes)
   if (p == NULL)
     {
       yyerror ("out of memory", NULL);
-      exit (1);
+      exit (EXIT_FAILURE);
     }
   return p;
 }
@@ -567,7 +583,7 @@ xrealloc (p, sz)
   if (p == NULL)
     {
       yyerror ("out of memory", NULL);
-      exit (1);
+      exit (EXIT_FAILURE);
     }
   return p;
 }
@@ -634,7 +650,10 @@ add_sym (name, nested_in_class)
   h %= TABLE_SIZE;
 
   for (sym = class_table[h]; sym; sym = sym->next)
-    if (streq (name, sym->name) && sym->namesp == scope)
+    if (streq (name, sym->name)
+       && ((!sym->namesp && !scope)
+           || (sym->namesp && scope
+               && streq (sym->namesp->name, scope->name))))
       break;
 
   if (sym == NULL)
@@ -676,7 +695,7 @@ add_link (super, sub)
     {
       lnk = (struct link *) xmalloc (sizeof *lnk);
       lnk2 = (struct link *) xmalloc (sizeof *lnk2);
-  
+
       lnk->sym = sub;
       lnk->next = p;
 
@@ -718,15 +737,15 @@ find_member (cls, name, var, sc, hash)
     case SC_FRIEND:
       list = &cls->friends;
       break;
-      
+
     case SC_TYPE:
       list = &cls->types;
       break;
-      
+
     case SC_STATIC:
       list = var ? &cls->static_vars : &cls->static_fns;
       break;
-      
+
     default:
       list = var ? &cls->vars : &cls->fns;
       break;
@@ -918,7 +937,7 @@ add_global_defn (name, regexp, pos, hash, var, sc, flags)
    a bit set giving additional information about the member (see the
    F_* defines).  */
 
-void 
+void
 add_global_decl (name, regexp, pos, hash, var, sc, flags)
      char *name, *regexp;
      int pos;
@@ -998,15 +1017,15 @@ add_member (cls, name, var, sc, hash)
     case SC_FRIEND:
       list = &cls->friends;
       break;
-      
+
     case SC_TYPE:
       list = &cls->types;
       break;
-      
+
     case SC_STATIC:
       list = var ? &cls->static_vars : &cls->static_fns;
       break;
-      
+
     default:
       list = var ? &cls->vars : &cls->fns;
       break;
@@ -1080,68 +1099,107 @@ mark_inherited_virtual ()
 /* Create and return a symbol for a namespace with name NAME.  */
 
 struct sym *
-make_namespace (name)
+make_namespace (name, context)
      char *name;
+     struct sym *context;
 {
   struct sym *s = (struct sym *) xmalloc (sizeof *s + strlen (name));
   bzero (s, sizeof *s);
   strcpy (s->name, name);
   s->next = all_namespaces;
-  s->namesp = current_namespace;
+  s->namesp = context;
   all_namespaces = s;
   return s;
 }
 
 
-/* Find the symbol for namespace NAME.  If not found, add a new symbol
-   for NAME to all_namespaces.  */
+/* Find the symbol for namespace NAME.  If not found, retrun NULL */
 
 struct sym *
-find_namespace (name)
+check_namespace (name, context)
      char *name;
+     struct sym *context;
 {
-  struct sym *p;
-  
+  struct sym *p = NULL;
+
   for (p = all_namespaces; p; p = p->next)
     {
-      if (streq (p->name, name))
-       break;
-      else
-       {
-         struct alias *p2;
-         for (p2 = p->namesp_aliases; p2; p2 = p2->next)
-           if (streq (p2->name, name))
-             break;
-         if (p2)
+      if (streq (p->name, name) && (p->namesp == context))
            break;
        }
+
+  return p;
     }
 
+/* Find the symbol for namespace NAME.  If not found, add a new symbol
+   for NAME to all_namespaces.  */
+
+struct sym *
+find_namespace (name, context)
+     char *name;
+     struct sym *context;
+{
+  struct sym *p = check_namespace (name, context);
+
   if (p == NULL)
-    p = make_namespace (name);
+    p = make_namespace (name, context);
+
+  return p;
+}
+
+
+/* Find namespace alias with name NAME. If not found return NULL. */
+
+struct link *
+check_namespace_alias (name)
+    char *name;
+{
+  struct link *p = NULL;
+  struct alias *al;
+  unsigned h;
+  char *s;
+
+  for (s = name, h = 0; *s; ++s)
+    h = (h << 1) ^ *s;
+  h %= TABLE_SIZE;
+
+  for (al = namespace_alias_table[h]; al; al = al->next)
+    if (streq (name, al->name) && (al->namesp == current_namespace))
+      {
+        p = al->aliasee;
+        break;
+      }
 
   return p;
 }
-  
 
-/* Register the name NEW_NAME as an alias for namespace OLD_NAME.  */
+/* Register the name NEW_NAME as an alias for namespace list OLD_NAME.  */
 
 void
 register_namespace_alias (new_name, old_name)
-     char *new_name, *old_name;
+     char *new_name;
+     struct link *old_name;
 {
-  struct sym *p = find_namespace (old_name);
+  unsigned h;
+  char *s;
   struct alias *al;
 
-  /* Is it already in the list of aliases?  */
-  for (al = p->namesp_aliases; al; al = al->next)
-    if (streq (new_name, p->name))
+  for (s = new_name, h = 0; *s; ++s)
+    h = (h << 1) ^ *s;
+  h %= TABLE_SIZE;
+
+
+  /* Is it already in the table of aliases?  */
+  for (al = namespace_alias_table[h]; al; al = al->next)
+    if (streq (new_name, al->name) && (al->namesp == current_namespace))
       return;
 
   al = (struct alias *) xmalloc (sizeof *al + strlen (new_name));
   strcpy (al->name, new_name);
-  al->next = p->namesp_aliases;
-  p->namesp_aliases = al;
+  al->next = namespace_alias_table[h];
+  al->namesp = current_namespace;
+  al->aliasee = old_name;
+  namespace_alias_table[h] = al;
 }
 
 
@@ -1151,7 +1209,7 @@ void
 enter_namespace (name)
      char *name;
 {
-  struct sym *p = find_namespace (name);
+  struct sym *p = find_namespace (name, current_namespace);
 
   if (namespace_sp == namespace_stack_size)
     {
@@ -1161,7 +1219,7 @@ enter_namespace (name)
                                    size * sizeof *namespace_stack);
       namespace_stack_size = size;
     }
-  
+
   namespace_stack[namespace_sp++] = current_namespace;
   current_namespace = p;
 }
@@ -1233,7 +1291,7 @@ sym_scope_1 (p)
      struct sym *p;
 {
   int len;
-  
+
   if (p->namesp)
     sym_scope_1 (p->namesp);
 
@@ -1248,14 +1306,14 @@ sym_scope_1 (p)
   ensure_scope_buffer_room (len + 1);
   strcat (scope_buffer, p->name);
   scope_buffer_len += len;
-  
+
   if (HAS_FLAG (p->flags, F_TEMPLATE))
     {
       ensure_scope_buffer_room (3);
       strcat (scope_buffer, "<>");
       scope_buffer_len += 2;
     }
-  
+
   return scope_buffer;
 }
 
@@ -1272,10 +1330,10 @@ sym_scope (p)
       scope_buffer_size = 1024;
       scope_buffer = (char *) xmalloc (scope_buffer_size);
     }
-  
+
   *scope_buffer = '\0';
   scope_buffer_len = 0;
-  
+
   if (p->namesp)
     sym_scope_1 (p->namesp);
 
@@ -1328,13 +1386,13 @@ dump_sym (fp, root)
 {
   fputs (CLASS_STRUCT, fp);
   PUTSTR (root->name, fp);
-  
+
   /* Print scope, if any.  */
   if (root->namesp)
     PUTSTR (sym_scope (root), fp);
   else
     PUTSTR (NULL, fp);
-  
+
   /* Print flags.  */
   fprintf (fp, "%u", root->flags);
   PUTSTR (root->filename, fp);
@@ -1514,7 +1572,7 @@ process_pp_line ()
          add_define (yytext, regexp, pos);
        }
     }
-  
+
   while (c && (c != '\n' || in_comment || in_string))
     {
       if (c == '\\')
@@ -1531,7 +1589,7 @@ process_pp_line ()
        }
       else if (c == '"')
        in_string = !in_string;
-      
+
       if (c == '\n')
        INCREMENT_LINENO;
 
@@ -2001,7 +2059,7 @@ matching_regexp ()
     {
       *--s = *--t;
 
-      if (*s == '"')
+      if (*s == '"' || *s == '\\')
         *--s = '\\';
     }
 
@@ -2135,7 +2193,7 @@ re_init_scanner ()
 {
   in = inbuffer;
   yyline = 1;
-  
+
   if (yytext == NULL)
     {
       int size = 256;
@@ -2324,7 +2382,6 @@ skip_to (token)
   return tk;
 }
 
-
 /* Skip over pairs of tokens (parentheses, square brackets,
    angle brackets, curly brackets) matching the current lookahead.  */
 
@@ -2338,19 +2395,19 @@ skip_matching ()
     case '{':
       close = '}';
       break;
-      
+
     case '(':
       close = ')';
       break;
-      
+
     case '<':
       close = '>';
       break;
-      
+
     case '[':
       close = ']';
       break;
-      
+
     default:
       abort ();
     }
@@ -2371,6 +2428,67 @@ skip_matching ()
     }
 }
 
+void
+skip_initializer ()
+{
+  for (;;)
+    {
+      switch (LA1)
+       {
+       case ';':
+       case ',':
+       case YYEOF:
+         return;
+
+       case '{':
+       case '[':
+       case '(':
+         skip_matching ();
+         break;
+
+       default:
+         MATCH ();
+         break;
+       }
+    }
+}
+
+/* Build qualified namespace alias (A::B::c) and return it. */
+
+struct link *
+match_qualified_namespace_alias ()
+{
+  struct link *head = NULL;
+  struct link *cur = NULL;
+  struct link *tmp = NULL;
+
+  for (;;)
+    {
+      MATCH ();
+      switch (LA1)
+        {
+        case IDENT:
+          tmp = (struct link *) xmalloc (sizeof *cur);
+          tmp->sym = find_namespace (yytext, cur);
+          tmp->next = NULL;
+          if (head)
+            {
+              cur = cur->next = tmp;
+            }
+          else
+            {
+              head = cur = tmp;
+            }
+          break;
+        case DCOLON:
+          /* Just skip */
+          break;
+        default:
+          return head;
+          break;
+        }
+    }
+}
 
 /* Re-initialize the parser by resetting the lookahead token.  */
 
@@ -2398,7 +2516,7 @@ parm_list (flags)
     {
       switch (LA1)
         {
-         /* Skip over grouping parens or parameter lists in parameter 
+         /* Skip over grouping parens or parameter lists in parameter
             declarations.  */
         case '(':
           skip_matching ();
@@ -2420,7 +2538,7 @@ parm_list (flags)
             {
              char *last_id;
              unsigned ident_type_hash = 0;
-             
+
              parse_qualified_param_ident_or_type (&last_id);
              if (last_id)
                {
@@ -2448,7 +2566,7 @@ parm_list (flags)
         case DOUBLE:    case ENUM:      case FLOAT:     case INT:
         case LONG:      case SHORT:     case SIGNED:    case STRUCT:
         case UNION:     case UNSIGNED:  case VOLATILE:  case WCHAR:
-        case ELLIPSIS:  
+        case ELLIPSIS:
           type_seen = 1;
           hash = (hash << 1) ^ LA1;
           MATCH ();
@@ -2468,7 +2586,7 @@ parm_list (flags)
   if (LOOKING_AT (')'))
     {
       MATCH ();
-      
+
       if (LOOKING_AT (CONST))
         {
           /* We can overload the same function on `const' */
@@ -2553,7 +2671,7 @@ member (cls, vis)
         case EXPLICIT:
           SET_FLAG (flags, F_EXPLICIT);
           goto typeseen;
-          
+
         case MUTABLE:
           SET_FLAG (flags, F_MUTABLE);
           goto typeseen;
@@ -2688,7 +2806,7 @@ member (cls, vis)
         {
           regexp = matching_regexp ();
           pos = BUFFER_POS ();
-          
+
           if (cls != NULL)
             {
               if (type_seen || !paren_seen)
@@ -2697,7 +2815,7 @@ member (cls, vis)
                add_member_decl (cls, id, regexp, pos, hash, 0, sc, vis, 0);
             }
         }
-      
+
       MATCH ();
       print_info ();
     }
@@ -2794,7 +2912,7 @@ struct sym *
 parse_classname ()
 {
   struct sym *last_class = NULL;
-  
+
   while (LOOKING_AT (IDENT))
     {
       last_class = add_sym (yytext, last_class);
@@ -2805,10 +2923,10 @@ parse_classname ()
           skip_matching ();
           SET_FLAG (last_class->flags, F_TEMPLATE);
         }
-      
+
       if (!LOOKING_AT (DCOLON))
         break;
-      
+
       MATCH ();
     }
 
@@ -2828,7 +2946,7 @@ operator_name (sc)
   static char *id = NULL;
   char *s;
   int len;
-  
+
   MATCH ();
 
   if (LOOKING_AT2 (NEW, DELETE))
@@ -2839,7 +2957,7 @@ operator_name (sc)
 
       s = token_string (LA1);
       MATCH ();
-      
+
       len = strlen (s) + 10;
       if (len > id_size)
        {
@@ -2849,12 +2967,12 @@ operator_name (sc)
        }
       strcpy (id, s);
 
-      /* Vector new or delete? */
+      /* Vector new or delete?  */
       if (LOOKING_AT ('['))
        {
          strcat (id, "[");
          MATCH ();
-         
+
          if (LOOKING_AT (']'))
            {
              strcat (id, "]");
@@ -2908,7 +3026,7 @@ operator_name (sc)
 
 
 /* This one consumes the last IDENT of a qualified member name like
-   `X::Y::z'.  This IDENT is returned in LAST_ID.  Value if the
+   `X::Y::z'.  This IDENT is returned in LAST_ID.  Value is the
    symbol structure for the ident.  */
 
 struct sym *
@@ -2918,7 +3036,8 @@ parse_qualified_ident_or_type (last_id)
   struct sym *cls = NULL;
   char *id = NULL;
   size_t id_size = 0;
-  
+  int enter = 0;
+
   while (LOOKING_AT (IDENT))
     {
       int len = strlen (yytext) + 1;
@@ -2935,7 +3054,26 @@ parse_qualified_ident_or_type (last_id)
 
       if (LOOKING_AT (DCOLON))
        {
-         cls = add_sym (id, cls);
+         struct sym *pcn = NULL;
+         struct link *pna = check_namespace_alias (id);
+         if (pna)
+           {
+             do
+               {
+                 enter_namespace (pna->sym->name);
+                 enter++;
+                 pna = pna->next;
+               }
+             while (pna);
+           }
+         else if ((pcn = check_namespace (id, current_namespace)))
+           {
+             enter_namespace (pcn->name);
+             enter++;
+           }
+         else
+           cls = add_sym (id, cls);
+
          *last_id = NULL;
          xfree (id);
          id = NULL;
@@ -2946,12 +3084,15 @@ parse_qualified_ident_or_type (last_id)
        break;
     }
 
+  while (enter--)
+    leave_namespace();
+
   return cls;
 }
 
 
 /* This one consumes the last IDENT of a qualified member name like
-   `X::Y::z'.  This IDENT is returned in LAST_ID.  Value if the
+   `X::Y::z'.  This IDENT is returned in LAST_ID.  Value is the
    symbol structure for the ident.  */
 
 void
@@ -3012,7 +3153,7 @@ class_definition (containing, tag, flags, nested)
      settings.  */
   if ((tag != CLASS && !f_structs) || (nested && !f_nested_classes))
     current = NULL;
-  else 
+  else
     {
       current = add_sym (yytext, containing);
       current->pos = BUFFER_POS ();
@@ -3031,7 +3172,7 @@ class_definition (containing, tag, flags, nested)
         {
           switch (LA1)
             {
-            case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE: 
+            case VIRTUAL: case PUBLIC: case PROTECTED: case PRIVATE:
               MATCH ();
               break;
 
@@ -3093,6 +3234,54 @@ class_definition (containing, tag, flags, nested)
     }
 }
 
+/* Add to class *CLS information for the declaration of variable or
+   type *ID.  If *CLS is null, this means a global declaration.  SC is
+   the storage class of *ID.  FLAGS is a bit set giving additional
+   information about the member (see the F_* defines).  */
+
+void
+add_declarator (cls, id, flags, sc)
+     struct sym **cls;
+     char **id;
+     int flags, sc;
+{
+  if (LOOKING_AT2 (';', ','))
+    {
+      /* The end of a member variable or of an access declaration
+         `X::f'.  To distinguish between them we have to know whether
+         type information has been seen.  */
+      if (*id)
+        {
+          char *regexp = matching_regexp ();
+          int pos = BUFFER_POS ();
+
+          if (*cls)
+           add_member_defn (*cls, *id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
+          else
+            add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
+        }
+
+      MATCH ();
+      print_info ();
+    }
+  else if (LOOKING_AT ('{'))
+    {
+      if (sc == SC_TYPE && *id)
+        {
+          /* A named enumeration.  */
+          char *regexp = matching_regexp ();
+          int pos = BUFFER_POS ();
+          add_global_defn (*id, regexp, pos, 0, 1, sc, flags);
+        }
+
+      skip_matching ();
+      print_info ();
+    }
+
+  xfree (*id);
+  *id = NULL;
+  *cls = NULL;
+}
 
 /* Parse a declaration.  */
 
@@ -3125,7 +3314,7 @@ declaration (flags)
           sc = SC_TYPE;
           MATCH ();
           break;
-          
+
         case STATIC:
           sc = SC_STATIC;
           MATCH ();
@@ -3147,11 +3336,15 @@ declaration (flags)
            }
 
         case '=':
-          /* Assumed to be the start of an initialization in this context.
-             Skip over everything up to ';'.  */
-          skip_to (';');
+          /* Assumed to be the start of an initialization in this
+            context.  */
+         skip_initializer ();
           break;
 
+       case ',':
+         add_declarator (&cls, &id, flags, sc);
+         break;
+
         case OPERATOR:
          {
            char *s = operator_name (&sc);
@@ -3238,40 +3431,7 @@ declaration (flags)
         }
     }
 
-  if (LOOKING_AT (';'))
-    {
-      /* The end of a member variable or of an access declaration
-         `X::f'.  To distinguish between them we have to know whether
-         type information has been seen.  */
-      if (id)
-        {
-          char *regexp = matching_regexp ();
-          int pos = BUFFER_POS ();
-
-          if (cls)
-           add_member_defn (cls, id, regexp, pos, 0, 1, SC_UNKNOWN, flags);
-          else
-            add_global_defn (id, regexp, pos, 0, 1, sc, flags);
-        }
-        
-      MATCH ();
-      print_info ();
-    }
-  else if (LOOKING_AT ('{'))
-    {
-      if (sc == SC_TYPE && id)
-        {
-          /* A named enumeration.  */
-          regexp = matching_regexp ();
-          pos = BUFFER_POS ();
-          add_global_defn (id, regexp, pos, 0, 1, sc, flags);
-        }
-
-      skip_matching ();
-      print_info ();
-    }
-
-  xfree (id);
+  add_declarator (&cls, &id, flags, sc);
 }
 
 
@@ -3291,7 +3451,7 @@ globals (start_flags)
   for (;;)
     {
       char *prev_in = in;
-      
+
       switch (LA1)
         {
         case NAMESPACE:
@@ -3302,13 +3462,13 @@ globals (start_flags)
               {
                 char *namespace_name = xstrdup (yytext);
                 MATCH ();
-                
+
                 if (LOOKING_AT ('='))
                   {
-                   MATCH ();
-                   if (LOOKING_AT (IDENT))
-                     register_namespace_alias (namespace_name, yytext);
-                     
+                   struct link *qna = match_qualified_namespace_alias ();
+                   if (qna)
+                      register_namespace_alias (namespace_name, qna);
+
                     if (skip_to (';') == ';')
                       MATCH ();
                   }
@@ -3333,7 +3493,7 @@ globals (start_flags)
             {
               /* This is `extern "C"'.  */
               MATCH ();
-              
+
               if (LOOKING_AT ('{'))
                 {
                   MATCH ();
@@ -3344,7 +3504,7 @@ globals (start_flags)
                 SET_FLAG (flags, F_EXTERNC);
             }
           break;
-          
+
         case TEMPLATE:
           MATCH ();
           SKIP_MATCHING_IF ('<');
@@ -3384,7 +3544,7 @@ globals (start_flags)
 
         case '}':
           return 0;
-          
+
         default:
           declaration (flags);
           flags = start_flags;
@@ -3423,10 +3583,10 @@ add_search_path (path_list)
     {
       char *start = path_list;
       struct search_path *p;
-      
+
       while (*path_list && *path_list != PATH_LIST_SEPARATOR)
         ++path_list;
-      
+
       p = (struct search_path *) xmalloc (sizeof *p);
       p->path = (char *) xmalloc (path_list - start + 1);
       memcpy (p->path, start, path_list - start);
@@ -3460,7 +3620,7 @@ open_file (file)
   static int buffer_size;
   struct search_path *path;
   int flen = strlen (file) + 1;        /* +1 for the slash */
-  
+
   filename = xstrdup (file);
 
   for (path = search_path; path && fp == NULL; path = path->next)
@@ -3472,20 +3632,20 @@ open_file (file)
          buffer_size = max (len + 1, 2 * buffer_size);
          buffer = (char *) xrealloc (buffer, buffer_size);
        }
-       
+
       strcpy (buffer, path->path);
       strcat (buffer, "/");
       strcat (buffer, file);
       fp = fopen (buffer, "r");
     }
-  
+
   /* Try the original file name.  */
   if (fp == NULL)
      fp = fopen (file, "r");
 
   if (fp == NULL)
     yyerror ("cannot open", NULL);
-  
+
   return fp;
 }
 
@@ -3516,7 +3676,7 @@ usage (error)
      int error;
 {
   puts (USAGE);
-  exit (error ? 1 : 0);
+  exit (error ? EXIT_FAILURE : EXIT_SUCCESS);
 }
 
 
@@ -3531,9 +3691,9 @@ void
 version ()
 {
   printf ("ebrowse %s\n", VERSION);
-  puts ("Copyright (C) 1992-1999, 2000 Free Software Foundation, Inc.");
+  puts ("Copyright (C) 1992-2007 Free Software Foundation, Inc.");
   puts ("This program is distributed under the same terms as Emacs.");
-  exit (0);
+  exit (EXIT_SUCCESS);
 }
 
 
@@ -3545,10 +3705,10 @@ process_file (file)
      char *file;
 {
   FILE *fp;
-  
+
   fp = open_file (file);
   if (fp)
-    {      
+    {
       int nread, nbytes;
 
       /* Give a progress indication if needed.  */
@@ -3571,7 +3731,7 @@ process_file (file)
              inbuffer_size = nread + READ_CHUNK_SIZE + 1;
              inbuffer = (char *) xrealloc (inbuffer, inbuffer_size);
            }
-         
+
          nbytes = fread (inbuffer + nread, 1, READ_CHUNK_SIZE, fp);
          if (nbytes <= 0)
            break;
@@ -3614,10 +3774,10 @@ read_line (fp)
 
       buffer[i++] = c;
     }
-  
+
   if (c == EOF && i == 0)
     return NULL;
-  
+
   if (i == buffer_size)
     {
       buffer_size = max (100, buffer_size * 2);
@@ -3657,7 +3817,7 @@ main (argc, argv)
        case 'p':
          info_position = atoi (optarg);
          break;
-         
+
         case 'n':
           f_nested_classes = 0;
           break;
@@ -3665,7 +3825,7 @@ main (argc, argv)
         case 'x':
           f_regexps = 0;
           break;
-        
+
           /* Add the name of a file containing more input files.  */
         case 'f':
          if (n_input_files == input_filenames_size)
@@ -3751,26 +3911,40 @@ main (argc, argv)
 
          fp = fopen (out_filename, "r");
          if (fp == NULL)
-           yyerror ("file `%s' must exist for --append", out_filename);
+           {
+             yyerror ("file `%s' must exist for --append", out_filename);
+             exit (EXIT_FAILURE);
+           }
 
          rc = fseek (fp, 0, SEEK_END);
          if (rc == -1)
-           yyerror ("error seeking in file `%s'", out_filename);
+           {
+             yyerror ("error seeking in file `%s'", out_filename);
+             exit (EXIT_FAILURE);
+           }
 
          rc = ftell (fp);
          if (rc == -1)
-           yyerror ("error getting size of file `%s'", out_filename);
-         else if (rc == 0)
-           yyerror ("file `%s' is empty", out_filename);
+           {
+             yyerror ("error getting size of file `%s'", out_filename);
+             exit (EXIT_FAILURE);
+           }
          
+         else if (rc == 0)
+           {
+             yyerror ("file `%s' is empty", out_filename);
+             /* It may be ok to use an empty file for appending.
+                exit (EXIT_FAILURE); */
+           }
+
          fclose (fp);
        }
-      
+
       yyout = fopen (out_filename, f_append ? "a" : "w");
       if (yyout == NULL)
        {
          yyerror ("cannot open output file `%s'", out_filename);
-         exit (1);
+         exit (EXIT_FAILURE);
        }
     }
 
@@ -3795,7 +3969,7 @@ main (argc, argv)
       for (i = 0; i < n_input_files; ++i)
         {
           FILE *fp = fopen (input_filenames[i], "r");
-          
+
           if (fp == NULL)
             yyerror ("cannot open input file `%s'", input_filenames[i]);
           else
@@ -3815,8 +3989,10 @@ main (argc, argv)
   if (yyout != stdout)
     fclose (yyout);
 
-  return 0;
+  return EXIT_SUCCESS;
 }
 
+/* arch-tag: fc03b4bc-91a9-4c3d-b3b9-12a77fa86dd8
+   (do not change this comment) */
 
-/* ebrowse.c ends here */
+/* ebrowse.c ends here */