%{
/* ########################################################################

			      BR_Parser.y

   ########################################################################

   Copyright (c) : Dominique Leveque

   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
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   ######################################################################## */


#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <setjmp.h>
#include <signal.h>

#include "proto_decl.h"

#include "BR_Global.h"
#include "BR_Lexer.h"
#include "BR_Parser.h"
#include "BR_Interface.h"


   /*-----------------------------------------------------------------------*/

#ifndef yyparse
#define yyparse  BR_yyparse
#define yyerror  BR_yyerror
#define yydebug  BR_yydebug
#define yynerrs  BR_yynerrs
#define yychar   BR_yychar
#endif


   /*-----------------------------------------------------------------------*/

#define YYDEBUG                 1

#define BR_YYERROR              YYFAIL


   /*-----------------------------------------------------------------------*/

FCT (int, yyerror, (char*) );


#if YYDEBUG != 0

#define YYPRINT(f, t, v)        BR_yyprint(f, t, v)
static
FCT (int, BR_yyprint, (FILE*, int, YYSTYPE) );

static
FCT (void, BR_dump_tree, (BR_Str*, BR_TokenPt) );

#endif


   /*-----------------------------------------------------------------------*/

static char* basic_value[] =
{
  /*   0  (signed)? int         */      "int ",
  /*   1  (signed)? char        */      "char ",
  /*   2  (signed)? short       */      "short ",
  /*   3  (signed)? long        */      "long ",
  /*   4  unsigned              */      "unsigned int ",
  /*   5  unsigned char         */      "unsigned char ",
  /*   6  unsigned short        */      "unsigned short ",
  /*   7  unsigned long         */      "unsigned long ",
  /*   8  const (signed)? int   */      "const int ",
  /*   9  const (signed)? char  */      "const char ",
  /*  10  const (signed)? short */      "const short ",
  /*  11  const (signed)? long  */      "const long ",
  /*  12  const unsigned        */      "const unsigned int ",
  /*  13  const unsigned char   */      "const unsigned char ",
  /*  14  const unsigned short  */      "const unsigned short ",
  /*  15  const unsigned long   */      "const unsigned long "
};

static int basic_length[] =
{
  /*   0  */   3,
  /*   1  */   4,                   
  /*   2  */   5,
  /*   3  */   4,
  /*   4  */   12,
  /*   5  */   13,
  /*   6  */   14,
  /*   7  */   13,
  /*   8  */   9,
  /*   9  */   10,
  /*  10  */   11,
  /*  11  */   10,
  /*  12  */   18,
  /*  13  */   19,
  /*  14  */   20,
  /*  15  */   19
};

#define CONVERT_BASIC(x)        \
   (x->_val     = basic_value[x->_bits],   \
    x->_val_len = basic_length[x->_bits],  \
    x)


   /*-----------------------------------------------------------------------*/

static BR_TokenPt xl1;
static BR_TokenPt xl2;
static BR_TokenPt xl3;
static BR_TokenPt xl4;
static BR_TokenPt xl5;

#define APPEND2(x1,x2)              ((xl1 = x1)->_last->_next = (xl2 = x2),  \
                                     xl1->_last               = xl2->_last,  \
                                     xl1)

#define APPEND3(x1,x2,x3)           ((xl1 = x1)->_last->_next = (xl2 = x2),  \
                                     xl2->_last->_next        = (xl3 = x3),  \
                                     xl1->_last               = xl3->_last,  \
                                     xl1)

#define APPEND4(x1,x2,x3,x4)        ((xl1 = x1)->_last->_next = (xl2 = x2),  \
                                     xl2->_last->_next        = (xl3 = x3),  \
                                     xl3->_last->_next        = (xl4 = x4),  \
                                     xl1->_last               = xl4->_last,  \
                                     xl1)

#define APPEND5(x1,x2,x3,x4,x5)     ((xl1 = x1)->_last->_next = (xl2 = x2),  \
                                     xl2->_last->_next        = (xl3 = x3),  \
                                     xl3->_last->_next        = (xl4 = x4),  \
                                     xl4->_last->_next        = (xl5 = x5),  \
                                     xl1->_last               = xl5->_last,  \
                                     xl1)


   /*-----------------------------------------------------------------------*/

#define STR_FCT_PT              "(*) ( "
#define STR_ANONYMOUS           "??? "
#define STR_PREFIX              ":: "
#define STR_CONST               "const "


#define ACCESS_BITS             (  BR_INFO_PRIVATE     \
				 | BR_INFO_PUBLIC      \
				 | BR_INFO_PROTECTED)

#define AGGREGATE_BITS          (  BR_INFO_CLASS       \
				 | BR_INFO_STRUCT      \
				 | BR_INFO_UNION       \
                                 | BR_INFO_ENUM)

#define PROC_DEF_BITS           (  BR_INFO_OPERATOR    \
                                 | BR_INFO_CONSTRUCTOR \
                                 | BR_INFO_DESTRUCTOR  \
                                 | BR_INFO_FRIEND)


   /*-----------------------------------------------------------------------*/

#define CONTROL_PARENT          (~(  ACCESS_BITS    | BR_INFO_VIRTUAL        \
                                   | BR_INFO_PARENT))

#define CONTROL_AGGREGATE       (~(  ACCESS_BITS    | AGGREGATE_BITS         \
                                   | BR_INFO_DEF    | BR_INFO_TEMPLATE       \
                                   | BR_INFO_FRIEND | BR_INFO_TYPEDEF))

#define CONTROL_TYPEDEF         (~(  ACCESS_BITS    | BR_INFO_TYPEDEF        \
                                   | BR_INFO_PROC   | BR_INFO_DATA           \
                                   | BR_INFO_STATIC | BR_INFO_EXTERN         \
                                   | BR_INFO_DEF    | BR_INFO_FRIEND))
                                 
#define CONTROL_PROC            (~(  ACCESS_BITS    | BR_INFO_PROC           \
                                   | BR_INFO_STATIC | BR_INFO_EXTERN         \
                                   | BR_INFO_INLINE | BR_INFO_TEMPLATE       \
                                   | BR_INFO_CONST  | BR_INFO_CONSTRUCTOR    \
                                   | BR_INFO_C      | BR_INFO_DESTRUCTOR     \
                                   | BR_INFO_FRIEND | BR_INFO_OPERATOR       \
                                   | BR_INFO_PURE   | BR_INFO_VIRTUAL        \
                                   | BR_INFO_DEF))

#define CONTROL_FRIEND_PROC     (~(  BR_INFO_FRIEND | BR_INFO_DEF            \
				   | BR_INFO_PROC   | BR_INFO_OPERATOR       \
                                   | BR_INFO_CONST))

#define CONTROL_DATA            (~(  ACCESS_BITS    | BR_INFO_DATA           \
                                   | BR_INFO_STATIC | BR_INFO_EXTERN         \
                                   | BR_INFO_DEF))


   /*-----------------------------------------------------------------------*/

#define TEST_BITS(val,bits)     ((val & (bits)) != 0)

#define CLEAR_BITS(val,bits)    (val &= ~(bits))

#define SET_BITS(val,bits)      (val |= bits)


   /*-----------------------------------------------------------------------*/

#define STACK_PREFIX(x)      \
  {                                                                      \
    if (global_prefix == BR_Null)                                        \
      global_prefix = x;                                                 \
    else                                                                 \
    {                                                                    \
      alloc_token   = ALLOC_TOKEN(T_PREFIX, STR_PREFIX);                 \
      last_token    = global_prefix->_last;                              \
      global_prefix = APPEND3(global_prefix, alloc_token, x);            \
      x->_last      = last_token;                                        \
    }                                                                    \
    global_prefix->_last->_line_num = prefix_stamp++;                    \
  }

#define UNSTACK_PREFIX()     \
  {                                                                      \
    if (global_prefix->_last == global_prefix)                           \
      global_prefix = BR_Null;                                           \
    else                                                                 \
    {                                                                    \
      global_prefix->_last        = global_prefix->_last->_last;         \
      global_prefix->_last->_next = BR_Null;                             \
    }                                                                    \
  }


   /*-----------------------------------------------------------------------*/

#define S_PRECED       10
#define A_PRECED       10
#define P_PRECED       10
#define F_PRECED       20
#define T_PRECED       20


#define SET_PRECED(x, preced)        (x->_line_num = preced)

#define GET_PRECED(x)                (x->_line_num)

#define TEST_PRECED(x, preced)   \
  if ((x->_code == '(') && (x->_line_num >= preced))              \
  {                                                               \
    (void) CLEAR_FIRST_TOK(x);                                    \
    (void) CLEAR_LAST_TOK(x);                                     \
  }


   /*-----------------------------------------------------------------------*/

static BR_TokenPt   default_token   = BR_Null;
static BR_TokenRec  tmp_token;

static BR_TokenPt   global_prefix   = BR_Null;
static BR_TokenPt   alloc_token     = BR_Null;
static BR_TokenPt   last_token      = BR_Null;

static BR_TokenPt   template_args   = BR_Null;
static BR_Boolean   template_flag   = BR_FALSE;

static BR_Str       prefix_buffer[1024];
static BR_Str       SU_buffer[4 * 1024];

static BR_Int       prefix_stamp    = 1;
static BR_Int       last_stamp      = 0;
static BR_Int       prefix_len      = 0;

BR_InfoHandler      BR_info_handler = BR_Null;


static jmp_buf      BR_env;

static void (*BR_sigill_handler)  ();
static void (*BR_sigbus_handler)  ();
static void (*BR_sigsegv_handler) ();


   /*-----------------------------------------------------------------------*/

#define IS_EMPTY(x)             (x == BR_Null)

#define SPACE(x)                ((x->_last->_val_len)++, x)

#define CLEAR_FIRST_TOK(x)      (x->_val_len = 0, x)
#define CLEAR_LAST_TOK(x)       (x->_last->_val_len = 0, x)

#define CORRECT_VAL(x, str)     (x->_val     = str,                          \
			         x->_val_len = sizeof(str) - 2,              \
			         x)

#define ALLOC_TOKEN(c, s)       (BR_lex_alloc_token(c, s, sizeof(s) - 2))

#define SET_ACCESS(bits)    (CLEAR_BITS(default_token->_bits, ACCESS_BITS),  \
			     SET_BITS(default_token->_bits, bits),           \
			     CLEAR_BITS(default_token->_val_len,ACCESS_BITS),\
			     SET_BITS(default_token->_val_len, bits))

#define CLEAR_TEMPLATE()        \
  if (template_args != BR_Null)                                              \
  {                                                                          \
    template_args = BR_Null;                                                 \
    default_token = BR_lex_unstack_frame();                                  \
  }                                                                          \
  template_flag = BR_FALSE;                                                  \
  BR_lex_empty_frame();


   /*-----------------------------------------------------------------------*/

static
FCT (void, BR_replace_template_args, (BR_TokenPt token) );

static
FCT (void, BR_format_SU, (BR_TokenPt SU_tree, BR_ULong default_info) );


   /*-----------------------------------------------------------------------*/
%}

%start     SU_List

%right     '*' '&'
%left      T_ARRAY 
%nonassoc  '('
%token     T_PREFIX T_ELLIPSIS T_OPERATOR
%token     T_STRUCT T_UNION T_CLASS T_ENUM 
%token     T_PUBLIC T_PROTECTED T_PRIVATE
%token     T_IDENT T_TEMPLATE T_BASIC T_TEMPLATE_ARG
%token     T_FRAME T_CONST T_FRIEND
%token     T_LEXER_ERROR


%%

   /*-----------------------------------------------------------------------*/

SU_List
  :
        { BR_lex_save_state(); }
  | SU_List ';'
        { BR_lex_empty_frame(); }

  | SU_List TDeclarator_Bit_List ';'
        { BR_lex_empty_frame(); }
    
  | SU_List Decl_Def ';'
        { BR_lex_empty_frame(); }
  | SU_List Template Decl_Def ';'
        { CLEAR_TEMPLATE(); }

  | SU_List Code_Def
        {  BR_lex_empty_frame(); }
  | SU_List Template Code_Def
        { CLEAR_TEMPLATE(); }

  | SU_List Aggregate ';'
        { BR_lex_empty_frame(); }
  | SU_List Template Aggregate ';'
        { CLEAR_TEMPLATE(); }

  | SU_List Agg_Specifier ';'
        {
          BR_format_SU($2, (default_token->_bits | $2->_bits));
          BR_lex_empty_frame();
        }
  | SU_List Template Agg_Specifier ';'
        {
          BR_format_SU($3, (default_token->_bits | $3->_bits));
          CLEAR_TEMPLATE();
        }

  | SU_List Extern_Block

  | SU_List Template error ';'
        { CLEAR_TEMPLATE();     BR_lex_synchronize(); }
  | SU_List Template error '{' '}'
        { CLEAR_TEMPLATE();     BR_lex_synchronize(); }
  | SU_List error ';'
        { BR_lex_empty_frame(); BR_lex_synchronize(); }
  | SU_List error '{' '}'
        { BR_lex_empty_frame(); BR_lex_synchronize(); }
  ;


   /*-----------------------------------------------------------------------*/

Decl_Def
  : Qualified TDeclarator_Bit_List
  | Bit_Specifier TDeclarator_Bit_List
  | Agg_Specifier TDeclarator_List
  | Aggregate TDeclarator_List
  ;


   /*-----------------------------------------------------------------------*/

Code_Def
  : TDeclarator Code
        { BR_format_SU($1, (default_token->_bits | $2->_bits)); }
  | Qualified TDeclarator Code
        { BR_format_SU($2, (default_token->_bits | $3->_bits)); }
  | Bit_Specifier TDeclarator Code
        { BR_format_SU($2, (default_token->_bits | $3->_bits)); }
  | Agg_Specifier TDeclarator Code
        { BR_format_SU($2, (default_token->_bits | $3->_bits)); }
  ;


   /*-----------------------------------------------------------------------*/

Extern_Block
  :
        {
          if (TEST_BITS(default_token->_bits, BR_INFO_EXTERN))
          {
	    default_token = BR_lex_stack_frame(BR_INFO_EXTERN);
	    BR_lex_jump_bracket();
	  }
          else
            BR_YYERROR;
        }
    '{' SU_List '}'
        {
          default_token = BR_lex_unstack_frame();
          CLEAR_BITS(default_token->_bits, BR_INFO_EXTERN);
        }
  ;


   /*-----------------------------------------------------------------------*/

Prefix
  : T_IDENT T_PREFIX
        {
          $1->_line_num = prefix_stamp++;
	  $$ = APPEND2($1, $2);
        }
  | Prefix T_IDENT T_PREFIX
        {
          $2->_line_num = $1->_line_num;
          $$ = APPEND3($1, $2, $3);
        }
  ;


   /*-----------------------------------------------------------------------*/

Qualified
  : T_IDENT
        {
          $1->_prefix = BR_Null;
          $$ = $1;
	}
  | Prefix T_IDENT
        {
          $2->_prefix = $1;
          $$ = $2;
        }
  ;


   /*-----------------------------------------------------------------------*/

Init
  :
        { $$ = BR_Null; }
  | '='
        { $$ = &tmp_token; }
  | '=' '{' '}'
        { $$ = &tmp_token; }
  ;


   /*-----------------------------------------------------------------------*/

Code
  : '{' '}'
        { $$ = &tmp_token; $$->_bits = (BR_INFO_PROC | BR_INFO_DEF); }
  | { BR_lex_ignore_proc_tail(); } ':' '{' '}'
        { $$ = &tmp_token; $$->_bits = (BR_INFO_PROC | BR_INFO_DEF); }
  | { BR_lex_ignore_proc_tail(); } C_Arg_Specifier '{' '}'
        { $$ = &tmp_token; $$->_bits = (BR_INFO_PROC | BR_INFO_DEF | BR_INFO_C); }
  ;


   /*-----------------------------------------------------------------------*/

C_Arg_Specifier
 : Basic
 | T_ENUM
 | T_CLASS
 | T_STRUCT
 | T_UNION
 | Qualified
 ;

   /*-----------------------------------------------------------------------*/

Template
  : T_TEMPLATE '>'
        {
          template_flag = BR_TRUE;
          template_args = BR_Null;
        }
  | T_TEMPLATE Template_List '>'
        { 
          template_flag = BR_TRUE;
          template_args = $2;
          default_token = BR_lex_stack_frame(BR_INFO_EMPTY);
        }
  ;


   /*-----------------------------------------------------------------------*/

Template_List
  : T_TEMPLATE_ARG
        { $$ = $1; }
  | Template_List T_TEMPLATE_ARG
        { $$ = APPEND2($1, $2); }
  ;
  

   /*-----------------------------------------------------------------------*/

Bit_Specifier
  : T_ENUM   T_IDENT
        { $$ = $2; }
  | Basic
        { $$ = CONVERT_BASIC($1); }
  ;


   /*-----------------------------------------------------------------------*/

Agg_Specifier
  : T_CLASS  T_IDENT
        {
          $$ = $2;
          $$->_bits = BR_INFO_CLASS;
        }
  | T_STRUCT T_IDENT
        {
          $$ = $2;
          $$->_bits = BR_INFO_STRUCT;
        }
  | T_UNION  T_IDENT
        {
          $$ = $2;
          $$->_bits = BR_INFO_UNION;
        }
  ;


   /*-----------------------------------------------------------------------*/

Basic
  : T_BASIC
        { $$ = $1; }
  | Basic T_BASIC
        { $$ = $1; SET_BITS($$->_bits, $2->_bits); }
  ;


   /*-----------------------------------------------------------------------*/

Full_Arg_List
  : '(' ')'
        { $$ = APPEND2($1, $2); }
  | '(' Arg_List ')'
        { 
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND4($1, SPACE(alloc_token), $2, $3))
		  : APPEND3($1, $2, $3));
        }
  | '(' T_ELLIPSIS ')'
        { 
          $$ = APPEND3($1, $2, $3);
        }
  | '(' Arg_List ',' T_ELLIPSIS ')' 
        { 
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND5($1, SPACE(alloc_token), SPACE($2), $4, $5))
		  : APPEND4($1, SPACE($2), $4, $5));
        }
  | '(' Arg_List T_ELLIPSIS ')'
        { 
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND5($1, SPACE(alloc_token), SPACE($2), $3, $4))
		  : APPEND4($1, SPACE($2), $3, $4));
        }
  ;


   /*-----------------------------------------------------------------------*/

Arg_List
  : Arg Init
        { $$ = $1; }
  | Arg_List ',' Arg Init
        {
          $$ = ((TEST_BITS($2->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND4($1, SPACE($2), SPACE(alloc_token), $3))
		  : APPEND3($1, SPACE($2), $3));
        }
  ;


   /*-----------------------------------------------------------------------*/

Arg
  : Bit_Specifier
        { $$ = $1; }
  | Agg_Specifier
        { $$ = $1; }
  | Qualified
        {
          if (template_args != BR_Null)
            BR_replace_template_args($1);
          $$ = $1;
        }

  | Bit_Specifier ADeclarator
        { $$ = APPEND2(SPACE($1), $2); }
  | Agg_Specifier ADeclarator
        { $$ = APPEND2(SPACE($1), $2); }
  | Qualified ADeclarator
        {
          if (template_args != BR_Null)
            BR_replace_template_args($1);
          $$ = APPEND2(SPACE($1), $2);
        }

  | Bit_Specifier Qualified
        { $$ = $1; }
  | Agg_Specifier Qualified
        { $$ = $1; }
  | Qualified Qualified
        {
          if (template_args != BR_Null)
            BR_replace_template_args($1);
          $$ = $1;
        }
  ;


   /*-----------------------------------------------------------------------*/

ADeclarator
           /*---------------------------------------------------------------*/
  : '*'
        {
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND2(SPACE($1), alloc_token))
		  : $1);
          SET_PRECED($$, S_PRECED);
        }
  | '&'
        {
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND2(SPACE($1), alloc_token))
		  : $1);
          SET_PRECED($$, A_PRECED);
        }
  | Prefix '*'
        {
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND3($1, SPACE($2), alloc_token))
		  : APPEND2($1, $2));
          SET_PRECED($$, P_PRECED);
        }
  | Full_Arg_List
        {
          $$ = CORRECT_VAL($1, STR_FCT_PT);
          SET_PRECED($$, F_PRECED);
        }
  | T_ARRAY
        { $$ = $1; SET_PRECED($$, T_PRECED); }

           /*---------------------------------------------------------------*/
  | '*' Qualified
        {
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND2(SPACE($1), alloc_token))
		  : $1);
          SET_PRECED($$, S_PRECED);
        }
  | '&' Qualified
        {
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND2(SPACE($1), alloc_token))
		  : $1);
          SET_PRECED($$, A_PRECED);
        }
  | Prefix '*' Qualified
        {
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND3($1, SPACE($2), alloc_token))
		  : APPEND2($1, $2));
          SET_PRECED($$, P_PRECED);
        }
  | Qualified Full_Arg_List
        {
          $$ = CORRECT_VAL($2, STR_FCT_PT);
          SET_PRECED($$, F_PRECED);
        }
  | Qualified T_ARRAY
        { $$ = $2; SET_PRECED($$, T_PRECED); }

           /*---------------------------------------------------------------*/
  | '*' ADeclarator
        {
          TEST_PRECED($2, S_PRECED);
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND3(SPACE($1), SPACE(alloc_token), $2))
		  : APPEND2($1, $2));
          SET_PRECED($$, S_PRECED);
        }
  | '&' ADeclarator
        {
          TEST_PRECED($2, A_PRECED);
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND3(SPACE($1), SPACE(alloc_token), $2))
		  : APPEND2($1, $2));
          SET_PRECED($$, A_PRECED);
        }
  | Prefix '*' ADeclarator
        {
          TEST_PRECED($3, P_PRECED);
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND4($1, SPACE($2), SPACE(alloc_token), $3))
		  : APPEND3($1, SPACE($2), $3));
          SET_PRECED($$, P_PRECED);
        }
  | ADeclarator Full_Arg_List
        {
          TEST_PRECED($1, F_PRECED);
          $$ = APPEND2($1, $2);
          SET_PRECED($$, F_PRECED);
        }
  | ADeclarator T_ARRAY
        {
          TEST_PRECED($1, T_PRECED);
          $$ = APPEND2($1, $2);
          SET_PRECED($$, T_PRECED);
        }

           /*---------------------------------------------------------------*/
  | '(' ADeclarator ')'
        {
          $$ = APPEND3($1, $2, $3);
          SET_PRECED($$, GET_PRECED($2));
        }
  ;


   /*-----------------------------------------------------------------------*/

TDeclarator_Bit_List
  : Qualified   Init
        { BR_format_SU($1, default_token->_bits | BR_INFO_DATA); }
  | Qualified   ':'
        {
          if (global_prefix != BR_Null)         
            BR_format_SU($1, default_token->_bits | BR_INFO_DATA);
          else
            BR_YYERROR;
        }
  | TDeclarator Init
        {
          if (($2 != BR_Null) && (($1->_bits & BR_INFO_PROC) != 0))
            BR_format_SU($1, (default_token->_bits | BR_INFO_PURE));
          else
            BR_format_SU($1, default_token->_bits);
        }
  | ':'
        {
          if (global_prefix == BR_Null)
            BR_YYERROR;
        }
  | TDeclarator_Bit_List ',' Qualified   Init
        { BR_format_SU($3, default_token->_bits | BR_INFO_DATA); }
  | TDeclarator_Bit_List ',' Qualified   ':'
        {
          if (global_prefix != BR_Null)         
            BR_format_SU($3, default_token->_bits | BR_INFO_DATA);
          else
            BR_YYERROR;
        }
  | TDeclarator_Bit_List ',' TDeclarator Init
        {
          if (($4 != BR_Null) && (($3->_bits & BR_INFO_PROC) != 0))
            BR_format_SU($3, (default_token->_bits | BR_INFO_PURE));
          else
            BR_format_SU($3, default_token->_bits);
        }
  | TDeclarator_Bit_List ',' ':'
        {
          if (global_prefix == BR_Null)
            BR_YYERROR;
        }
  ;


   /*-----------------------------------------------------------------------*/

TDeclarator_List
  : Qualified   Init
        { BR_format_SU($1, default_token->_bits | BR_INFO_DATA); }
  | TDeclarator Init
        {
          if (($2 != BR_Null) && (($1->_bits & BR_INFO_PROC) != 0))
            BR_format_SU($1, (default_token->_bits | BR_INFO_PURE));
          else
            BR_format_SU($1, default_token->_bits);
        }
  | TDeclarator_List ',' Qualified   Init
        { BR_format_SU($3, default_token->_bits | BR_INFO_DATA); }
  | TDeclarator_List ',' TDeclarator Init
        {
          if (($4 != BR_Null) && (($3->_bits & BR_INFO_PROC) != 0))
            BR_format_SU($3, (default_token->_bits | BR_INFO_PURE));
          else
            BR_format_SU($3, default_token->_bits);
        }
  ;


   /*-----------------------------------------------------------------------*/

TDeclarator
           /*---------------------------------------------------------------*/
  : '*' Qualified
        { $$ = $2; $$->_bits = BR_INFO_DATA; }
  | '&' Qualified
        { $$ = $2; $$->_bits = BR_INFO_DATA; }
  | Prefix '*' Qualified
        { $$ = $3; $$->_bits = BR_INFO_DATA; }
  | Qualified T_ARRAY
        { $$ = $1; $$->_bits = BR_INFO_DATA; }
  | Qualified Full_Arg_List
        {
          $$ = APPEND2($1, $2);
          SET_BITS($$->_bits, BR_INFO_PROC);
          if (TEST_BITS($2->_last->_bits, BR_INFO_CONST))
            SET_BITS($$->_bits, BR_INFO_CONST);
        }
  | '~' T_IDENT Full_Arg_List
        {
          $1->_prefix = BR_Null;
          $$ = APPEND3($1, $2, $3);
          SET_BITS($$->_bits, (BR_INFO_PROC | BR_INFO_DESTRUCTOR));          
        }    
  | T_OPERATOR Operator_Decl Full_Arg_List
        {
          $1->_prefix = BR_Null;
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND4(SPACE($1), SPACE(alloc_token), $2, $3))
		  : APPEND3(SPACE($1), $2, $3));
          SET_BITS($$->_bits, (BR_INFO_PROC | BR_INFO_OPERATOR));
          if (TEST_BITS($3->_last->_bits, BR_INFO_CONST))
            SET_BITS($$->_bits, BR_INFO_CONST);
        }
  | Prefix '~' T_IDENT Full_Arg_List
        {
          $2->_prefix = $1;
          $$ = APPEND3($2, $3, $4);
          SET_BITS($$->_bits, (BR_INFO_PROC | BR_INFO_DESTRUCTOR));          
        }
  | Prefix T_OPERATOR Operator_Decl Full_Arg_List
        {
          $2->_prefix = $1;
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND4(SPACE($2), SPACE(alloc_token), $3, $4))
		  : APPEND3(SPACE($2), $3, $4));
          SET_BITS($$->_bits, (BR_INFO_PROC | BR_INFO_OPERATOR));
          if (TEST_BITS($4->_last->_bits, BR_INFO_CONST))
            SET_BITS($$->_bits, BR_INFO_CONST);
        }

           /*---------------------------------------------------------------*/
  | '*' TDeclarator
        { $$ = $2; }
  | '&' TDeclarator
        { $$ = $2; }
  | Prefix '*' TDeclarator
        { $$ = $3; }
  | TDeclarator T_ARRAY
        { $$ = $1; }
  | TDeclarator Full_Arg_List
        { $$ = $1; }

           /*---------------------------------------------------------------*/
   | '(' TDeclarator ')'
        { $$ = $2; }
  ;


   /*-----------------------------------------------------------------------*/

Operator_Decl
  : Operator_Basic
        { $$ = $1; }
  | Operator_Basic '*'
        {
          $$ = ((TEST_BITS($2->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND3($1, SPACE($2), alloc_token))
		  : APPEND2($1, $2));
        }
  | Operator_Basic '&'
        {
          $$ = ((TEST_BITS($2->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND3($1, SPACE($2), alloc_token))
		  : APPEND2($1, $2));
	}
  ;


   /*-----------------------------------------------------------------------*/

Operator_Basic
  : Qualified
        { $$ = $1; }
  | Bit_Specifier
        { $$ = $1; }
  | Agg_Specifier
        { $$ = $1; }
  ;


   /*-----------------------------------------------------------------------*/

Aggregate
  : T_ENUM '{' '}'
        {
          $$ = ALLOC_TOKEN(T_IDENT, STR_ANONYMOUS);
          BR_format_SU($$, BR_INFO_DEF | BR_INFO_ENUM | default_token->_bits);
	}
  | T_ENUM T_IDENT  '{' '}'
        { BR_format_SU($2, BR_INFO_DEF | BR_INFO_ENUM | default_token->_bits); }
  | Aggregate_Head
        {
          SET_ACCESS($1->_bits);
          BR_lex_jump_bracket();
        }
    '{' ESU_List '}'
        {
          UNSTACK_PREFIX();
          default_token = BR_lex_unstack_frame();
        }
  | Aggregate_Head error
        {
          UNSTACK_PREFIX();
          default_token = BR_lex_unstack_frame();
        }
  ;


   /*-----------------------------------------------------------------------*/

Aggregate_Head
  : Aggregate_Name
        {
          $$ = $1;
          STACK_PREFIX($1);
          default_token = BR_lex_stack_frame(BR_INFO_EMPTY);
        }
  | Aggregate_Name
        {
          STACK_PREFIX($1);
          default_token = BR_lex_stack_frame(BR_INFO_EMPTY);
          BR_lex_jump_colon();
        }
    Parent_List
        { $$ = $1; }
  ;


   /*-----------------------------------------------------------------------*/

Aggregate_Name
  : T_CLASS
        {
          $$ = ALLOC_TOKEN(T_IDENT, STR_ANONYMOUS);
          BR_format_SU($$, BR_INFO_DEF | BR_INFO_CLASS | default_token->_bits);
          $$->_bits = BR_INFO_PRIVATE;
        }
  | T_STRUCT
        {
          $$ = ALLOC_TOKEN(T_IDENT, STR_ANONYMOUS);
          BR_format_SU($$, BR_INFO_DEF | BR_INFO_STRUCT | default_token->_bits);
          $$->_bits = BR_INFO_PUBLIC;
        }
  | T_UNION 
        {
          $$ = ALLOC_TOKEN(T_IDENT, STR_ANONYMOUS);
          BR_format_SU($$, BR_INFO_DEF | BR_INFO_UNION | default_token->_bits);
          $$->_bits = BR_INFO_PUBLIC;
        }
  | T_CLASS  T_IDENT
        {
          $$ = $2;
          BR_format_SU($$, BR_INFO_DEF | BR_INFO_CLASS | default_token->_bits);
          $$->_bits = BR_INFO_PRIVATE;
        }
  | T_STRUCT T_IDENT
        {
          $$ = $2;
          BR_format_SU($$, BR_INFO_DEF | BR_INFO_STRUCT | default_token->_bits);
          $$->_bits = BR_INFO_PUBLIC;
        }
  | T_UNION  T_IDENT
        {
          $$ = $2;
          BR_format_SU($$, BR_INFO_DEF | BR_INFO_UNION | default_token->_bits);
          $$->_bits = BR_INFO_PUBLIC;
        }
  ;


   /*-----------------------------------------------------------------------*/

Parent_List
  : ':' Qualified
        {
          BR_format_SU($2, (BR_INFO_PARENT|BR_INFO_PRIVATE|default_token->_bits));
          BR_lex_empty_frame();
        }
  | ':' Access Qualified
        {
          BR_format_SU($3, (BR_INFO_PARENT|$2->_bits|default_token->_bits));
          BR_lex_empty_frame();
        }
  | Parent_List ',' Qualified
        {
          BR_format_SU($3, (BR_INFO_PARENT|BR_INFO_PRIVATE|default_token->_bits));
          BR_lex_empty_frame();
        }
  | Parent_List ',' Access Qualified
        {
          BR_format_SU($4, (BR_INFO_PARENT|$3->_bits|default_token->_bits));
          BR_lex_empty_frame();
        }
  ;


   /*-----------------------------------------------------------------------*/

ESU_List
  : SU_List
  | ESU_List T_FRIEND
        { default_token->_bits |= BR_INFO_FRIEND; }
    Friend_Decl
        { BR_lex_empty_frame(); }
    SU_List
  | ESU_List Access 
        {
          SET_ACCESS($2->_bits);
          BR_lex_jump_colon();
        }
    ':'
        { BR_lex_empty_frame(); }
     SU_List
  ;


   /*-----------------------------------------------------------------------*/

Friend_Decl
  : Qualified ';'
        { BR_format_SU($1, (default_token->_bits | BR_INFO_TYPEDEF)); }
  | Agg_Specifier ';'
        { BR_format_SU($1, ($1->_bits | default_token->_bits)); }
  | Full_FDeclarator
  | Qualified Full_FDeclarator
  | Bit_Specifier Full_FDeclarator
  | Agg_Specifier Full_FDeclarator
  | Aggregate Full_FDeclarator
  ;


   /*-----------------------------------------------------------------------*/
Full_FDeclarator
  : FDeclarator '{' '}'
        { BR_format_SU($1, ($1->_bits | default_token->_bits | BR_INFO_DEF)); }
  | FDeclarator_List ';'
  ;


   /*-----------------------------------------------------------------------*/

FDeclarator_List
  : FDeclarator
        { BR_format_SU($1, ($1->_bits | default_token->_bits)); }
  | FDeclarator_List ',' FDeclarator
        { BR_format_SU($3, ($3->_bits | default_token->_bits)); }
  ;


   /*-----------------------------------------------------------------------*/

FDeclarator
  : Qualified Full_Arg_List
        {
          $$ = APPEND2($1, $2);
          if (TEST_BITS($2->_last->_bits, BR_INFO_CONST))
            SET_BITS($$->_bits, (BR_INFO_PROC | BR_INFO_CONST));
          else
            SET_BITS($$->_bits, BR_INFO_PROC);
        }
  | T_OPERATOR Operator_Decl Full_Arg_List
        {
          $1->_prefix = BR_Null;
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND4(SPACE($1), SPACE(alloc_token), $2, $3))
		  : APPEND3(SPACE($1), $2, $3));
          SET_BITS($$->_bits, (BR_INFO_PROC | BR_INFO_OPERATOR));
          if (TEST_BITS($3->_last->_bits, BR_INFO_CONST))
            SET_BITS($$->_bits, BR_INFO_CONST);
        }
  | Prefix T_OPERATOR Operator_Decl Full_Arg_List
        {
          $2->_prefix = $1;
          $$ = ((TEST_BITS($1->_bits, BR_INFO_CONST))
		  ? (alloc_token = ALLOC_TOKEN(T_CONST, STR_CONST),
		     APPEND4(SPACE($2), SPACE(alloc_token), $3, $4))
		  : APPEND3(SPACE($2), $3, $4));
          SET_BITS($$->_bits, (BR_INFO_PROC | BR_INFO_OPERATOR));
          if (TEST_BITS($4->_last->_bits, BR_INFO_CONST))
            SET_BITS($$->_bits, BR_INFO_CONST);
        }
  | '*' FDeclarator
        { $$ = $2; }
  | '&' FDeclarator
        { $$ = $2; }
  | Prefix '*' FDeclarator
        { $$ = $3; }
  | FDeclarator T_ARRAY
        { $$ = $1; }
  | FDeclarator Full_Arg_List
        { $$ = $1; }

   | '(' FDeclarator ')'
        { $$ = $2; }
  ;


   /*-----------------------------------------------------------------------*/

Access
  : T_PRIVATE
        { $$ = $1; $$->_bits = BR_INFO_PRIVATE; }
  | T_PROTECTED
        { $$ = $1; $$->_bits = BR_INFO_PROTECTED; }
  | T_PUBLIC
        { $$ = $1; $$->_bits = BR_INFO_PUBLIC; }
  ;


%%


   /*-----------------------------------------------------------------------*/

#if YYDEBUG != 0

static char val[1024];

static int
BR_yyprint(f, t, v)
     FILE*   f;
     int     t;
     YYSTYPE v;
{
  if ((v != BR_Null) && (v->_val != BR_Null))
  {
    strncpy(val, yylval->_val, (BR_Int) yylval->_val_len + 1);      
    *(val + yylval->_val_len + 1) = '\0';
    fprintf(f, "   [(l=%05ld) \"%s\"]", yylval->_line_num, val);
  }
  return(0);
}

#endif


   /*-----------------------------------------------------------------------*/

int
yyerror(msg)
     char* msg;
{
  if (BR_info_handler != BR_Null)
    BR_info_handler("", "", BR_INFO_ERROR, BR_lex_get_line_num());
  else
    BR_WARNING(">>>>>  Hum, Hum !!! Strange construction at line : %d\n",
	       BR_lex_get_line_num());

  return(0);
}


   /*-----------------------------------------------------------------------*/

#define MAX_TEMPLATE_ARGS   20

static BR_Str* template_substitute[MAX_TEMPLATE_ARGS] =
{
  "$T00 ",
  "$T01 ",
  "$T02 ",
  "$T03 ",
  "$T04 ",
  "$T05 ",
  "$T06 ",
  "$T07 ",
  "$T08 ",
  "$T09 ",

  "$T10 ",
  "$T11 ",
  "$T12 ",
  "$T13 ",
  "$T14 ",
  "$T15 ",
  "$T16 ",
  "$T17 ",
  "$T18 ",
  "$T19 ",
};


static void
BR_replace_template_args(token)
     BR_TokenPt token;
{
  BR_TokenPt curr_arg;
  BR_Int     arg_num;

  curr_arg = template_args;
  arg_num  = 0;
  while (curr_arg != BR_Null)
  {
    if (   (curr_arg->_val_len == token->_val_len)
        && (strncmp(curr_arg->_val, token->_val, token->_val_len) == 0))
    {
      if (arg_num < MAX_TEMPLATE_ARGS)
	token->_val = template_substitute[arg_num];
      else
	token->_val = "$TXX ";
      token->_val_len = 4;
      curr_arg = BR_Null;
    }
    else
      curr_arg = curr_arg->_next;
    arg_num++;
  }
}


   /*-----------------------------------------------------------------------*/

#if YYDEBUG != 0

static BR_Str dump_buff[1024];

static void
BR_dump_tree(msg, tree)
     BR_Str*    msg;
     BR_TokenPt tree;
{
  BR_TokenPt curr_tok;

  fprintf(stderr, "%s\n", msg);
  curr_tok = tree;
  while (curr_tok != BR_Null)
  {
    strncpy(dump_buff, curr_tok->_val, curr_tok->_val_len);
    dump_buff[curr_tok->_val_len] = '\0';
    fprintf(stderr, "   (p=0x%08lx, n=0x%08lx, l=0x%08lx, b=0x%08lx) %s\n",
	            (BR_ULong) curr_tok,
	            (BR_ULong) curr_tok->_next,
	            (BR_ULong) curr_tok->_last,
	            (BR_ULong) curr_tok->_bits,
	            dump_buff);
    curr_tok = curr_tok->_next;
  }
}

#endif

  
   /*-----------------------------------------------------------------------*/

static void
BR_format_SU(SU_tree, default_infos)
     BR_TokenPt SU_tree;
     BR_ULong   default_infos;
{
  BR_TokenPt  prev_tok;
  BR_TokenPt  curr_tok;
  BR_Str*     curr_buf;
  BR_Str*     curr_val;
  BR_ULong    infos;
  BR_TokenPt  prefix;
  BR_Str*     str_prefix;
  BR_Str*     str_SU;
  BR_TokenPt  last_token;
  BR_Str*     begin_qualif;
  BR_TokenPt  test_tok;
  BR_TokenPt  last_pref;
  BR_TokenPt  const_token;

  infos = default_infos | SU_tree->_bits;

  /*---------------------------------------------------------  Prefix  --*/
  if ((global_prefix != BR_Null) && (!TEST_BITS(infos, BR_INFO_FRIEND)))
    prefix = global_prefix;
  else
    prefix = SU_tree->_prefix;

  if (prefix != BR_Null)
  {
    if (prefix->_last->_line_num != last_stamp)
    {
      prev_tok = prefix;
      curr_tok = prefix;
      curr_buf = prefix_buffer;
      while (curr_tok != BR_Null)
      {
	curr_val = curr_tok->_val;
	if (curr_tok->_code == T_PREFIX)
        {
	  if (curr_tok->_next != BR_Null)
          {
	    *curr_buf++ = *curr_val++;
	    *curr_buf++ = *curr_val;
	  }
	  else
	    prefix->_last = prev_tok;
	}
	else
        {
	  strncpy(curr_buf, curr_val, curr_tok->_val_len);
	  curr_buf += curr_tok->_val_len;
	}
	prev_tok = curr_tok;
	curr_tok = curr_tok->_next;
      }
      prefix_len  = curr_buf - prefix_buffer;
      *curr_buf++ = '\0';
      last_stamp  = prefix->_last->_line_num;
    }
    str_prefix = prefix_buffer;
  }
  else
    str_prefix = BR_Null;

  /*----------------------------------------------------------  Infos  --*/
  if (TEST_BITS(infos, BR_INFO_PARENT))
  {
    /*fprintf(stderr, ">=> Parent : 0x%08x (0x%08x)\n", infos, CONTROL_PARENT);*/
    if (TEST_BITS(infos, CONTROL_PARENT))
      SET_BITS(infos, BR_INFO_ERROR);    
  }

  if (TEST_BITS(infos, AGGREGATE_BITS))
  {
    CLEAR_BITS(infos, (BR_INFO_EXTERN | BR_INFO_STATIC));
    /*fprintf(stderr,">=> Aggrega : 0x%08x (0x%08x)\n",infos,CONTROL_AGGREGATE);*/
    if (TEST_BITS(infos, CONTROL_AGGREGATE))
      SET_BITS(infos, BR_INFO_ERROR);
    CLEAR_BITS(infos, BR_INFO_TYPEDEF);
    if (TEST_BITS(infos, BR_INFO_FRIEND))
      CLEAR_BITS(infos, ACCESS_BITS);
    else if (template_flag != BR_FALSE)
    {
      if (TEST_BITS(infos, BR_INFO_CLASS))
	SET_BITS(infos, BR_INFO_TEMPLATE);
      else
	SET_BITS(infos, BR_INFO_ERROR);
    }
  }

  if (TEST_BITS(infos, BR_INFO_TYPEDEF))
  {
    /*fprintf(stderr,">=> Typedef : 0x%08x (0x%08x)\n", infos, CONTROL_TYPEDEF);*/
    if (TEST_BITS(infos, CONTROL_TYPEDEF))
      SET_BITS(infos, BR_INFO_ERROR);
    else if (TEST_BITS(infos, BR_INFO_PROC))
      SU_tree->_next = BR_Null;
    CLEAR_BITS(infos, (BR_INFO_PROC | BR_INFO_DATA));
    CLEAR_BITS(infos, (BR_INFO_EXTERN | BR_INFO_STATIC));
    if (TEST_BITS(infos, BR_INFO_FRIEND))
      CLEAR_BITS(infos, ACCESS_BITS);
    else
      SET_BITS(infos, BR_INFO_DEF);
  }

  if (TEST_BITS(infos, BR_INFO_PROC))
  {
    /*fprintf(stderr, ">=> Proc    : 0x%08x (0x%08x)\n", infos, CONTROL_PROC);*/
    if (TEST_BITS(infos, CONTROL_PROC))
      SET_BITS(infos, BR_INFO_ERROR);
    else
    {
      if (TEST_BITS(SU_tree->_last->_bits, BR_INFO_CONST))
      {
        SET_BITS(infos, BR_INFO_CONST);
	const_token = ALLOC_TOKEN(T_CONST, STR_CONST);
	APPEND2(SPACE(SU_tree), const_token);
      }
      if (TEST_BITS(infos, BR_INFO_FRIEND))
      {
        CLEAR_BITS(infos, ACCESS_BITS);
        if (TEST_BITS(infos, CONTROL_FRIEND_PROC))
          SET_BITS(infos, BR_INFO_ERROR);
	else if (TEST_BITS(infos, BR_INFO_DEF))
	  SET_BITS(infos, BR_INFO_INLINE);
      }
      else if (TEST_BITS(infos, BR_INFO_C))
        SU_tree->_next->_next = SU_tree->_last;
      else if (prefix != BR_Null)
      {
        last_pref = prefix->_last;
        if (*(SU_tree->_val) == '~')
          test_tok = SU_tree->_next;
        else
          test_tok = SU_tree;
	if (   (test_tok->_val_len == last_pref->_val_len)
	    && (strncmp(test_tok->_val,
			last_pref->_val,
			last_pref->_val_len) == 0))
        {
	  if (*(SU_tree->_val) != '~')
	    SET_BITS(infos, BR_INFO_CONSTRUCTOR);
        }
	else if (*(SU_tree->_val) == '~')
	  SET_BITS(infos, BR_INFO_ERROR);
	if ((global_prefix != BR_Null) && (TEST_BITS(infos, BR_INFO_DEF)))
	  SET_BITS(infos, BR_INFO_INLINE);
      }
      else if (TEST_BITS(infos, BR_INFO_CONST | BR_INFO_VIRTUAL | BR_INFO_PURE))
        SET_BITS(infos, BR_INFO_ERROR);
      else if (template_flag != BR_FALSE)
        SET_BITS(infos, BR_INFO_TEMPLATE);
      CLEAR_BITS(infos, BR_INFO_EXTERN);
    }
  }

  if (TEST_BITS(infos, BR_INFO_DATA))
  {
    /*fprintf(stderr, ">=> Data    : 0x%08x (0x%08x)\n", infos, CONTROL_DATA);*/
    if (TEST_BITS(infos, CONTROL_DATA))
      SET_BITS(infos, BR_INFO_ERROR);      
    else if (!TEST_BITS(infos, BR_INFO_EXTERN))
      SET_BITS(infos, BR_INFO_DEF);      
    CLEAR_BITS(infos, BR_INFO_EXTERN);
  }
 
  /*----------------------------------------------------  Syntax Unit  --*/
  curr_tok     = SU_tree;
  curr_buf     = SU_buffer;
  last_token   = BR_Null;
  begin_qualif = BR_Null;
  while (curr_tok != BR_Null)
  {
    if (curr_tok == last_token)
    {
      if (   (str_prefix != BR_Null)
          && (((curr_buf - begin_qualif) - 2) == prefix_len)
	  && (strncmp(begin_qualif, str_prefix, prefix_len) == 0))
	curr_buf = begin_qualif;
    }

    if ((curr_tok != SU_tree) && (curr_tok->_prefix != BR_Null))
    {
      last_token          = curr_tok;
      begin_qualif        = curr_buf;
      curr_tok            = APPEND2(curr_tok->_prefix, curr_tok);
      last_token->_prefix = BR_Null;
    }

    curr_val = curr_tok->_val;
    switch(curr_tok->_val_len)
    {
      case 0 :
	break;
      case 1 :
	*curr_buf++ = *curr_val;
	break;
      case 2 :
	*curr_buf++ = *curr_val++;
	*curr_buf++ = *curr_val;
	break;
      case 3 :
	*curr_buf++ = *curr_val++;
	*curr_buf++ = *curr_val++;
	*curr_buf++ = *curr_val;
	break;
      default:
	strncpy(curr_buf, curr_val, curr_tok->_val_len);
	curr_buf += curr_tok->_val_len;
    }
    curr_tok = curr_tok->_next;
  }
  *curr_buf++ = '\0';
  str_SU = SU_buffer;

  /*---------------------------------------------------------------------*/
  if (BR_info_handler != BR_Null)
  {
    if (TEST_BITS(infos, BR_INFO_ERROR))
      BR_info_handler("", "", BR_INFO_ERROR, SU_tree->_line_num);
    else
      BR_info_handler(str_prefix, str_SU, infos, SU_tree->_line_num);
  } 
}


   /*-----------------------------------------------------------------------*/

static void
BR_signal_handler()
{
  longjmp(BR_env, 1);
}


   /*-----------------------------------------------------------------------*/

BR_Boolean
BR_parse_file(file_name, info_handler, filter_cmd)
     BR_Str          *file_name;
     BR_InfoHandler   info_handler;
     BR_Str         **filter_cmd;
{
  pid_t       child_pid;
  BR_Boolean  parse_ok;
  FILE*       file_pt;
#ifdef _AIX
  union wait  child_status;
#else
  int         child_status;
#endif
  int         p_array[2];

  if (file_name == BR_Null)
    parse_ok = BR_FALSE;
  else
  {
    parse_ok = BR_TRUE;
    if (filter_cmd != BR_Null)
    {
      child_pid = -1;
      file_pt   = BR_Null;

      if (pipe(p_array) == -1)
      {
	BR_WARNING(">>>>>  Filter pipe creation failure %s\n", "");
	parse_ok = BR_FALSE;
      }
      else
      {
	child_pid = fork();
	if (child_pid > 0)
	{ /*------------------------------------------------------------*/
	  close(p_array[1]);
	  file_pt = fdopen(p_array[0], "r");
	}
	else if (child_pid == 0)
	{ /*------------------------------------------------------------*/
	  close(1);
	  dup(p_array[1]);
	  close(p_array[1]);
	  close(p_array[0]);
	  execv(filter_cmd[0], filter_cmd);
	  BR_FATAL_ERROR(">>>>>  Execv failure (\"%s\")\n", filter_cmd[0]);
	}
	else
        { /*------------------------------------------------------------*/
	  close(p_array[1]);
	  close(p_array[0]);
	  BR_WARNING(">>>>>  Filter fork failure (\"%s\")\n", filter_cmd[0]);
	  parse_ok = BR_FALSE;
	}
      }
    }
    else
    {
      child_pid = 0;
      file_pt   = fopen(file_name, "r");
    }

    if (file_pt != BR_Null)
      BR_lex_init(file_pt, file_name);
    else if (parse_ok != BR_FALSE)
    {
      BR_WARNING(">>>>>  File opening failure (\"%s\")\n", file_name);
      parse_ok = BR_FALSE;
    }

    default_token      = BR_Null;
    global_prefix      = BR_Null;
    template_args      = BR_Null;
    template_flag      = BR_FALSE;
    prefix_stamp       = 1;
    last_stamp         = 0;
    BR_info_handler    = info_handler;
    default_token      = BR_lex_stack_frame(BR_INFO_EMPTY);

    BR_sigill_handler  = (void (*) ()) signal(SIGILL,  BR_signal_handler);
    BR_sigbus_handler  = (void (*) ()) signal(SIGBUS,  BR_signal_handler);
    BR_sigsegv_handler = (void (*) ()) signal(SIGSEGV, BR_signal_handler);

    if (setjmp(BR_env) == 0)
    {
      if ((parse_ok != BR_FALSE) && (BR_yyparse() != 0))
	parse_ok = BR_FALSE;
    }
    else
    {
      fprintf(stderr, ">>>>>\n");
      fprintf(stderr, ">>>>>  Browser Fatal Internal Error (Parsing Aborted)  <<<<<\n");
      fprintf(stderr, ">>>>>     In Parsing file : %s\n", file_name);
      fprintf(stderr, ">>>>>     Near line       : %d\n", BR_lex_get_line_num());
      fprintf(stderr, ">>>>>\n");

      parse_ok = BR_FALSE;
    }

    signal(SIGILL,  (void (*) ()) BR_sigill_handler);
    signal(SIGBUS,  (void (*) ()) BR_sigbus_handler);
    signal(SIGSEGV, (void (*) ()) BR_sigsegv_handler);

    if (file_pt != BR_Null)
      fclose(file_pt);

    if (   (child_pid > 0)
	&& (   (waitpid(child_pid, &child_status, WUNTRACED) != child_pid)
	    || (WIFEXITED(child_status)   == 0)
	    || (WEXITSTATUS(child_status) != 0)))
      parse_ok = BR_FALSE;
  }

  return(parse_ok);
}
