stack_xhtml2.zip

FlexLexer.h

// -*-C++-*- // FlexLexer.h -- define interfaces for lexical analyzer classes generated // by flex // Copyright (c) 1993 The Regents of the University of California. // All rights reserved. // // This code is derived from software contributed to Berkeley by // Kent Williams and Tom Epperly. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // Neither the name of the University nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE. // This file defines FlexLexer, an abstract class which specifies the // external interface provided to flex C++ lexer objects, and yyFlexLexer, // which defines a particular lexer class. // // If you want to create multiple lexer classes, you use the -P flag // to rename each yyFlexLexer to some other xxFlexLexer. You then // include <FlexLexer.h> in your other sources once per lexer class: // // #undef yyFlexLexer // #define yyFlexLexer xxFlexLexer // #include <FlexLexer.h> // // #undef yyFlexLexer // #define yyFlexLexer zzFlexLexer // #include <FlexLexer.h> // ... #ifndef __FLEX_LEXER_H // Never included before - need to define base class. #define __FLEX_LEXER_H #include <iostream> extern "C++" { struct yy_buffer_state; typedef int yy_state_type; class FlexLexer { public: virtual ~FlexLexer() { } const char* YYText() const { return yytext; } int YYLeng() const { return yyleng; } virtual void yy_switch_to_buffer( yy_buffer_state* new_buffer ) = 0; virtual yy_buffer_state* yy_create_buffer( std::istream* s, int size ) = 0; virtual yy_buffer_state* yy_create_buffer( std::istream& s, int size ) = 0; virtual void yy_delete_buffer( yy_buffer_state* b ) = 0; virtual void yyrestart( std::istream* s ) = 0; virtual void yyrestart( std::istream& s ) = 0; virtual int yylex() = 0; // Call yylex with new input/output sources. int yylex( std::istream& new_in, std::ostream& new_out ) { switch_streams( new_in, new_out ); return yylex(); } int yylex( std::istream* new_in, std::ostream* new_out = 0) { switch_streams( new_in, new_out ); return yylex(); } // Switch to new input/output streams. A nil stream pointer // indicates "keep the current one". virtual void switch_streams( std::istream* new_in, std::ostream* new_out ) = 0; virtual void switch_streams( std::istream& new_in, std::ostream& new_out ) = 0; int lineno() const { return yylineno; } int debug() const { return yy_flex_debug; } void set_debug( int flag ) { yy_flex_debug = flag; } protected: char* yytext; int yyleng; int yylineno; // only maintained if you use %option yylineno int yy_flex_debug; // only has effect with -d or "%option debug" }; } #endif // FLEXLEXER_H #if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce) // Either this is the first time through (yyFlexLexerOnce not defined), // or this is a repeated include to define a different flavor of // yyFlexLexer, as discussed in the flex manual. # define yyFlexLexerOnce extern "C++" { class yyFlexLexer : public FlexLexer { public: // arg_yyin and arg_yyout default to the cin and cout, but we // only make that assignment when initializing in yylex(). yyFlexLexer( std::istream& arg_yyin, std::ostream& arg_yyout ); yyFlexLexer( std::istream* arg_yyin = 0, std::ostream* arg_yyout = 0 ); private: void ctor_common(); public: virtual ~yyFlexLexer(); void yy_switch_to_buffer( yy_buffer_state* new_buffer ); yy_buffer_state* yy_create_buffer( std::istream* s, int size ); yy_buffer_state* yy_create_buffer( std::istream& s, int size ); void yy_delete_buffer( yy_buffer_state* b ); void yyrestart( std::istream* s ); void yyrestart( std::istream& s ); void yypush_buffer_state( yy_buffer_state* new_buffer ); void yypop_buffer_state(); virtual int yylex(); virtual void switch_streams( std::istream& new_in, std::ostream& new_out ); virtual void switch_streams( std::istream* new_in = 0, std::ostream* new_out = 0 ); virtual int yywrap(); protected: virtual int LexerInput( char* buf, int max_size ); virtual void LexerOutput( const char* buf, int size ); virtual void LexerError( const char* msg ); void yyunput( int c, char* buf_ptr ); int yyinput(); void yy_load_buffer_state(); void yy_init_buffer( yy_buffer_state* b, std::istream& s ); void yy_flush_buffer( yy_buffer_state* b ); int yy_start_stack_ptr; int yy_start_stack_depth; int* yy_start_stack; void yy_push_state( int new_state ); void yy_pop_state(); int yy_top_state(); yy_state_type yy_get_previous_state(); yy_state_type yy_try_NUL_trans( yy_state_type current_state ); int yy_get_next_buffer(); std::istream yyin; // input source for default LexerInput std::ostream yyout; // output sink for default LexerOutput // yy_hold_char holds the character lost when yytext is formed. char yy_hold_char; // Number of characters read into yy_ch_buf. int yy_n_chars; // Points to current character in buffer. char* yy_c_buf_p; int yy_init; // whether we need to initialize int yy_start; // start state number // Flag which is used to allow yywrap()'s to do buffer switches // instead of setting up a fresh yyin. A bit of a hack ... int yy_did_buffer_switch_on_eof; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */ void yyensure_buffer_stack(void); // The following are not always needed, but may be depending // on use of certain flex features (like REJECT or yymore()). yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; yy_state_type* yy_state_buf; yy_state_type* yy_state_ptr; char* yy_full_match; int* yy_full_state; int yy_full_lp; int yy_lp; int yy_looking_for_trail_begin; int yy_more_flag; int yy_more_len; int yy_more_offset; int yy_prev_more_offset; }; } #endif // yyFlexLexer || ! yyFlexLexerOnce

bin/Linux/xmlcheck

bin/Windows/xmlcheck.exe

lex.yy.cpp

lex.yy.cpp


#line   3   "lex.yy.cc"

#define   YY_INT_ALIGNED  short   int

/* A lexical scanner generated by flex */

#define  FLEX_SCANNER
#define  YY_FLEX_MAJOR_VERSION  2
#define  YY_FLEX_MINOR_VERSION  6
#define  YY_FLEX_SUBMINOR_VERSION  4
#if  YY_FLEX_SUBMINOR_VERSION  >   0
#define  FLEX_BETA
#endif

     /* The c++ scanner is a mess. The FlexLexer.h header file relies on the
     * following macro. This is required in order to pass the c++-multiple-scanners
     * test in the regression suite. We get reports that it breaks inheritance.
     * We will address this in a future release of flex, or omit the C++ scanner
     * altogether.
     */
     #define  yyFlexLexer yyFlexLexer

/* First, we deal with  platform-specific or compiler-specific issues. */

/* begin standard C headers. */

/* end standard C headers. */

/* flex integer type definitions */

#ifndef  FLEXINT_H
#define  FLEXINT_H

/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */

#if  defined  ( __STDC_VERSION__ )   &&  __STDC_VERSION__  >=   199901L

/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
 * if you want the limit (max/min) macros for int types. 
 */
#ifndef  __STDC_LIMIT_MACROS
#define  __STDC_LIMIT_MACROS  1
#endif

#include   < inttypes . h >
typedef  int8_t flex_int8_t ;
typedef  uint8_t flex_uint8_t ;
typedef  int16_t flex_int16_t ;
typedef  uint16_t flex_uint16_t ;
typedef  int32_t flex_int32_t ;
typedef  uint32_t flex_uint32_t ;
#else
typedef   signed   char  flex_int8_t ;
typedef   short   int  flex_int16_t ;
typedef   int  flex_int32_t ;
typedef   unsigned   char  flex_uint8_t ;  
typedef   unsigned   short   int  flex_uint16_t ;
typedef   unsigned   int  flex_uint32_t ;

/* Limits of integral types. */
#ifndef  INT8_MIN
#define  INT8_MIN                ( - 128 )
#endif
#ifndef  INT16_MIN
#define  INT16_MIN               ( - 32767 - 1 )
#endif
#ifndef  INT32_MIN
#define  INT32_MIN               ( - 2147483647 - 1 )
#endif
#ifndef  INT8_MAX
#define  INT8_MAX                ( 127 )
#endif
#ifndef  INT16_MAX
#define  INT16_MAX               ( 32767 )
#endif
#ifndef  INT32_MAX
#define  INT32_MAX               ( 2147483647 )
#endif
#ifndef  UINT8_MAX
#define  UINT8_MAX               ( 255U )
#endif
#ifndef  UINT16_MAX
#define  UINT16_MAX              ( 65535U )
#endif
#ifndef  UINT32_MAX
#define  UINT32_MAX              ( 4294967295U )
#endif

#ifndef  SIZE_MAX
#define  SIZE_MAX                ( ~ ( size_t ) 0 )
#endif

#endif   /* ! C99 */

#endif   /* ! FLEXINT_H */

/* begin standard C++ headers. */
#include   < iostream >
#include   < errno . h >
#include   < cstdlib >
#include   < cstdio >
#include   < cstring >
/* end standard C++ headers. */

/* TODO: this is always defined, so inline it */
#define  yyconst  const

#if  defined ( __GNUC__ )   &&  __GNUC__  >=   3
#define  yynoreturn __attribute__ (( __noreturn__ ))
#else
#define  yynoreturn
#endif

/* Returned upon end-of-file. */
#define  YY_NULL  0

/* Promotes a possibly negative, possibly signed char to an
 *   integer in range [0..255] for use as an array index.
 */
#define  YY_SC_TO_UI ( c )   (( YY_CHAR )   ( c ))

/* Enter a start condition.  This macro really ought to take a parameter,
 * but we do it the disgusting crufty way forced on us by the ()-less
 * definition of BEGIN.
 */
#define  BEGIN  ( yy_start )   =   1   +   2   *
/* Translate the current start state into a value that can be later handed
 * to BEGIN to return to the state.  The YYSTATE alias is for lex
 * compatibility.
 */
#define  YY_START  ((( yy_start )   -   1 )   /   2 )
#define  YYSTATE YY_START
/* Action number for EOF rule of a given start state. */
#define  YY_STATE_EOF ( state )   ( YY_END_OF_BUFFER  +  state  +   1 )
/* Special action meaning "start processing a new file". */
#define  YY_NEW_FILE yyrestart (  yyin   )
#define  YY_END_OF_BUFFER_CHAR  0

/* Size of default input buffer. */
#ifndef  YY_BUF_SIZE
#ifdef  __ia64__
/* On IA-64, the buffer size is 16k, not 8k.
 * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
 * Ditto for the __ia64__ case accordingly.
 */
#define  YY_BUF_SIZE  32768
#else
#define  YY_BUF_SIZE  16384
#endif   /* __ia64__ */
#endif

/* The state buf must be large enough to hold one state per character in the main buffer.
 */
#define  YY_STATE_BUF_SIZE    (( YY_BUF_SIZE  +   2 )   *   sizeof ( yy_state_type ))

#ifndef  YY_TYPEDEF_YY_BUFFER_STATE
#define  YY_TYPEDEF_YY_BUFFER_STATE
typedef   struct  yy_buffer_state  * YY_BUFFER_STATE ;
#endif

#ifndef  YY_TYPEDEF_YY_SIZE_T
#define  YY_TYPEDEF_YY_SIZE_T
typedef  size_t yy_size_t ;
#endif

extern   int  yyleng ;

#define  EOB_ACT_CONTINUE_SCAN  0
#define  EOB_ACT_END_OF_FILE  1
#define  EOB_ACT_LAST_MATCH  2
    
     #define  YY_LESS_LINENO ( n )
     #define  YY_LINENO_REWIND_TO ( ptr )
    
/* Return all but the first "n" matched characters back to the input stream. */
#define  yyless ( n )  \
     do  \
         {  \
         /* Undo effects of setting up yytext. */  \
         int  yyless_macro_arg  =   ( n );  \
        YY_LESS_LINENO ( yyless_macro_arg ); \
         * yy_cp  =   ( yy_hold_char );  \
        YY_RESTORE_YY_MORE_OFFSET \
         ( yy_c_buf_p )   =  yy_cp  =  yy_bp  +  yyless_macro_arg  -  YY_MORE_ADJ ;  \
        YY_DO_BEFORE_ACTION ;   /* set up yytext again */  \
         }  \
     while   (   0   )
#define  unput ( c )  yyunput (  c ,   ( yytext_ptr )    )

#ifndef  YY_STRUCT_YY_BUFFER_STATE
#define  YY_STRUCT_YY_BUFFER_STATE
struct  yy_buffer_state
     {

    std :: streambuf *  yy_input_file ;

     char   * yy_ch_buf ;          /* input buffer */
     char   * yy_buf_pos ;         /* current position in input buffer */

     /* Size of input buffer in bytes, not including room for EOB
     * characters.
     */
     int  yy_buf_size ;

     /* Number of characters read into yy_ch_buf, not including EOB
     * characters.
     */
     int  yy_n_chars ;

     /* Whether we "own" the buffer - i.e., we know we created it,
     * and can realloc() it to grow it, and should free() it to
     * delete it.
     */
     int  yy_is_our_buffer ;

     /* Whether this is an "interactive" input source; if so, and
     * if we're using stdio for input, then we want to use getc()
     * instead of fread(), to make sure we stop fetching input after
     * each newline.
     */
     int  yy_is_interactive ;

     /* Whether we're considered to be at the beginning of a line.
     * If so, '^' rules will be active on the next match, otherwise
     * not.
     */
     int  yy_at_bol ;

     int  yy_bs_lineno ;   /**< The line count. */
     int  yy_bs_column ;   /**< The column count. */

     /* Whether to try to fill the input buffer when we reach the
     * end of it.
     */
     int  yy_fill_buffer ;

     int  yy_buffer_status ;

#define  YY_BUFFER_NEW  0
#define  YY_BUFFER_NORMAL  1
     /* When an EOF's been seen but there's still some text to process
     * then we mark the buffer as YY_EOF_PENDING, to indicate that we
     * shouldn't try reading from the input source any more.  We might
     * still have a bunch of tokens to match, though, because of
     * possible backing-up.
     *
     * When we actually see the EOF, we change the status to "new"
     * (via yyrestart()), so that the user can continue scanning by
     * just pointing yyin at a new input file.
     */
#define  YY_BUFFER_EOF_PENDING  2

     };
#endif   /* !YY_STRUCT_YY_BUFFER_STATE */

/* We provide macros for accessing buffer states in case in the
 * future we want to put the buffer states in a more general
 * "scanner state".
 *
 * Returns the top of the stack, or NULL.
 */
#define  YY_CURRENT_BUFFER  (   ( yy_buffer_stack )  \
                           ?   ( yy_buffer_stack )[( yy_buffer_stack_top )]  \
                           :  NULL )
/* Same as previous macro, but useful when we know that the buffer stack is not
 * NULL or when we need an lvalue. For internal use only.
 */
#define  YY_CURRENT_BUFFER_LVALUE  ( yy_buffer_stack )[( yy_buffer_stack_top )]

void   * yyalloc  (  yy_size_t   );
void   * yyrealloc  (   void   * ,  yy_size_t   );
void  yyfree  (   void   *    );

#define  yy_new_buffer yy_create_buffer
#define  yy_set_interactive ( is_interactive )  \
     {  \
     if   (   !  YY_CURRENT_BUFFER  ){  \
        yyensure_buffer_stack  ();  \
        YY_CURRENT_BUFFER_LVALUE  =     \
            yy_create_buffer (  yyin ,  YY_BUF_SIZE  );  \
     }  \
    YY_CURRENT_BUFFER_LVALUE -> yy_is_interactive  =  is_interactive ;  \
     }
#define  yy_set_bol ( at_bol )  \
     {  \
     if   (   !  YY_CURRENT_BUFFER  ){ \
        yyensure_buffer_stack  ();  \
        YY_CURRENT_BUFFER_LVALUE  =     \
            yy_create_buffer (  yyin ,  YY_BUF_SIZE  );  \
     }  \
    YY_CURRENT_BUFFER_LVALUE -> yy_at_bol  =  at_bol ;  \
     }
#define  YY_AT_BOL ()   ( YY_CURRENT_BUFFER_LVALUE -> yy_at_bol )

/* Begin user sect3 */
#define  YY_SKIP_YYWRAP
typedef  flex_uint8_t YY_CHAR ;

#define  yytext_ptr yytext
#define  YY_INTERACTIVE

#include   "FlexLexer.h"

int  yyFlexLexer :: yywrap ()   {   return   1 ;   }

/* Done after the current pattern has been matched and before the
 * corresponding action - sets up yytext.
 */
#define  YY_DO_BEFORE_ACTION \
     ( yytext_ptr )   =  yy_bp ;  \
    yyleng  =   ( int )   ( yy_cp  -  yy_bp );  \
     ( yy_hold_char )   =   * yy_cp ;  \
     * yy_cp  =   '\0' ;  \
     ( yy_c_buf_p )   =  yy_cp ;
#define  YY_NUM_RULES  15
#define  YY_END_OF_BUFFER  16
/* This struct is not used in this scanner,
   but its presence is necessary. */
struct  yy_trans_info
     {
    flex_int32_t yy_verify ;
    flex_int32_t yy_nxt ;
     };
static   const  flex_int16_t yy_accept [ 56 ]   =
     {     0 ,
         0 ,      0 ,      0 ,      0 ,      0 ,      0 ,      0 ,      0 ,     16 ,     14 ,
         1 ,      1 ,     14 ,      7 ,     15 ,     15 ,     15 ,     15 ,     13 ,     15 ,
        15 ,      1 ,      0 ,      0 ,      0 ,      0 ,      7 ,      0 ,      0 ,     11 ,
         0 ,     12 ,      0 ,      0 ,      0 ,      0 ,      3 ,      3 ,      0 ,      0 ,
         0 ,      4 ,      8 ,      0 ,      0 ,      2 ,      0 ,      0 ,      6 ,      0 ,
         0 ,      5 ,     10 ,      9 ,      0
     }   ;

static   const  YY_CHAR yy_ec [ 256 ]   =
     {     0 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      2 ,      3 ,
         1 ,      1 ,      2 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      2 ,      4 ,      5 ,      1 ,      1 ,      1 ,      1 ,      6 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      7 ,      1 ,      8 ,      9 ,      9 ,      9 ,
         9 ,      9 ,      9 ,      9 ,      9 ,      9 ,      9 ,      1 ,      1 ,     10 ,
         1 ,     11 ,      1 ,      1 ,     12 ,     13 ,     13 ,     13 ,     14 ,     15 ,
        13 ,     16 ,     13 ,     13 ,     13 ,     13 ,     17 ,     18 ,     13 ,     13 ,
        13 ,     19 ,     13 ,     13 ,     13 ,     13 ,     13 ,     13 ,     13 ,     13 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,     12 ,     13 ,     13 ,     13 ,

        14 ,     15 ,     13 ,     16 ,     13 ,     13 ,     13 ,     13 ,     17 ,     18 ,
        13 ,     13 ,     13 ,     19 ,     13 ,     13 ,     13 ,     13 ,     13 ,     13 ,
        13 ,     13 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,

         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1
     }   ;

static   const  YY_CHAR yy_meta [ 20 ]   =
     {     0 ,
         1 ,      1 ,      1 ,      2 ,      1 ,      1 ,      1 ,      2 ,      3 ,      1 ,
         1 ,      4 ,      4 ,      4 ,      4 ,      4 ,      4 ,      4 ,      4
     }   ;

static   const  flex_int16_t yy_base [ 62 ]   =
     {     0 ,
         0 ,      0 ,    163 ,    162 ,     15 ,      0 ,      0 ,      0 ,    157 ,    171 ,
        20 ,     22 ,     30 ,      0 ,    171 ,    136 ,    137 ,    126 ,    171 ,    112 ,
       109 ,     25 ,    113 ,      0 ,     42 ,     61 ,      0 ,     30 ,     35 ,    171 ,
        33 ,    171 ,     23 ,     19 ,     28 ,     80 ,    171 ,     99 ,      0 ,    110 ,
         0 ,    171 ,    171 ,     17 ,     16 ,    171 ,    121 ,      0 ,    171 ,    132 ,
         0 ,    171 ,    171 ,    171 ,    171 ,    151 ,    154 ,     25 ,    158 ,    162 ,
       164
     }   ;

static   const  flex_int16_t yy_def [ 62 ]   =
     {     0 ,
        55 ,      1 ,     56 ,     56 ,     56 ,      5 ,     56 ,     56 ,     55 ,     55 ,
        55 ,     55 ,     57 ,     58 ,     55 ,     55 ,     59 ,     60 ,     55 ,     55 ,
        55 ,     55 ,     55 ,     61 ,     55 ,     55 ,     58 ,     55 ,     59 ,     55 ,
        60 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     38 ,     26 ,
        26 ,     55 ,     55 ,     55 ,     55 ,     55 ,     36 ,     36 ,     55 ,     38 ,
        38 ,     55 ,     55 ,     55 ,      0 ,     55 ,     55 ,     55 ,     55 ,     55 ,
        55
     }   ;

static   const  flex_int16_t yy_nxt [ 191 ]   =
     {     0 ,
        10 ,     11 ,     12 ,     10 ,     10 ,     10 ,     10 ,     10 ,     10 ,     13 ,
        10 ,     14 ,     14 ,     14 ,     14 ,     14 ,     14 ,     14 ,     14 ,     17 ,
        18 ,     22 ,     22 ,     22 ,     22 ,     19 ,     22 ,     22 ,     27 ,     54 ,
        20 ,     53 ,     21 ,     23 ,     46 ,     45 ,     44 ,     24 ,     32 ,     30 ,
        43 ,     25 ,     37 ,     37 ,     37 ,     37 ,     37 ,     37 ,     37 ,     37 ,
        38 ,     37 ,     37 ,     39 ,     39 ,     39 ,     39 ,     39 ,     39 ,     39 ,
        39 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     41 ,
        40 ,     42 ,     41 ,     41 ,     41 ,     41 ,     41 ,     41 ,     41 ,     41 ,
        47 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,     48 ,     47 ,
        49 ,     48 ,     48 ,     48 ,     48 ,     48 ,     48 ,     48 ,     48 ,     50 ,

        50 ,     50 ,     50 ,     50 ,     50 ,     50 ,     50 ,     51 ,     50 ,     52 ,
        51 ,     51 ,     51 ,     51 ,     51 ,     51 ,     51 ,     51 ,     40 ,     35 ,
        34 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     47 ,
        33 ,     32 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,
        50 ,     30 ,     28 ,     50 ,     50 ,     50 ,     50 ,     50 ,     50 ,     50 ,
        50 ,     15 ,     15 ,     15 ,     15 ,     26 ,     55 ,     26 ,     29 ,     29 ,
        29 ,     29 ,     31 ,     31 ,     31 ,     31 ,     36 ,     36 ,     16 ,     16 ,
         9 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,
        55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55
     }   ;

static   const  flex_int16_t yy_chk [ 191 ]   =
     {     0 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,
         1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      1 ,      5 ,
         5 ,     11 ,     11 ,     12 ,     12 ,      5 ,     22 ,     22 ,     58 ,     45 ,
         5 ,     44 ,      5 ,     13 ,     35 ,     34 ,     33 ,     13 ,     31 ,     29 ,
        28 ,     13 ,     25 ,     25 ,     25 ,     25 ,     25 ,     25 ,     25 ,     25 ,
        25 ,     25 ,     25 ,     25 ,     25 ,     25 ,     25 ,     25 ,     25 ,     25 ,
        25 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,
        26 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,     26 ,
        36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     36 ,
        36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     36 ,     38 ,

        38 ,     38 ,     38 ,     38 ,     38 ,     38 ,     38 ,     38 ,     38 ,     38 ,
        38 ,     38 ,     38 ,     38 ,     38 ,     38 ,     38 ,     38 ,     40 ,     23 ,
        21 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     40 ,     47 ,
        20 ,     18 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,     47 ,
        50 ,     17 ,     16 ,     50 ,     50 ,     50 ,     50 ,     50 ,     50 ,     50 ,
        50 ,     56 ,     56 ,     56 ,     56 ,     57 ,      9 ,     57 ,     59 ,     59 ,
        59 ,     59 ,     60 ,     60 ,     60 ,     60 ,     61 ,     61 ,      4 ,      3 ,
        55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,
        55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55 ,     55
     }   ;

/* The intent behind this definition is that it'll catch
 * any uses of REJECT which flex missed.
 */
#define  REJECT reject_used_but_not_detected
#define  yymore ()  yymore_used_but_not_detected
#define  YY_MORE_ADJ  0
#define  YY_RESTORE_YY_MORE_OFFSET
#line   1   "scanner.l"
#line   4   "scanner.l"

#include   < fstream >
#include   "scanner.h"

using   namespace  std ;

   int  savedState ,  hrefMode ;
  std :: string lexeme ;

 
#undef  ECHO 
//#define ECHO cerr << yytext << flush;
#define  ECHO

#undef  LEXEME
#define  LEXEME lexeme  =  yytext ;  

int  yy_more_offset ,  yy_prev_more_offset ;



#line   474   "lex.yy.cc"

/* regular definitions */
#line   477   "lex.yy.cc"

#define  INITIAL  0
#define  INCOMMENT  1
#define  ANCHOR  2
#define  HTMLTAG  3

#ifndef  YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
 * down here because we want the user's section 1 to have been scanned first.
 * The user has a chance to override it with an option.
 */
#include   < unistd . h >
#endif

#ifndef  YY_EXTRA_TYPE
#define  YY_EXTRA_TYPE  void   *
#endif

#ifndef  yytext_ptr
static   void  yy_flex_strncpy  (   char   * ,   const   char   * ,   int   );
#endif

#ifdef  YY_NEED_STRLEN
static   int  yy_flex_strlen  (   const   char   *   );
#endif

#ifndef  YY_NO_INPUT

#endif

/* Amount of stuff to slurp up with each read. */
#ifndef  YY_READ_BUF_SIZE
#ifdef  __ia64__
/* On IA-64, the buffer size is 16k, not 8k */
#define  YY_READ_BUF_SIZE  16384
#else
#define  YY_READ_BUF_SIZE  8192
#endif   /* __ia64__ */
#endif

/* Copy whatever the last rule matched to the standard output. */
#ifndef  ECHO
#define  ECHO  LexerOutput (  yytext ,  yyleng  )
#endif

/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
 * is returned in "result".
 */
#ifndef  YY_INPUT
#define  YY_INPUT ( buf , result , max_size )  \
\
     if   (   ( int )( result  =   LexerInput (   ( char   * )  buf ,  max_size  ))   <   0   )  \
        YY_FATAL_ERROR (   "input in flex scanner failed"   );

#endif

/* No semi-colon after return; correct usage is to write "yyterminate();" -
 * we don't want an extra ';' after the "return" because that will cause
 * some compilers to complain about unreachable statements.
 */
#ifndef  yyterminate
#define  yyterminate ()   return  YY_NULL
#endif

/* Number of entries by which start-condition stack grows. */
#ifndef  YY_START_STACK_INCR
#define  YY_START_STACK_INCR  25
#endif

/* Report a fatal error. */
#ifndef  YY_FATAL_ERROR
#define  YY_FATAL_ERROR ( msg )   LexerError (  msg  )
#endif

/* end tables serialization structures and prototypes */

/* Default declaration of generated scanner - a define so the user can
 * easily add parameters.
 */
#ifndef  YY_DECL
#define  YY_DECL_IS_OURS  1
#define  YY_DECL  int  yyFlexLexer :: yylex ()
#endif   /* !YY_DECL */

/* Code executed at the beginning of each rule, after yytext and yyleng
 * have been set up.
 */
#ifndef  YY_USER_ACTION
#define  YY_USER_ACTION
#endif

/* Code executed at the end of each rule. */
#ifndef  YY_BREAK
#define  YY_BREAK  /*LINTED*/ break ;
#endif

#define  YY_RULE_SETUP \
    YY_USER_ACTION

/** The main scanner function which does all the work.
 */
YY_DECL
{
    yy_state_type yy_current_state ;
     char   * yy_cp ,   * yy_bp ;
     int  yy_act ;
    
     if   (   ! ( yy_init )   )
         {
         ( yy_init )   =   1 ;

#ifdef  YY_USER_INIT
        YY_USER_INIT ;
#endif

         if   (   !   ( yy_start )   )
             ( yy_start )   =   1 ;   /* first start state */

         if   (   !  yyin  )
            yyin . rdbuf ( std :: cin . rdbuf ());

         if   (   !  yyout  )
            yyout . rdbuf ( std :: cout . rdbuf ());

         if   (   !  YY_CURRENT_BUFFER  )   {
            yyensure_buffer_stack  ();
            YY_CURRENT_BUFFER_LVALUE  =
                yy_create_buffer (  yyin ,  YY_BUF_SIZE  );
         }

        yy_load_buffer_state (    );
         }

     {
#line   43   "scanner.l"


#line   615   "lex.yy.cc"

     while   (   /*CONSTCOND*/ 1   )          /* loops until end-of-file is reached */
         {
        yy_cp  =   ( yy_c_buf_p );

         /* Support of yytext. */
         * yy_cp  =   ( yy_hold_char );

         /* yy_bp points to the position in yy_ch_buf of the start of
         * the current run.
         */
        yy_bp  =  yy_cp ;

        yy_current_state  =   ( yy_start );
yy_match :
         do
             {
            YY_CHAR yy_c  =  yy_ec [ YY_SC_TO_UI ( * yy_cp )]   ;
             if   (  yy_accept [ yy_current_state ]   )
                 {
                 ( yy_last_accepting_state )   =  yy_current_state ;
                 ( yy_last_accepting_cpos )   =  yy_cp ;
                 }
             while   (  yy_chk [ yy_base [ yy_current_state ]   +  yy_c ]   !=  yy_current_state  )
                 {
                yy_current_state  =   ( int )  yy_def [ yy_current_state ];
                 if   (  yy_current_state  >=   56   )
                    yy_c  =  yy_meta [ yy_c ];
                 }
            yy_current_state  =  yy_nxt [ yy_base [ yy_current_state ]   +  yy_c ];
             ++ yy_cp ;
             }
         while   (  yy_base [ yy_current_state ]   !=   171   );

yy_find_action :
        yy_act  =  yy_accept [ yy_current_state ];
         if   (  yy_act  ==   0   )
             {   /* have to back up */
            yy_cp  =   ( yy_last_accepting_cpos );
            yy_current_state  =   ( yy_last_accepting_state );
            yy_act  =  yy_accept [ yy_current_state ];
             }

        YY_DO_BEFORE_ACTION ;

do_action :    /* This label is used only to access EOF actions. */

         switch   (  yy_act  )
     {   /* beginning of action switch */
             case   0 :   /* must back up */
             /* undo the effects of YY_DO_BEFORE_ACTION */
             * yy_cp  =   ( yy_hold_char );
            yy_cp  =   ( yy_last_accepting_cpos );
            yy_current_state  =   ( yy_last_accepting_state );
             goto  yy_find_action ;

case   1 :
/* rule 1 can match eol */
YY_RULE_SETUP
#line   45   "scanner.l"
{}
    YY_BREAK
case   2 :
YY_RULE_SETUP
#line   47   "scanner.l"
{ savedState  =  YY_START ;  BEGIN ( INCOMMENT );}
    YY_BREAK
case   3 :
/* rule 3 can match eol */
YY_RULE_SETUP
#line   48   "scanner.l"
{ BEGIN ( ANCHOR );}
    YY_BREAK
case   4 :
/* rule 4 can match eol */
YY_RULE_SETUP
#line   50   "scanner.l"
{ lexeme  =  yytext ;   return  TAG ;}
    YY_BREAK
case   5 :
/* rule 5 can match eol */
YY_RULE_SETUP
#line   51   "scanner.l"
{ lexeme  =  yytext ;   return  TAG ;}
    YY_BREAK
case   6 :
/* rule 6 can match eol */
YY_RULE_SETUP
#line   52   "scanner.l"
{ lexeme  =  yytext ;   return  TAG ;}
    YY_BREAK
case   7 :
YY_RULE_SETUP
#line   53   "scanner.l"
{ LEXEME ;   return  WORD ;}
    YY_BREAK
case   8 :
YY_RULE_SETUP
#line   56   "scanner.l"
{ BEGIN ( savedState );}
    YY_BREAK
case   9 :
YY_RULE_SETUP
#line   58   "scanner.l"
{ hrefMode  =  NAME ;}
    YY_BREAK
case   10 :
YY_RULE_SETUP
#line   59   "scanner.l"
{ hrefMode  =  LINK ;}
    YY_BREAK
case   11 :
/* rule 11 can match eol */
YY_RULE_SETUP
#line   60   "scanner.l"
{ LEXEME ;
                          return  hrefMode ;}
    YY_BREAK
case   12 :
/* rule 12 can match eol */
YY_RULE_SETUP
#line   62   "scanner.l"
{ LEXEME ;
                          return  hrefMode ;}
    YY_BREAK
case   13 :
YY_RULE_SETUP
#line   64   "scanner.l"
{ BEGIN ( INITIAL );}
    YY_BREAK
case  YY_STATE_EOF ( INITIAL ) :
case  YY_STATE_EOF ( INCOMMENT ) :
case  YY_STATE_EOF ( ANCHOR ) :
case  YY_STATE_EOF ( HTMLTAG ) :
#line   66   "scanner.l"
{ return  ENDOFFILE ;}
    YY_BREAK
case   14 :
YY_RULE_SETUP
#line   67   "scanner.l"
{}
    YY_BREAK
case   15 :
YY_RULE_SETUP
#line   69   "scanner.l"
ECHO ;
    YY_BREAK
#line   763   "lex.yy.cc"

     case  YY_END_OF_BUFFER :
         {
         /* Amount of text matched not including the EOB char. */
         int  yy_amount_of_matched_text  =   ( int )   ( yy_cp  -   ( yytext_ptr ))   -   1 ;

         /* Undo the effects of YY_DO_BEFORE_ACTION. */
         * yy_cp  =   ( yy_hold_char );
        YY_RESTORE_YY_MORE_OFFSET

         if   (  YY_CURRENT_BUFFER_LVALUE -> yy_buffer_status  ==  YY_BUFFER_NEW  )
             {
             /* We're scanning a new file or input source.  It's
             * possible that this happened because the user
             * just pointed yyin at a new source and called
             * yylex().  If so, then we have to assure
             * consistency between YY_CURRENT_BUFFER and our
             * globals.  Here is the right place to do so, because
             * this is the first action (other than possibly a
             * back-up) that will match for the new input source.
             */
             ( yy_n_chars )   =  YY_CURRENT_BUFFER_LVALUE -> yy_n_chars ;
            YY_CURRENT_BUFFER_LVALUE -> yy_input_file  =  yyin . rdbuf ();
            YY_CURRENT_BUFFER_LVALUE -> yy_buffer_status  =  YY_BUFFER_NORMAL ;
             }

         /* Note that here we test for yy_c_buf_p "<=" to the position
         * of the first EOB in the buffer, since yy_c_buf_p will
         * already have been incremented past the NUL character
         * (since all states make transitions on EOB to the
         * end-of-buffer state).  Contrast this with the test
         * in input().
         */
         if   (   ( yy_c_buf_p )   <=   & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [( yy_n_chars )]   )
             {   /* This was really a NUL. */
            yy_state_type yy_next_state ;

             ( yy_c_buf_p )   =   ( yytext_ptr )   +  yy_amount_of_matched_text ;

            yy_current_state  =  yy_get_previous_state (    );

             /* Okay, we're now positioned to make the NUL
             * transition.  We couldn't have
             * yy_get_previous_state() go ahead and do it
             * for us because it doesn't know how to deal
             * with the possibility of jamming (and we don't
             * want to build jamming into it because then it
             * will run more slowly).
             */

            yy_next_state  =  yy_try_NUL_trans (  yy_current_state  );

            yy_bp  =   ( yytext_ptr )   +  YY_MORE_ADJ ;

             if   (  yy_next_state  )
                 {
                 /* Consume the NUL. */
                yy_cp  =   ++ ( yy_c_buf_p );
                yy_current_state  =  yy_next_state ;
                 goto  yy_match ;
                 }

             else
                 {
                yy_cp  =   ( yy_c_buf_p );
                 goto  yy_find_action ;
                 }
             }

         else   switch   (  yy_get_next_buffer (    )   )
             {
             case  EOB_ACT_END_OF_FILE :
                 {
                 ( yy_did_buffer_switch_on_eof )   =   0 ;

                 if   (  yywrap (    )   )
                     {
                     /* Note: because we've taken care in
                     * yy_get_next_buffer() to have set up
                     * yytext, we can now set up
                     * yy_c_buf_p so that if some total
                     * hoser (like flex itself) wants to
                     * call the scanner after we return the
                     * YY_NULL, it'll still work - another
                     * YY_NULL will get returned.
                     */
                     ( yy_c_buf_p )   =   ( yytext_ptr )   +  YY_MORE_ADJ ;

                    yy_act  =  YY_STATE_EOF ( YY_START );
                     goto  do_action ;
                     }

                 else
                     {
                     if   (   !   ( yy_did_buffer_switch_on_eof )   )
                        YY_NEW_FILE ;
                     }
                 break ;
                 }

             case  EOB_ACT_CONTINUE_SCAN :
                 ( yy_c_buf_p )   =
                     ( yytext_ptr )   +  yy_amount_of_matched_text ;

                yy_current_state  =  yy_get_previous_state (    );

                yy_cp  =   ( yy_c_buf_p );
                yy_bp  =   ( yytext_ptr )   +  YY_MORE_ADJ ;
                 goto  yy_match ;

             case  EOB_ACT_LAST_MATCH :
                 ( yy_c_buf_p )   =
                 & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [( yy_n_chars )];

                yy_current_state  =  yy_get_previous_state (    );

                yy_cp  =   ( yy_c_buf_p );
                yy_bp  =   ( yytext_ptr )   +  YY_MORE_ADJ ;
                 goto  yy_find_action ;
             }
         break ;
         }

     default :
        YY_FATAL_ERROR (
             "fatal flex scanner internal error--no action found"   );
     }   /* end of action switch */
         }   /* end of scanning one token */
     }   /* end of user's declarations */
}   /* end of yylex */

/* The contents of this function are C++ specific, so the () macro is not used.
 * This constructor simply maintains backward compatibility.
 * DEPRECATED
 */
yyFlexLexer :: yyFlexLexer (  std :: istream *  arg_yyin ,  std :: ostream *  arg_yyout  ) :
    yyin ( arg_yyin  ?  arg_yyin -> rdbuf ()   :  std :: cin . rdbuf ()),
    yyout ( arg_yyout  ?  arg_yyout -> rdbuf ()   :  std :: cout . rdbuf ())
{
    ctor_common ();
}

/* The contents of this function are C++ specific, so the () macro is not used.
 */
yyFlexLexer :: yyFlexLexer (  std :: istream &  arg_yyin ,  std :: ostream &  arg_yyout  ) :
    yyin ( arg_yyin . rdbuf ()),
    yyout ( arg_yyout . rdbuf ())
{
    ctor_common ();
}

/* The contents of this function are C++ specific, so the () macro is not used.
 */
void  yyFlexLexer :: ctor_common ()
{
    yy_c_buf_p  =   0 ;
    yy_init  =   0 ;
    yy_start  =   0 ;
    yy_flex_debug  =   0 ;
    yylineno  =   1 ;     // this will only get updated if %option yylineno

    yy_did_buffer_switch_on_eof  =   0 ;

    yy_looking_for_trail_begin  =   0 ;
    yy_more_flag  =   0 ;
    yy_more_len  =   0 ;
    yy_more_offset  =  yy_prev_more_offset  =   0 ;

    yy_start_stack_ptr  =  yy_start_stack_depth  =   0 ;
    yy_start_stack  =  NULL ;

    yy_buffer_stack  =  NULL ;
    yy_buffer_stack_top  =   0 ;
    yy_buffer_stack_max  =   0 ;

    yy_state_buf  =   0 ;

}

/* The contents of this function are C++ specific, so the () macro is not used.
 */
yyFlexLexer ::~ yyFlexLexer ()
{
     delete   []  yy_state_buf ;
    yyfree (  yy_start_stack   );
    yy_delete_buffer (  YY_CURRENT_BUFFER  );
    yyfree (  yy_buffer_stack   );
}

/* The contents of this function are C++ specific, so the () macro is not used.
 */
void  yyFlexLexer :: switch_streams (  std :: istream &  new_in ,  std :: ostream &  new_out  )
{
     // was if( new_in )
    yy_delete_buffer (  YY_CURRENT_BUFFER  );
    yy_switch_to_buffer (  yy_create_buffer (  new_in ,  YY_BUF_SIZE   )   );

     // was if( new_out )
    yyout . rdbuf ( new_out . rdbuf ());
}

/* The contents of this function are C++ specific, so the () macro is not used.
 */
void  yyFlexLexer :: switch_streams (  std :: istream *  new_in ,  std :: ostream *  new_out  )
{
     if (   !  new_in  )   {
        new_in  =   & yyin ;
     }

     if   (   !  new_out  )   {
        new_out  =   & yyout ;
     }

    switch_streams ( * new_in ,   * new_out );
}

#ifdef  YY_INTERACTIVE
int  yyFlexLexer :: LexerInput (   char *  buf ,   int   /* max_size */   )
#else
int  yyFlexLexer :: LexerInput (   char *  buf ,   int  max_size  )
#endif
{
     if   (  yyin . eof ()   ||  yyin . fail ()   )
         return   0 ;

#ifdef  YY_INTERACTIVE
    yyin . get (  buf [ 0 ]   );

     if   (  yyin . eof ()   )
         return   0 ;

     if   (  yyin . bad ()   )
         return   - 1 ;

     return   1 ;

#else
     ( void )  yyin . read (  buf ,  max_size  );

     if   (  yyin . bad ()   )
         return   - 1 ;
     else
         return  yyin . gcount ();
#endif
}

void  yyFlexLexer :: LexerOutput (   const   char *  buf ,   int  size  )
{
     ( void )  yyout . write (  buf ,  size  );
}

/* yy_get_next_buffer - try to read in a new buffer
 *
 * Returns a code representing an action:
 *  EOB_ACT_LAST_MATCH -
 *  EOB_ACT_CONTINUE_SCAN - continue scanning from current position
 *  EOB_ACT_END_OF_FILE - end of file
 */
int  yyFlexLexer :: yy_get_next_buffer ()
{
         char   * dest  =  YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf ;
     char   * source  =   ( yytext_ptr );
     int  number_to_move ,  i ;
     int  ret_val ;

     if   (   ( yy_c_buf_p )   >   & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [( yy_n_chars )   +   1 ]   )
        YY_FATAL_ERROR (
         "fatal flex scanner internal error--end of buffer missed"   );

     if   (  YY_CURRENT_BUFFER_LVALUE -> yy_fill_buffer  ==   0   )
         {   /* Don't try to fill the buffer, so this is an EOF. */
         if   (   ( yy_c_buf_p )   -   ( yytext_ptr )   -  YY_MORE_ADJ  ==   1   )
             {
             /* We matched a single character, the EOB, so
             * treat this as a final EOF.
             */
             return  EOB_ACT_END_OF_FILE ;
             }

         else
             {
             /* We matched some text prior to the EOB, first
             * process it.
             */
             return  EOB_ACT_LAST_MATCH ;
             }
         }

     /* Try to read more data. */

     /* First move last chars to start of buffer. */
    number_to_move  =   ( int )   (( yy_c_buf_p )   -   ( yytext_ptr )   -   1 );

     for   (  i  =   0 ;  i  <  number_to_move ;   ++ )
         * ( dest ++ )   =   * ( source ++ );

     if   (  YY_CURRENT_BUFFER_LVALUE -> yy_buffer_status  ==  YY_BUFFER_EOF_PENDING  )
         /* don't do the read, it's not guaranteed to return an EOF,
         * just force an EOF
         */
        YY_CURRENT_BUFFER_LVALUE -> yy_n_chars  =   ( yy_n_chars )   =   0 ;

     else
         {
             int  num_to_read  =
            YY_CURRENT_BUFFER_LVALUE -> yy_buf_size  -  number_to_move  -   1 ;

         while   (  num_to_read  <=   0   )
             {   /* Not enough room in the buffer - grow it. */

             /* just a shorter name for the current buffer */
            YY_BUFFER_STATE b  =  YY_CURRENT_BUFFER_LVALUE ;

             int  yy_c_buf_p_offset  =
                 ( int )   (( yy_c_buf_p )   -  b -> yy_ch_buf );

             if   (  b -> yy_is_our_buffer  )
                 {
                 int  new_size  =  b -> yy_buf_size  *   2 ;

                 if   (  new_size  <=   0   )
                    b -> yy_buf_size  +=  b -> yy_buf_size  /   8 ;
                 else
                    b -> yy_buf_size  *=   2 ;

                b -> yy_ch_buf  =   ( char   * )
                     /* Include room in for 2 EOB chars. */
                    yyrealloc (   ( void   * )  b -> yy_ch_buf ,
                              ( yy_size_t )   ( b -> yy_buf_size  +   2 )    );
                 }
             else
                 /* Can't grow it, we don't own it. */
                b -> yy_ch_buf  =  NULL ;

             if   (   !  b -> yy_ch_buf  )
                YY_FATAL_ERROR (
                 "fatal error - scanner input buffer overflow"   );

             ( yy_c_buf_p )   =   & b -> yy_ch_buf [ yy_c_buf_p_offset ];

            num_to_read  =  YY_CURRENT_BUFFER_LVALUE -> yy_buf_size  -
                        number_to_move  -   1 ;

             }

         if   (  num_to_read  >  YY_READ_BUF_SIZE  )
            num_to_read  =  YY_READ_BUF_SIZE ;

         /* Read in more data. */
        YY_INPUT (   ( & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [ number_to_move ]),
             ( yy_n_chars ),  num_to_read  );

        YY_CURRENT_BUFFER_LVALUE -> yy_n_chars  =   ( yy_n_chars );
         }

     if   (   ( yy_n_chars )   ==   0   )
         {
         if   (  number_to_move  ==  YY_MORE_ADJ  )
             {
            ret_val  =  EOB_ACT_END_OF_FILE ;
            yyrestart (  yyin   );
             }

         else
             {
            ret_val  =  EOB_ACT_LAST_MATCH ;
            YY_CURRENT_BUFFER_LVALUE -> yy_buffer_status  =
                YY_BUFFER_EOF_PENDING ;
             }
         }

     else
        ret_val  =  EOB_ACT_CONTINUE_SCAN ;

     if   ((( yy_n_chars )   +  number_to_move )   >  YY_CURRENT_BUFFER_LVALUE -> yy_buf_size )   {
         /* Extend the array by 50%, plus the number we really need. */
         int  new_size  =   ( yy_n_chars )   +  number_to_move  +   (( yy_n_chars )   >>   1 );
        YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf  =   ( char   * )  yyrealloc (
             ( void   * )  YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf ,   ( yy_size_t )  new_size   );
         if   (   !  YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf  )
            YY_FATAL_ERROR (   "out of dynamic memory in yy_get_next_buffer()"   );
         /* "- 2" to take care of EOB's */
        YY_CURRENT_BUFFER_LVALUE -> yy_buf_size  =   ( int )   ( new_size  -   2 );
     }

     ( yy_n_chars )   +=  number_to_move ;
    YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [( yy_n_chars )]   =  YY_END_OF_BUFFER_CHAR ;
    YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [( yy_n_chars )   +   1 ]   =  YY_END_OF_BUFFER_CHAR ;

     ( yytext_ptr )   =   & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [ 0 ];

     return  ret_val ;
}

/* yy_get_previous_state - get the state just before the EOB char was reached */

    yy_state_type yyFlexLexer :: yy_get_previous_state ()
{
    yy_state_type yy_current_state ;
     char   * yy_cp ;
    
    yy_current_state  =   ( yy_start );

     for   (  yy_cp  =   ( yytext_ptr )   +  YY_MORE_ADJ ;  yy_cp  <   ( yy_c_buf_p );   ++ yy_cp  )
         {
        YY_CHAR yy_c  =   ( * yy_cp  ?  yy_ec [ YY_SC_TO_UI ( * yy_cp )]   :   1 );
         if   (  yy_accept [ yy_current_state ]   )
             {
             ( yy_last_accepting_state )   =  yy_current_state ;
             ( yy_last_accepting_cpos )   =  yy_cp ;
             }
         while   (  yy_chk [ yy_base [ yy_current_state ]   +  yy_c ]   !=  yy_current_state  )
             {
            yy_current_state  =   ( int )  yy_def [ yy_current_state ];
             if   (  yy_current_state  >=   56   )
                yy_c  =  yy_meta [ yy_c ];
             }
        yy_current_state  =  yy_nxt [ yy_base [ yy_current_state ]   +  yy_c ];
         }

     return  yy_current_state ;
}

/* yy_try_NUL_trans - try to make a transition on the NUL character
 *
 * synopsis
 *  next_state = yy_try_NUL_trans( current_state );
 */
    yy_state_type yyFlexLexer :: yy_try_NUL_trans (  yy_state_type yy_current_state  )
{
     int  yy_is_jam ;
         char   * yy_cp  =   ( yy_c_buf_p );

    YY_CHAR yy_c  =   1 ;
     if   (  yy_accept [ yy_current_state ]   )
         {
         ( yy_last_accepting_state )   =  yy_current_state ;
         ( yy_last_accepting_cpos )   =  yy_cp ;
         }
     while   (  yy_chk [ yy_base [ yy_current_state ]   +  yy_c ]   !=  yy_current_state  )
         {
        yy_current_state  =   ( int )  yy_def [ yy_current_state ];
         if   (  yy_current_state  >=   56   )
            yy_c  =  yy_meta [ yy_c ];
         }
    yy_current_state  =  yy_nxt [ yy_base [ yy_current_state ]   +  yy_c ];
    yy_is_jam  =   ( yy_current_state  ==   55 );

         return  yy_is_jam  ?   0   :  yy_current_state ;
}

#ifndef  YY_NO_UNPUT
     void  yyFlexLexer :: yyunput (   int  c ,   char *  yy_bp )
{
     char   * yy_cp ;
    
    yy_cp  =   ( yy_c_buf_p );

     /* undo effects of setting up yytext */
     * yy_cp  =   ( yy_hold_char );

     if   (  yy_cp  <  YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf  +   2   )
         {   /* need to shift things up to make room */
         /* +2 for EOB chars. */
         int  number_to_move  =   ( yy_n_chars )   +   2 ;
         char   * dest  =   & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [
                    YY_CURRENT_BUFFER_LVALUE -> yy_buf_size  +   2 ];
         char   * source  =
                 & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [ number_to_move ];

         while   (  source  >  YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf  )
             *-- dest  =   *-- source ;

        yy_cp  +=   ( int )   ( dest  -  source );
        yy_bp  +=   ( int )   ( dest  -  source );
        YY_CURRENT_BUFFER_LVALUE -> yy_n_chars  =
             ( yy_n_chars )   =   ( int )  YY_CURRENT_BUFFER_LVALUE -> yy_buf_size ;

         if   (  yy_cp  <  YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf  +   2   )
            YY_FATAL_ERROR (   "flex scanner push-back overflow"   );
         }

     *-- yy_cp  =   ( char )  c ;

     ( yytext_ptr )   =  yy_bp ;
     ( yy_hold_char )   =   * yy_cp ;
     ( yy_c_buf_p )   =  yy_cp ;
}
#endif

     int  yyFlexLexer :: yyinput ()
{
     int  c ;
    
     * ( yy_c_buf_p )   =   ( yy_hold_char );

     if   (   * ( yy_c_buf_p )   ==  YY_END_OF_BUFFER_CHAR  )
         {
         /* yy_c_buf_p now points to the character we want to return.
         * If this occurs *before* the EOB characters, then it's a
         * valid NUL; if not, then we've hit the end of the buffer.
         */
         if   (   ( yy_c_buf_p )   <   & YY_CURRENT_BUFFER_LVALUE -> yy_ch_buf [( yy_n_chars )]   )
             /* This was really a NUL. */
             * ( yy_c_buf_p )   =   '\0' ;

         else
             {   /* need more input */
             int  offset  =   ( int )   (( yy_c_buf_p )   -   ( yytext_ptr ));
             ++ ( yy_c_buf_p );

             switch   (  yy_get_next_buffer (    )   )
                 {
                 case  EOB_ACT_LAST_MATCH :
                     /* This happens because yy_g_n_b()
                     * sees that we've accumulated a
                     * token and flags that we need to
                     * try matching the token before
                     * proceeding.  But for input(),
                     * there's no matching to consider.
                     * So convert the EOB_ACT_LAST_MATCH
                     * to EOB_ACT_END_OF_FILE.
                     */

                     /* Reset buffer status. */
                    yyrestart (  yyin  );

                     /*FALLTHROUGH*/

                 case  EOB_ACT_END_OF_FILE :
                     {
                     if   (  yywrap (    )   )
                         return   0 ;

                     if   (   !   ( yy_did_buffer_switch_on_eof )   )
                        YY_NEW_FILE ;
#ifdef  __cplusplus
                     return  yyinput ();
#else
                     return  input ();
#endif
                     }

                 case  EOB_ACT_CONTINUE_SCAN :
                     ( yy_c_buf_p )   =   ( yytext_ptr )   +  offset ;
                     break ;
                 }
             }
         }

    c  =   * ( unsigned   char   * )   ( yy_c_buf_p );      /* cast for 8-bit char's */
     * ( yy_c_buf_p )   =   '\0' ;     /* preserve yytext */
     ( yy_hold_char )   =   *++ ( yy_c_buf_p );

     return  c ;
}

/** Immediately switch to a different input stream.
 *  @param  input_file A readable stream.
 * 
 *  @note  This function does not reset the start condition to  @c  INITIAL .
 */
     void  yyFlexLexer :: yyrestart (  std :: istream &  input_file  )
{
    
     if   (   !  YY_CURRENT_BUFFER  ){
        yyensure_buffer_stack  ();
        YY_CURRENT_BUFFER_LVALUE  =
            yy_create_buffer (  yyin ,  YY_BUF_SIZE  );
     }

    yy_init_buffer (  YY_CURRENT_BUFFER ,  input_file  );
    yy_load_buffer_state (    );
}

/** Delegate to the new version that takes an istream reference.
 *  @param  input_file A readable stream.
 * 
 *  @note  This function does not reset the start condition to  @c  INITIAL .
 */
void  yyFlexLexer :: yyrestart (  std :: istream *  input_file  )
{
     if (   !  input_file  )   {
        input_file  =   & yyin ;
     }
    yyrestart (   * input_file  );
}

/** Switch to a different input buffer.
 *  @param  new_buffer The new input buffer.
 * 
 */
     void  yyFlexLexer :: yy_switch_to_buffer (  YY_BUFFER_STATE new_buffer  )
{
    
     /* TODO. We should be able to replace this entire function body
     * with
     *      yypop_buffer_state();
     *      yypush_buffer_state(new_buffer);
     */
    yyensure_buffer_stack  ();
     if   (  YY_CURRENT_BUFFER  ==  new_buffer  )
         return ;

     if   (  YY_CURRENT_BUFFER  )
         {
         /* Flush out information for old buffer. */
         * ( yy_c_buf_p )   =   ( yy_hold_char );
        YY_CURRENT_BUFFER_LVALUE -> yy_buf_pos  =   ( yy_c_buf_p );
        YY_CURRENT_BUFFER_LVALUE -> yy_n_chars  =   ( yy_n_chars );
         }

    YY_CURRENT_BUFFER_LVALUE  =  new_buffer ;
    yy_load_buffer_state (    );

     /* We don't actually know whether we did this switch during
     * EOF (yywrap()) processing, but the only time this flag
     * is looked at is after yywrap() is called, so it's safe
     * to go ahead and always set it.
     */
     ( yy_did_buffer_switch_on_eof )   =   1 ;
}

     void  yyFlexLexer :: yy_load_buffer_state ()
{
         ( yy_n_chars )   =  YY_CURRENT_BUFFER_LVALUE -> yy_n_chars ;
     ( yytext_ptr )   =   ( yy_c_buf_p )   =  YY_CURRENT_BUFFER_LVALUE -> yy_buf_pos ;
    yyin . rdbuf ( YY_CURRENT_BUFFER_LVALUE -> yy_input_file );
     ( yy_hold_char )   =   * ( yy_c_buf_p );
}

/** Allocate and initialize an input buffer state.
 *  @param  file A readable stream.
 *  @param  size The character buffer size in bytes. When in doubt, use  @c  YY_BUF_SIZE.
 * 
 *  @return  the allocated buffer state.
 */
    YY_BUFFER_STATE yyFlexLexer :: yy_create_buffer (  std :: istream &  file ,   int  size  )
{
    YY_BUFFER_STATE b ;
    
    b  =   ( YY_BUFFER_STATE )  yyalloc (   sizeof (   struct  yy_buffer_state  )    );
     if   (   !  b  )
        YY_FATAL_ERROR (   "out of dynamic memory in yy_create_buffer()"   );

    b -> yy_buf_size  =  size ;

     /* yy_ch_buf has to be 2 characters longer than the size given because
     * we need to put in 2 end-of-buffer characters.
     */
    b -> yy_ch_buf  =   ( char   * )  yyalloc (   ( yy_size_t )   ( b -> yy_buf_size  +   2 )    );
     if   (   !  b -> yy_ch_buf  )
        YY_FATAL_ERROR (   "out of dynamic memory in yy_create_buffer()"   );

    b -> yy_is_our_buffer  =   1 ;

    yy_init_buffer (  b ,  file  );

     return  b ;
}

/** Delegate creation of buffers to the new version that takes an istream reference.
 *  @param  file A readable stream.
 *  @param  size The character buffer size in bytes. When in doubt, use  @c  YY_BUF_SIZE.
 * 
 *  @return  the allocated buffer state.
 */
    YY_BUFFER_STATE yyFlexLexer :: yy_create_buffer (  std :: istream *  file ,   int  size  )
{
     return  yy_create_buffer (   * file ,  size  );
}

/** Destroy the buffer.
 *  @param  b a buffer created with yy_create_buffer()
 * 
 */
     void  yyFlexLexer :: yy_delete_buffer (  YY_BUFFER_STATE b  )
{
    
     if   (   !  b  )
         return ;

     if   (  b  ==  YY_CURRENT_BUFFER  )   /* Not sure if we should pop here. */
        YY_CURRENT_BUFFER_LVALUE  =   ( YY_BUFFER_STATE )   0 ;

     if   (  b -> yy_is_our_buffer  )
        yyfree (   ( void   * )  b -> yy_ch_buf   );

    yyfree (   ( void   * )  b   );
}

/* Initializes or reinitializes a buffer.
 * This function is sometimes called more than once on the same buffer,
 * such as during a yyrestart() or at EOF.
 */
     void  yyFlexLexer :: yy_init_buffer (  YY_BUFFER_STATE b ,  std :: istream &  file  )

{
     int  oerrno  =  errno ;
    
    yy_flush_buffer (  b  );

    b -> yy_input_file  =  file . rdbuf ();
    b -> yy_fill_buffer  =   1 ;

     /* If b is the current buffer, then yy_init_buffer was _probably_
     * called from yyrestart() or through yy_get_next_buffer.
     * In that case, we don't want to reset the lineno or column.
     */
     if   ( !=  YY_CURRENT_BUFFER ){
        b -> yy_bs_lineno  =   1 ;
        b -> yy_bs_column  =   0 ;
     }

    b -> yy_is_interactive  =   0 ;
    errno  =  oerrno ;
}

/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
 *  @param  b the buffer state to be flushed, usually  @c  YY_CURRENT_BUFFER.
 * 
 */
     void  yyFlexLexer :: yy_flush_buffer (  YY_BUFFER_STATE b  )
{
         if   (   !  b  )
         return ;

    b -> yy_n_chars  =   0 ;

     /* We always need two end-of-buffer characters.  The first causes
     * a transition to the end-of-buffer state.  The second causes
     * a jam in that state.
     */
    b -> yy_ch_buf [ 0 ]   =  YY_END_OF_BUFFER_CHAR ;
    b -> yy_ch_buf [ 1 ]   =  YY_END_OF_BUFFER_CHAR ;

    b -> yy_buf_pos  =   & b -> yy_ch_buf [ 0 ];

    b -> yy_at_bol  =   1 ;
    b -> yy_buffer_status  =  YY_BUFFER_NEW ;

     if   (  b  ==  YY_CURRENT_BUFFER  )
        yy_load_buffer_state (    );
}

/** Pushes the new state onto the stack. The new state becomes
 *  the current state. This function will allocate the stack
 *  if necessary.
 *   @param  new_buffer The new state.
 *  
 */
void  yyFlexLexer :: yypush_buffer_state  ( YY_BUFFER_STATE new_buffer )
{
         if   ( new_buffer  ==  NULL )
         return ;

    yyensure_buffer_stack ();

     /* This block is copied from yy_switch_to_buffer. */
     if   (  YY_CURRENT_BUFFER  )
         {
         /* Flush out information for old buffer. */
         * ( yy_c_buf_p )   =   ( yy_hold_char );
        YY_CURRENT_BUFFER_LVALUE -> yy_buf_pos  =   ( yy_c_buf_p );
        YY_CURRENT_BUFFER_LVALUE -> yy_n_chars  =   ( yy_n_chars );
         }

     /* Only push if top exists. Otherwise, replace top. */
     if   ( YY_CURRENT_BUFFER )
         ( yy_buffer_stack_top ) ++ ;
    YY_CURRENT_BUFFER_LVALUE  =  new_buffer ;

     /* copied from yy_switch_to_buffer. */
    yy_load_buffer_state (    );
     ( yy_did_buffer_switch_on_eof )   =   1 ;
}

/** Removes and deletes the top of the stack, if present.
 *  The next element becomes the new top.
 *  
 */
void  yyFlexLexer :: yypop_buffer_state  ( void )
{
         if   ( ! YY_CURRENT_BUFFER )
         return ;

    yy_delete_buffer ( YY_CURRENT_BUFFER  );
    YY_CURRENT_BUFFER_LVALUE  =  NULL ;
     if   (( yy_buffer_stack_top )   >   0 )
         -- ( yy_buffer_stack_top );

     if   ( YY_CURRENT_BUFFER )   {
        yy_load_buffer_state (    );
         ( yy_did_buffer_switch_on_eof )   =   1 ;
     }
}

/* Allocates the stack if it does not exist.
 *  Guarantees space for at least one push.
 */
void  yyFlexLexer :: yyensure_buffer_stack ( void )
{
    yy_size_t num_to_alloc ;
    
     if   ( ! ( yy_buffer_stack ))   {

         /* First allocation is just for 2 elements, since we don't know if this
         * scanner will even need a stack. We use 2 instead of 1 to avoid an
         * immediate realloc on the next call.
         */
      num_to_alloc  =   1 ;   /* After all that talk, this was set to 1 anyways... */
         ( yy_buffer_stack )   =   ( struct  yy_buffer_state ** ) yyalloc
                                 ( num_to_alloc  *   sizeof ( struct  yy_buffer_state * )
                                 );
         if   (   !   ( yy_buffer_stack )   )
            YY_FATAL_ERROR (   "out of dynamic memory in yyensure_buffer_stack()"   );

        memset (( yy_buffer_stack ),   0 ,  num_to_alloc  *   sizeof ( struct  yy_buffer_state * ));

         ( yy_buffer_stack_max )   =  num_to_alloc ;
         ( yy_buffer_stack_top )   =   0 ;
         return ;
     }

     if   (( yy_buffer_stack_top )   >=   (( yy_buffer_stack_max ))   -   1 ){

         /* Increase the buffer to prepare for a possible push. */
        yy_size_t grow_size  =   8   /* arbitrary grow size */ ;

        num_to_alloc  =   ( yy_buffer_stack_max )   +  grow_size ;
         ( yy_buffer_stack )   =   ( struct  yy_buffer_state ** ) yyrealloc
                                 (( yy_buffer_stack ),
                                num_to_alloc  *   sizeof ( struct  yy_buffer_state * )
                                 );
         if   (   !   ( yy_buffer_stack )   )
            YY_FATAL_ERROR (   "out of dynamic memory in yyensure_buffer_stack()"   );

         /* zero only the new slots.*/
        memset (( yy_buffer_stack )   +   ( yy_buffer_stack_max ),   0 ,  grow_size  *   sizeof ( struct  yy_buffer_state * ));
         ( yy_buffer_stack_max )   =  num_to_alloc ;
     }
}

     void  yyFlexLexer :: yy_push_state (   int  _new_state  )
{
         if   (   ( yy_start_stack_ptr )   >=   ( yy_start_stack_depth )   )
         {
        yy_size_t new_size ;

         ( yy_start_stack_depth )   +=  YY_START_STACK_INCR ;
        new_size  =   ( yy_size_t )   ( yy_start_stack_depth )   *   sizeof (   int   );

         if   (   !   ( yy_start_stack )   )
             ( yy_start_stack )   =   ( int   * )  yyalloc (  new_size   );

         else
             ( yy_start_stack )   =   ( int   * )  yyrealloc (
                     ( void   * )   ( yy_start_stack ),  new_size   );

         if   (   !   ( yy_start_stack )   )
            YY_FATAL_ERROR (   "out of memory expanding start-condition stack"   );
         }

     ( yy_start_stack )[( yy_start_stack_ptr ) ++ ]   =  YY_START ;

    BEGIN ( _new_state );
}

     void  yyFlexLexer :: yy_pop_state ()
{
         if   (   -- ( yy_start_stack_ptr )   <   0   )
        YY_FATAL_ERROR (   "start-condition stack underflow"   );

    BEGIN (( yy_start_stack )[( yy_start_stack_ptr )]);
}

     int  yyFlexLexer :: yy_top_state ()
{
         return   ( yy_start_stack )[( yy_start_stack_ptr )   -   1 ];
}

#ifndef  YY_EXIT_FAILURE
#define  YY_EXIT_FAILURE  2
#endif

void  yyFlexLexer :: LexerError (   const   char *  msg  )
{
        std :: cerr  <<  msg  <<  std :: endl ;
    exit (  YY_EXIT_FAILURE  );
}

/* Redefine yyless() so it works in section 3 code. */

#undef  yyless
#define  yyless ( n )  \
     do  \
         {  \
         /* Undo effects of setting up yytext. */  \
         int  yyless_macro_arg  =   ( n );  \
        YY_LESS_LINENO ( yyless_macro_arg ); \
        yytext [ yyleng ]   =   ( yy_hold_char );  \
         ( yy_c_buf_p )   =  yytext  +  yyless_macro_arg ;  \
         ( yy_hold_char )   =   * ( yy_c_buf_p );  \
         * ( yy_c_buf_p )   =   '\0' ;  \
        yyleng  =  yyless_macro_arg ;  \
         }  \
     while   (   0   )

/* Accessor  methods (get/set functions) to struct members. */

/*
 * Internal utility routines.
 */

#ifndef  yytext_ptr
static   void  yy_flex_strncpy  ( char *  s1 ,   const   char   *  s2 ,   int  n  )
{
        
     int  i ;
     for   (  i  =   0 ;  i  <  n ;   ++ )
        s1 [ i ]   =  s2 [ i ];
}
#endif

#ifdef  YY_NEED_STRLEN
static   int  yy_flex_strlen  ( const   char   *  s  )
{
     int  n ;
     for   (  n  =   0 ;  s [ n ];   ++ )
         ;

     return  n ;
}
#endif

void   * yyalloc  ( yy_size_t  size  )
{
             return  malloc ( size );
}

void   * yyrealloc   ( void   *  ptr ,  yy_size_t  size  )
{
        
     /* The cast to (char *) in the following accommodates both
     * implementations that use char* generic pointers, and those
     * that use void* generic pointers.  It works with the latter
     * because both ANSI C and C++ allow castless assignment from
     * any pointer type to void*, and deal with argument conversions
     * as though doing an assignment.
     */
     return  realloc ( ptr ,  size );
}

void  yyfree  ( void   *  ptr  )
{
            free (   ( char   * )  ptr  );     /* see yyrealloc() for (char *) cast */
}

#define  YYTABLES_NAME  "yytables"

#line   69   "scanner.l"








makefile

MAINPROG=xmlcheck DIR=${PWD} ASST=$(notdir ${DIR}) CC=gcc CXX=g++ ## # Adjust settings for different compilers # ifeq ($(OS),Windows_NT) # # Flags for Windows compilers CPPFLAGS=-g -std=c++17 -MMD -pthread -D_GLIBCXX_DEBUG -Wall LFLAGS= RM=del /q EXE=.exe else # # Flags for Linux & MacOS CPPFLAGS=-g -std=c++17 -MMD -pthread -D_GLIBCXX_DEBUG -Wall LFLAGSx=-fuse-ld=gold -pthread RM=/bin/rm -rf EXE= endif # ######################################################################## # Macro definitions for "standard" C and C++ compilations # CFLAGS=-g TARGET=$(MAINPROG)$(EXE) CPPS=$(wildcard *.cpp) MAINCPPS=$(filter-out unittest.cpp test%.cpp, $(CPPS)) TESTCPPS=$(filter-out $(MAINPROG).cpp, $(CPPS)) LINK=g++ $(CPPFLAGS) # # # In most cases, you should not change anything below this line. # # The following is "boilerplate" to set up the standard compilation # commands: # MAINOBJS=$(MAINCPPS:%.cpp=%.o) TESTOBJS=$(TESTCPPS:%.cpp=%.o) DEPENDENCIES = $(CPPS:%.cpp=%.d) %.d: %.cpp touch $@ %.o: %.cpp $(CXX) $(CPPFLAGS) -o $@ -c $*.cpp # # Targets: # all: $(TARGET) unittest$(EXE) $(TARGET): $(MAINOBJS) $(LINK) $(FLAGS) -o $(TARGET) $^ $(LFLAGS) clean: -/bin/rm -rf *.d *.o $(TARGET) unittest$(EXE) docs documentation: -mkdir docs doxygen Doxyfile unittest$(EXE): $(TESTOBJS) $(LINK) $(FLAGS) -o $@ $^ $(LFLAGS) make.dep: $(DEPENDENCIES) -cat $(DEPENDENCIES) > $@ include make.dep

scanner.h

#ifndef SCANNER_H #define SCANNER_H #include <string> extern std::string lexeme; // token kinds const int ENDOFFILE = 0; const int WORD = 1; const int LINK = 2; const int NAME = 3; const int TAG = 4; const int ERROR = -1; #endif

scanner.l

%option noyywrap %{ #include <fstream> #include "scanner.h" using namespace std; int savedState, hrefMode; std::string lexeme; #undef ECHO //#define ECHO cerr << yytext << flush; #define ECHO #undef LEXEME #define LEXEME lexeme = yytext; int yy_more_offset, yy_prev_more_offset; %} %x INCOMMENT ANCHOR HTMLTAG /* regular definitions */ delim [ \t\r\n] tagdelim [ \t\r\n\>] whitespace {delim}+ digit [0-9] alpha [a-zA-Z] nota [b-zB-Z] alphanum [a-zA-Z0-9] pathchars [-~a-zA-Z0-9_/\\.] number {digit}+(\.{digit}+)? quote \" apostrophe ['] tagfill .|{delim} %% {whitespace} {} <INITIAL>\<!-- {savedState = YY_START; BEGIN(INCOMMENT);} <INITIAL>\<[aA][^a-zA-Z] {BEGIN(ANCHOR);} <INITIAL>\<{nota}{alphanum}*[^\>]*\> {lexeme = yytext; return TAG;} <INITIAL>\<[aA]{alphanum}+[^\>]*\> {lexeme = yytext; return TAG;} <INITIAL>\<[/]{alphanum}+[^\>]*\> {lexeme = yytext; return TAG;} <INITIAL>{alpha}+ {LEXEME; return WORD;} <INCOMMENT>--\> {BEGIN(savedState);} <ANCHOR>[Nn][Aa][Mm][Ee] {hrefMode = NAME;} <ANCHOR>[Hh][Rr][Ee][Ff] {hrefMode = LINK;} <ANCHOR>\"[^\"]*\" {LEXEME; return hrefMode;} <ANCHOR>\'[^\']*\' {LEXEME; return hrefMode;} <ANCHOR>\> {BEGIN(INITIAL);} <<EOF>> {return ENDOFFILE;} . {} %%

test0.html

Hello world!

test1.html

CS 361: Hardware & Software Requirements

Steven Zeil July 28, 1999 1 Technical Requirements - Hardware 2 Technical Requirements - Software

[next]

testBalancer.cpp

testBalancer.cpp

/*
 * testBalancer.cpp
 *
 * Unit tests for Balancer class
 *
 *  Created on: June 4, 2019
 *      Author: zeil
 */

#include   "balancer.h"

#include   < vector >
#include   < string >

#include   "unittest.h"


using   namespace  std ;




UnitTest   ( BalancerDefaultConstructor )   {
     Balancer  bal ;

    assertThat  ( bal . status (),  is ( 1 ));
}

UnitTest   ( BalancerOneSingleton )   {
     Balancer  bal ;

    bal . tag ( "<img src='foo.png' aligh='right'/>" );
    assertThat  ( bal . status (),  is ( 1 ));
}

UnitTest   ( BalancerOneOpener )   {
     Balancer  bal ;

    bal . tag ( "<div class='title'>" );
    assertThat  ( bal . status (),  is ( 0 ));
}

UnitTest   ( BalancerOneCloser )   {
     Balancer  bal ;

    bal . tag ( "</div>" );
    assertThat  ( bal . status (),  is ( - 1 ));
}

UnitTest   ( BalancerSimpleMismatch )   {
     Balancer  bal ;

    bal . tag ( "<a>" );
    assertThat  ( bal . status (),  is ( 0 ));
    bal . tag ( "<b />" );
    assertThat  ( bal . status (),  is ( 0 ));
    bal . tag ( "</A>" );
    assertThat  ( bal . status (),  is ( - 1 ));
}


UnitTest   ( BalancerAlternation )   {
     Balancer  bal ;

     for   ( int  i  =   0 ;  i  <   12 ;   ++ i )   {
         if   ( %   2   ==   0 )   {
            bal . tag ( "<a>" );
         }   else   {
            bal . tag ( "<b>" );
         }
        assertThat ( bal . status (),  is ( 0 ));

        bal . tag ( "<a/>" );
        assertThat ( bal . status (),  is ( 0 ));

        bal . tag ( "<b/>" );
        assertThat ( bal . status (),  is ( 0 ));

         if   ( %   2   ==   0 )   {
            bal . tag ( "</a>" );
         }   else   {
            bal . tag ( "</b>" );
         }
        assertThat ( bal . status (),  is ( 1 ));
     }
    bal . tag ( "</a>" );
    assertThat ( bal . status (),  is ( - 1 ));
}



UnitTest   ( BalancerNesting )   {
     Balancer  bal ;

     for   ( int  i  =   0 ;  i  <   12 ;   ++ i )   {
         if   ( %   2   ==   0 )   {
            bal . tag ( "<a>" );
         }   else   {
            bal . tag ( "<b>" );
         }
        assertThat ( bal . status (),  is ( 0 ));

        bal . tag ( "<a/>" );
        assertThat ( bal . status (),  is ( 0 ));

        bal . tag ( "<b/>" );
        assertThat ( bal . status (),  is ( 0 ));
     }


     for   ( int  i  =   0 ;  i  <   12 ;   ++ i )   {
        bal . tag ( "<a/>" );
        assertThat ( bal . status (),  is ( 0 ));

        bal . tag ( "<b/>" );
        assertThat ( bal . status (),  is ( 0 ));

         if   ( %   2   ==   0 )   {
            bal . tag ( "</b>" );
         }   else   {
            bal . tag ( "</a>" );
         }
         int  expected  =   ( <   11 )   ?   0   :   1 ;
        assertThat ( bal . status (),  is ( expected ));
     }
    bal . tag ( "</a>" );
    assertThat ( bal . status (),  is ( - 1 ));
}

UnitTest   ( BalancerMixed )   {
     Balancer  bal ;
     for   ( int  k  =   0 ;  k  <   4 ;   ++ k )   {
        bal . tag ( "<a img=\"whatever.gif\">" );
     }
     for   ( int  k  =   0 ;  k  <   2 ;   ++ k )   {
         for   ( int  i  =   0 ;  i  <   12 ;   ++ i )   {
             if   ( %   2   ==   0 )   {
                bal . tag ( "<a>" );
             }   else   {
                bal . tag ( "<b>" );
             }
            assertThat ( bal . status (),  is ( 0 ));

            bal . tag ( "<a/>" );
            assertThat ( bal . status (),  is ( 0 ));

            bal . tag ( "<b/>" );
            assertThat ( bal . status (),  is ( 0 ));
         }


         for   ( int  i  =   0 ;  i  <   12 ;   ++ i )   {
            bal . tag ( "<a/>" );
            assertThat ( bal . status (),  is ( 0 ));

            bal . tag ( "<b/>" );
            assertThat ( bal . status (),  is ( 0 ));

             if   ( %   2   ==   0 )   {
                bal . tag ( "</b>" );
             }   else   {
                bal . tag ( "</a>" );
             }
            assertThat ( bal . status (),  is ( 0 ));
         }
     }
     for   ( int  k  =   0 ;  k  <   4 ;   ++ k )   {
        bal . tag ( "</a>" );
     }
    assertThat ( bal . status (),  is ( 1 ));
}

unittest.cpp

#include <algorithm> #include <iostream> #include <iomanip> #include <set> #include <sstream> #include <fstream> #include <chrono> #include <thread> #include <mutex> #include <regex> #include <iterator> #include <signal.h> #include <setjmp.h> #include <cstdlib> #include <unistd.h> #include "unittest.h" #ifdef __MINGW32__ #ifdef __MINGW64__ #include <debugapi.h> #else #include <winbase.h> #endif #elif __CYGWIN__ #include <w32api/debugapi.h> #endif using namespace CppUnitLite; std::map<std::string, UnitTest::BoundedTest> *UnitTest::tests = nullptr; long UnitTest::numSuccesses = 0L; long UnitTest::numFailures = 0L; long UnitTest::numErrors = 0L; std::string UnitTest::currentTest; bool UnitTest::expectToFail = false; bool UnitTest::diagnosticMessagesBeforeResults = true; std::vector<std::string> UnitTest::callLog; std::vector<std::string> UnitTest::failedTests; #ifdef __amd64__ #define breakDebugger { asm volatile ("int $3"); } #elif __i386__ #define breakDebugger { asm volatile ("int $3"); } #else #define breakDebugger { } #endif template <> std::string CppUnitLite::getStringRepr(std::string t) { return std::string("\"") + t + '"'; } template <> std::string CppUnitLite::getStringRepr(const char t[]) { return CppUnitLite::getStringRepr(std::string(t)); } template <> std::string CppUnitLite::getStringRepr(char t) { return std::string("'") + t + "'"; } template <> std::string CppUnitLite::getStringRepr(bool b) { return (b) ? "true" : "false"; } UnitTest::UnitTestFailure::UnitTestFailure ( const char* conditionStr, const char* fileName, int lineNumber) { if (!UnitTest::expectToFail) { std::ostringstream out; out << "Failed assertion " << conditionStr << " in " << currentTest << " at " << fileName << ", line " << lineNumber << "\n"; explanation = out.str(); } else { explanation = "(expected to fail)"; } } UnitTest::UnitTestFailure::UnitTestFailure ( const std::string& conditionStr, const char* fileName, int lineNumber) { if (!UnitTest::expectToFail) { std::ostringstream out; out << fileName << ":" << lineNumber << ": \t" << conditionStr << "\n"; explanation = out.str(); } else { explanation = "(expected to fail)"; } } const char* UnitTest::UnitTestFailure::what() const noexcept { return explanation.c_str(); } AssertionResult::AssertionResult (bool theResult, std::string pexplain, std::string fexplain) : result(theResult), passExplanation(pexplain), failExplanation(fexplain) {} #ifdef __MINGW32__ bool UnitTest::debuggerIsRunning() { return IsDebuggerPresent(); } #elif __CYGWIN__ bool UnitTest::debuggerIsRunning() { bool debuggerDetected = IsDebuggerPresent(); if (debuggerDetected) { UnitTest::msg("# Debugger detected -- test time limits will be ignored.\n"); } return debuggerDetected; } #else bool UnitTest::debuggerIsRunning() { using namespace std; static bool debuggerDetected = false; const string traceField = "tracerpid"; int pid = ::getpid(); string statusFile = string("/proc/") + std::to_string(pid) + "/status"; ifstream status (statusFile); if (status) { string line; getline (status, line); while (status) { transform(line.begin(), line.end(), line.begin(), ::tolower); if (line.find(traceField) != string::npos) { string::size_type k = line.find_first_of(" \t"); if (k != string::npos) { line = line.substr(k+1); istringstream lineIn (line); pid = -1; lineIn >> pid; if (pid > 0) { debuggerDetected = true; } } break; } getline (status, line); } } if (debuggerDetected) { UnitTest::msg("# Debugger detected -- test time limits will be ignored.\n"); } return debuggerDetected; } #endif void UnitTest::checkTest (AssertionResult assertionResult, std::string conditionStr, const char* fileName, int lineNumber) { if (!assertionResult.result) { if (debuggerIsRunning()) { std::string explanation = "Failed assertion: " + conditionStr + "\n" + assertionResult.failExplanation; breakDebugger; // A unit test has failed. // Examine explanation and your call stack for information explanation = explanation + " "; } if (assertionResult.failExplanation.size() > 0) { conditionStr += "\n\t" + assertionResult.failExplanation; } throw UnitTestFailure(conditionStr, fileName, lineNumber); } } //void UnitTest::checkTest (bool condition, const string& conditionStr, // const char* fileName, int lineNumber) //{ // checkTest(AssertionResult(condition), conditionStr.c_str(), fileName, lineNumber); //} // Print a simple summary report void UnitTest::report () { UnitTest::msgSummary(); } // Register a new UnitTest int UnitTest::registerUT (std::string functName, int timeLimit, TestFunction funct) { if (tests == nullptr) { tests = new std::map<std::string, UnitTest::BoundedTest>(); } if (tests->count(functName) > 0) { std::cerr << "**Error: duplicate unit test named " << functName << std::endl; } (*tests)[functName] = BoundedTest(timeLimit, funct); return 0; } jmp_buf unitTestSignalEnv; int unitTestLastSignal = 0; void unitTestSignalHandler(int sig) { unitTestLastSignal = sig; longjmp (unitTestSignalEnv, sig); } int UnitTest::runTestGuarded (unsigned testNumber, std::string testName, TestFunction u, std::string& testExplanation) { currentTest = testName; expectToFail = false; try { signal(SIGFPE, &unitTestSignalHandler); signal(SIGSEGV, &unitTestSignalHandler); if (setjmp(unitTestSignalEnv)) { // Runtime error was caught std::ostringstream out; out << "# runtime error " << unitTestLastSignal; if (!expectToFail) { testExplanation = UnitTest::msgFailed(testNumber, testName, out.str(), 0); return -1; } else { // OK (failed but was expected to fail)" UnitTest::msgXFailed(testNumber, testName, out.str(), 0); } } else { u(); if (!expectToFail) { UnitTest::msgPassed(testNumber, testName, 0); } else { // Failed (passed but was expected to fail UnitTest::msgXPassed(testNumber, testName, 0); return 0; } } return 1; } catch (UnitTestFailure& ex) { if (!expectToFail) { testExplanation = UnitTest::msgFailed(testNumber, testName, ex.what(), 0); return 0; } else { // OK (failed but was expected to fail)" UnitTest::msgXFailed(testNumber, testName, ex.what(), 0); return 1; } } catch (std::exception& e) { if (!expectToFail) { UnitTest::msgError(testNumber, testName, "Unexpected error in " + currentTest + ": " +e.what(), 0); testExplanation = ""; return -1; } else { // OK (exception but was expected to fail)" UnitTest::msgXFailed(testNumber, testName, "", 0); return 1; } } catch (...) { if (!expectToFail) { UnitTest::msgError(testNumber, testName, "Unexpected error in " + currentTest, 0); testExplanation = ""; return -1; } else { // OK (exception but was expected to fail)" UnitTest::msgXFailed(testNumber, testName, "", 0); return 1; } } } /** * Reverses the expectation for the current test. A test that fails or halts * with an error will be reported and counted as OK. If that test succeeds, * it will be reported and counted as an error. * * Must be called before any assertions. */ void UnitTest::expectedToFail() { expectToFail = true; } // Run a single unit test function with no timer. void UnitTest::runTestUntimed (unsigned testNumber, std::string testName, TestFunction u) { int testResult; // 1== passed, 0 == failed, -1 == erro std::string testExplanation; // No time-out supported if compiler does not have thread support. testResult = runTestGuarded (testNumber, testName, u, testExplanation); try { // Normal exit if (testResult == 1) { ++numSuccesses; } else if (testResult == 0) { ++numFailures; failedTests.push_back(testName); UnitTest::msg(testExplanation); } else if (testResult == -1) { ++numErrors; failedTests.push_back(testName); UnitTest::msg(testExplanation); } } catch (std::runtime_error& e) { ++numErrors; failedTests.push_back(testName); UnitTest::msg(std::string("# Test ") + currentTest + " failed due to " + e.what() + "\n"); } } #ifndef __MINGW32__ // Run a single unit test function. void UnitTest::runTest (unsigned testNumber, std::string testName, TestFunction u, long timeLimit) { if (timeLimit > 0L && !debuggerIsRunning()) { int testResult = -99; // 1== passed, 0 == failed, -1 == error std::string testExplanation; std::mutex m; std::chrono::duration<int,std::milli> limit (timeLimit); std::chrono::duration<int,std::milli> incr (100); std::chrono::duration<int,std::milli> elapsed (0); std::thread t([&m, &testNumber, &testName, &u, &testResult, &testExplanation](){ { int result = runTestGuarded (testNumber, testName, u, testExplanation); std::unique_lock<std::mutex> l2(m); testResult = result; } }); t.detach(); bool finished = false; do { { std::unique_lock<std::mutex> l(m); finished = (testResult >= -1 || elapsed >= limit); elapsed += incr; } std::this_thread::sleep_for( incr ); } while (!finished); if (testResult < -1) { ++numFailures; failedTests.push_back(testName); std::ostringstream out; out << "# Test " << testNumber << " - " << currentTest << " still running after " << timeLimit << " milliseconds - possible infinite loop?"; if (!expectToFail) { UnitTest::msg ( UnitTest::msgFailed(testNumber, testName, out.str(), timeLimit) ); } else { UnitTest::msgXFailed(testNumber, testName, out.str(), timeLimit); ++numSuccesses; --numFailures; } } // Normal exit else if (testResult == 1) { ++numSuccesses; } else if (testResult == 0) { ++numFailures; failedTests.push_back(testName); UnitTest::msg(testExplanation); } else if (testResult == -1) { ++numErrors; failedTests.push_back(testName); UnitTest::msg(testExplanation); } } else { runTestUntimed (testNumber, testName, u); } } #else // Run a single unit test function. void UnitTest::runTest (unsigned testNumber, std::string testName, TestFunction u, long int timeLimit) { runTestUntimed (testNumber, testName, u); } #endif // Run all units tests whose name contains testNames[i], // 0 <= i <= nTests // // Special case: If nTests == 0, runs all unit Tests. void UnitTest::runTests (int nTests, char** testNames, char* program) { std::set<std::string> testsToRun; // Check for GTest emulation for (int i = 0; i < nTests; ++i) { std::string arg = testNames[i]; } std::string badTestSpecifications = ""; for (int i = 0; i < nTests; ++i) { std::string testID = testNames[i]; bool found = false; for (const auto& utest: *tests) { if (utest.first.find(testID) != std::string::npos) { testsToRun.insert(utest.first); found = true; } } if (!found) { for (const auto& utest: *tests) { const std::string& utestName = utest.first; std::string reducedName (1, utestName[0]); for (unsigned j = 1; j < utest.first.size(); ++j) { if (utestName[j] >= 'A' && utestName[j] <= 'Z') { reducedName += utestName[j]; } } if (testID == reducedName) { testsToRun.insert(utest.first); found = true; } } } if (!found) { badTestSpecifications += "# Warning: No matching test found for input specification " + testID + "\n"; } } if (testsToRun.size() == 0) { for (const auto& utest: *tests) { testsToRun.insert(utest.first); } } // Emit TAP plan line UnitTest::msg ("1.." + std::to_string(testsToRun.size())); UnitTest::msg (badTestSpecifications); unsigned testNumber = 1; for (std::string testName: testsToRun) { BoundedTest test = (*tests)[testName]; runTest (testNumber, testName, test.unitTest, test.timeLimit); ++testNumber; } } /** * Clear the call log. */ void UnitTest::clearCallLog() { callLog.clear(); } /** * Position of oldest logged call. */ UnitTest::iterator UnitTest::begin() { return callLog.begin(); } /** * Position just after the most recently logged call. */ UnitTest::iterator UnitTest::end() { return callLog.end(); } /** * Log a call to a zero-parameter function. * * @param functionName name of the function */ void UnitTest::logCall (const std::string& functionName) { callLog.push_back (functionName); } void UnitTest::msgPassed (unsigned testNumber, std::string testName, unsigned timeMS) { using namespace std; cout << flush; cout << "ok " << testNumber << " - " << testName << endl; } void UnitTest::msgXPassed (unsigned testNumber, std::string testName, unsigned timeMS) { UnitTest::msg( UnitTest::msgFailed(testNumber, testName, std::string("Test ") + std::to_string(testNumber) + " - " + testName + " passed but was expected to fail.", timeMS) ); } std::string UnitTest::extractLocation (const std::string& msg) { using namespace std; string::size_type len = msg.size(); string::size_type pos1 = msg.find(".h:"); string::size_type pos2 = msg.find(".cpp:"); string::size_type pos = (pos1 < pos2) ? pos1 : pos2; string::size_type posEnd = pos + ((pos1 < pos2) ? 3 : 5); string::size_type stop = posEnd; while (stop < len && isdigit(msg[stop])) { ++stop; } if (stop == posEnd) return ""; string::size_type start = pos; char c = msg[start]; while (start <= pos && (isalnum(c) || c == '.' || c == '_' || c == '-' || c == '/' || c == '\\')) { --start; if (start <= pos) c = msg[start]; } if (start == pos) return ""; string result = msg.substr(start+1, stop-start-1); return result; } std::string UnitTest::msgFailed (unsigned testNumber, std::string testName, std::string diagnostics, unsigned timeMS) { using namespace std; string location = extractLocation(diagnostics); if (location.size() > 0) location += ": error: Failed test\n"; string diagnosticString = location + msgComment(diagnostics); string resultMsg = "not ok " + to_string(testNumber) + " - " + testName; if (diagnosticMessagesBeforeResults) return diagnosticString + ": \n" + resultMsg; else return resultMsg + "\n" + diagnosticString; } std::string UnitTest::msgComment (const std::string& commentary) { const static std::string commentPrefix = "# "; std::string result; std::string startOfLine = commentary.substr(0, commentPrefix.size()); if (startOfLine == commentPrefix) result = commentary; else result = commentPrefix + commentary; std::string::size_type pos = result.find('\n'); while (pos != std::string::npos) { if (result.size() >= pos+1+commentPrefix.size()) { startOfLine = result.substr(pos+1, commentPrefix.size()); if (startOfLine != commentPrefix) { result.insert(pos+1, commentPrefix); } } else { result.insert(pos+1, commentPrefix); } pos = result.find('\n', pos+1); } return result; } void UnitTest::msgXFailed (unsigned testNumber, std::string testName, std::string diagnostics, unsigned timeMS) { std::string diagnosticMsg = msgComment(std::string("Test ") + std::to_string(testNumber) + " failed but was expected to fail."); if (diagnosticMessagesBeforeResults) UnitTest::msg(diagnosticMsg); UnitTest::msgPassed(testNumber, testName, timeMS); if (!diagnosticMessagesBeforeResults) UnitTest::msg(diagnosticMsg); } void UnitTest::msgError (unsigned testNumber, std::string testName, std::string diagnostics, unsigned timeMS) { std::string diagnosticMsg = msgComment("ERROR - " + diagnostics); if (diagnosticMessagesBeforeResults) UnitTest::msg(diagnosticMsg); UnitTest::msg("not ok " + std::to_string(testNumber) + " - " + testName); if (!diagnosticMessagesBeforeResults) UnitTest::msg(diagnosticMsg); } void UnitTest::msgSummary () { using namespace std; cout << "# UnitTest: passed " << numSuccesses << " out of " << getNumTests() << " tests, for a success rate of " << std::showpoint << std::fixed << std::setprecision(1) << (100.0 * numSuccesses)/(float)getNumTests() << "%" << endl; } void UnitTest::msg (const std::string& detailMessage) { using std::cout; cout << detailMessage; if (detailMessage.size() > 0 && detailMessage[detailMessage.size()-1] != '\n') cout << "\n"; cout << std::flush; } StringContainsMatcher::StringContainsMatcher (const std::string& t): right(t) {} AssertionResult StringContainsMatcher::eval(const std::string& e) const { auto result = e.find(right); return AssertionResult( result != std::string::npos, "Found " + getStringRepr(right) + " starting in position " + getStringRepr(result) + " of " + getStringRepr(e), "Within " + getStringRepr(e) + ", cannot find " + getStringRepr(right)); } CppUnitLite::StringContainsMatcher contains(const char* t) { return CppUnitLite::StringContainsMatcher(std::string(t)); } CppUnitLite::StringContainsMatcher contains(const std::string& t) { return CppUnitLite::StringContainsMatcher(t); } StringEndsWithMatcher::StringEndsWithMatcher (const std::string& t): right(t) {} AssertionResult StringEndsWithMatcher::eval(const std::string& e) const { std::string eStr = getStringRepr(e); std::string rightStr = getStringRepr(right); bool result = (right.size() <= e.size()) && equal(right.begin(), right.end(), e.begin() + e.size() - right.size()); return AssertionResult(result, eStr + " ends with " + rightStr, eStr + " does not end with " + rightStr); } StringEndsWithMatcher endsWith(const char* t) { return StringEndsWithMatcher(std::string(t)); } StringEndsWithMatcher endsWith(const std::string& t) { return StringEndsWithMatcher(t); } StringBeginsWithMatcher::StringBeginsWithMatcher (const std::string& t) : right(t) {} AssertionResult StringBeginsWithMatcher::eval(const std::string& e) const { std::string eStr = getStringRepr(e); std::string rightStr = getStringRepr(right); bool result = (right.size() <= e.size()) && equal(right.begin(), right.end(), e.begin()); return AssertionResult(result, eStr + " begins with " + rightStr, eStr + " does not begin with " + rightStr ); } StringBeginsWithMatcher beginsWith(const char* t) { return CppUnitLite::StringBeginsWithMatcher(std::string(t)); } StringBeginsWithMatcher beginsWith(const std::string& t) { return StringBeginsWithMatcher(t); } StringBeginsWithMatcher startsWith(const char* t) { return StringBeginsWithMatcher(std::string(t)); } StringBeginsWithMatcher startsWith(const std::string& t) { return StringBeginsWithMatcher(t); } AssertionResult NullMatcher::eval(const void* p) const { return AssertionResult(p == nullptr, "", ""); } CppUnitLite::NullMatcher isNull() { return CppUnitLite::NullMatcher(); } AssertionResult NotNullMatcher::eval(const void* p) const { return AssertionResult(p != nullptr, "", ""); } CppUnitLite::NotNullMatcher isNotNull() { return CppUnitLite::NotNullMatcher(); } #ifndef NOMAIN int main(int argc, char** argv) { UnitTest::diagnosticMessagesBeforeResults = true; UnitTest::runTests(argc-1, argv+1, argv[0]); UnitTest::report(); return 0; } #endif

unittest.h

#ifndef UNITTEST_H #define UNITTEST_H #include <algorithm> #include <cstdarg> #include <iostream> #include <map> #include <sstream> #include <string> #include <vector> /** * This class helps support self-checking unit tests. * * This is a lightweight framework similar in spirit to JUnit (for Java), * Google Test, and Boost Test, but which can be added to a project by the * simple addition of the two files, unittest.h and unittest.cpp. It's not as * robust as those other frameworks - some runtime errors will shut the * test suite down with no final report. * * # Usage * * The framework consists of a two files, `unittest.h` and `unittest.cpp`, * that can be dropped into a C++ project directory, allowing the creation of * a unit test suite. * * A test suite consists of a collection of unit test functions, which can * be distributed among multiple .cpp files. (Typically one such file * would be devoted to testing each class in the project.) * * Each unit test function is introduced via `UnitTest` or, optionally, * `UnitTestTimed` (which alters the default timeout, measured in * milliseconds). * * Each unit test function can contain code to set up parameters, invoke * the function(s) being tested, and to evaluate the results of those * function calls via the use of assertions. Most assertions have the form: * * assertThat (value, matcher); * * although the following "old-fashioned" assertions are also supported. * * assertTrue (condition); * assertFalse (condition); * assertEqual (expression1, expression2); * assertNotEqual (expression1, expression2); * assertNull (expression); * assertNotNull (expression); * * The assertThat form, however, allows for a much wider and expressive range of * tests: * * ## Relational Matchers * * assertThat(x, isEqualTo(y)); * assertThat(x, is(y)); // same as isEqualTo * assertThat(x, isApproximately(y, delta)); // floating point only * assertThat(x, isNotEqualTo(y)); * assertThat(x, isNot(y)); // same as isNotEqualTo * * assertThat(x, isOneOf(w, y, z)); // Allows 1 or more options * * assertThat(x, isLessThan(y)); * assertThat(x, isGreaterThan(y)); * assertThat(x, isLessThanOrEqualTo(y)); * assertThat(x, isGreaterThanOrEqualTo(y)); * * ## String Matchers * * assertThat(str, contains("bc")); * assertThat(str, beginsWith(str2)); * assertThat(str, endsWith(str2)); * assertThat(str, startsWith(str2)); // same as beginsWith * * ## Pointer Matchers * * assertThat(p, isNull()); * assertThat(q, isNotNull()); * * ## Container Matchers * * Containers that define key_type (sets and maps, including unordered) * will be searched using their own fast find member function. Other * containers will be searched using a sequential search over begin()..end(). * * assertThat(v, contains(3)); * assertThat(v, hasItem(x)); // Same as contains * assertThat(v, hasKey(x)); // Same as contains * * assertThat(L, hasItems(3, 9)); // Allows one or more values * assertThat(L, hasKeys(3, 9)); // Same as hasItems * * range() and arrayOfLength() can be used to describe sequences that can be * used with any of the container objects. * * assertThat(range(v.begin(), v.end()), hasItem(z)); * assertThat(arrayOfLength(array, len), hasItem(z)); * * The common case of a sequence consisting of some container's entire contents * from begin() to end() can also be written as contentsOf(): * * assertThat(contentsOf(v), hasItem(z)); * * assertThat(x, isIn(v)); * assertThat(x, isInRange(v.begin(), v.end())); * * assertThat(aMap, hasEntry(5, 10)); // maps only * * A test for equality of corresponding elements between two sequences can be * made with matches(). * * assertThat(range(v.begin(), v.end()), matches(range(L.begin(), L.end()))); * * This can also be written as * * assertThat(contentsOf(v), matches(contentsOf(L))); * * ## Combining Matchers * * assertThat(x, !(matcher)); // Negate a matcher * * assertThat(x, allOf(isLessThan(42), isGreaterThan(10), is(23))); // All must be true * * assertThat(23, anyOf(isLessThan(42), isGreaterThan(10))); // One or more must be true * * # Example * * ## Writing A Unit Test * * A unit test of a simple "counter" class might look like: * * #include "unittest.h" * #include "myCounter.h" * * UnitTest (testConstructor) * { * MyClass x (23); * assertThat (x.getValue(), is(23)); * assertThat (x.isZero(), is(true)); * assertTrue (x.isZero()); // older style * } * * UnitTestTimed (testIncrement, 100L) // Limited to 100ms * { * MyClass x (23); * x.increment(); * assertThat (x.getValue(), is(24)); * x.increment(); * assertThat (x.getValue(), is(25)); * } * * UnitTestTimed (longTest, -1L) // No timer: will never time out * { * MyClass x (23); * for (int i = 0; i < 10000; ++i) * x.increment(); * assertThat (x.getValue(), is(10023)); * } * * * ## Running Your Tests * * The unittest.cpp includes a main() function to drive the tests. When * run with no command-line parameters, all unit test functions are run. * If command-line parameters are provided, they provide a list of test * function names to indicate which tests to run. Specifically, * any test function whose name contains the command-line parameter * will be run. * * For example, if the above tests are compiled to form an executable * named "`unittest`", then * * ./unittest testIncrement * * or * * ./unittest Incr * * * would run only the second test above, but any of the following * * ./unittest testConstructor testIncrement longTest * ./unittest est * ./unittest * * would run all three tests. */ /** * Time limit, in milliseconds, before a test function is killed * on suspicion of the code under test having gone into an infinite loop. * * Affects all subsequent UniTest(...) declarations, but is ignored by * any UnitTestTimed(...) declarations (because they supply their own * time limit, overriding the default). * * Note that a non-positive value for this time limit suppresses the timing * check entirely. This may be useful as a way of "stopping the clock" * when debugging failed tests. */ #define DEFAULT_UNIT_TEST_TIME_LIMIT 500L /** * Macros - actual tests will invoke one of these */ #define assertThat( obj, matcher ) CppUnitLite::UnitTest::checkTest \ ((matcher).eval(obj), \ std::string(#obj) + " " + std::string(#matcher), __FILE__, __LINE__) #define assertTrue(cond) CppUnitLite::UnitTest::checkTest\ (CppUnitLite::AssertionResult(cond,"",""), #cond, __FILE__, __LINE__) #define assertTruex(cond) CppUnitLite::UnitTest::checkTest\ (cond, #cond, __FILE__, __LINE__) #define assertFalse(cond) CppUnitLite::UnitTest::checkTest\ (CppUnitLite::AssertionResult(!(cond),"",""), std::string("!(") + #cond + ")", __FILE__, __LINE__) #define assertFalsex(cond) CppUnitLite::UnitTest::checkTest\ (!(cond), std::string("!(") + #cond + ")", __FILE__, __LINE__) #define assertEqual( x, y ) assertThat(x, isEqualTo(y)) #define assertEqualx( x, y ) CppUnitLite::UnitTest::checkTest ((x)==(y),\ "assertEqual(" #x "," #y ")", \ __FILE__, __LINE__) #define assertNotEqual( x , y ) assertThat(x, isNotEqualTo(y)) #define assertNotEqualx( x , y ) assertFalse ((x)==(y)) #define assertNull(x) assertTrue ((x)==nullptr) #define assertNotNull(x) assertTrue ((x)!=nullptr) #define succeed CppUnitLite::UnitTest::checkTest (\ CppUnitLite::AssertionResult(true,"",""),\ "succeed", __FILE__, __LINE__) #define fail CppUnitLite::UnitTest::checkTest (\ CppUnitLite::AssertionResult(false,"",""), "fail",\ __FILE__, __LINE__) /** * Test registration */ #define UnitTest(functName) UnitTestTimed(functName, DEFAULT_UNIT_TEST_TIME_LIMIT) #define UnitTestTimed(functName, limit) void functName(); int functName ## dummy = \ CppUnitLite::UnitTest::registerUT(#functName, limit, &functName); void functName() namespace CppUnitLite { template <typename T> struct has_begin { private: template <typename U, class = decltype( std::declval<U&>().begin() ) > static std::true_type try_begin(U&&); static std::false_type try_begin(...); public: using type = decltype( try_begin( std::declval<T>())); static constexpr bool value = type(); }; template <typename T> struct can_be_written { private: template <typename U, class = decltype( std::declval<std::ostringstream&>() << std::declval<U&>()) > static std::true_type try_output(U&&); static std::false_type try_output(...); public: using type = decltype( try_output( std::declval<T>())); static constexpr bool value = type(); }; template <typename T, typename U> std::string getStringRepr(const std::pair<T,U>& t); template <typename T> std::string getStringRepr(T t); template<typename T, typename std::enable_if<can_be_written<T>::value, int>::type = 0> std::string getStringRepr2(T const& t) { std::ostringstream out; out << t; return out.str(); } template<typename T, typename std::enable_if<!can_be_written<T>::value && has_begin<T>::value, int>::type = 0> std::string getStringRepr2(T t) { static const unsigned ContainerDisplayLimit = 10; auto n = std::distance(t.begin(), t.end()); auto pos = t.begin(); unsigned count = 0; std::string result = "["; while (pos != t.end() && n > 0) { result += getStringRepr(*pos); if (n > 1) result += ", "; --n; ++pos; ++count; if (count >= ContainerDisplayLimit && n > 0) { result += "..."; break; } } if (n > 0) { result += "... (" + getStringRepr(n) + " additional elements) ..."; } result += "]"; return result; } template<typename T, typename std::enable_if<!can_be_written<T>::value && !has_begin<T>::value, int>::type = 0> std::string getStringRepr2(T t) { return "???"; } template <typename T, typename U> std::string getStringRepr(const std::pair<T,U>& t) { return std::string("<") + getStringRepr(t.first) + ", " + getStringRepr(t.second) + ">"; } template <typename Tuple, std::size_t size, std::size_t remaining> struct getTupleRepr { static std::string getContentRepr(Tuple t) { std::string separator = (remaining > 1)? std::string(", ") : std::string(); return getStringRepr(std::get<size-remaining>(t)) + separator + getTupleRepr<Tuple,size, remaining-1>::getContentRepr(t); } }; template <typename Tuple, std::size_t size> struct getTupleRepr<Tuple, size, 0> { static std::string getContentRepr(Tuple t) { return ""; } }; template <typename Tuple> std::string getTupleStringRepr(Tuple t) { return std::string("<") + getTupleRepr<Tuple, std::tuple_size<Tuple>::value, std::tuple_size<Tuple>::value>::getContentRepr(t) + ">"; } template <typename... T> std::string getStringRepr(const std::tuple<T...>& t) { return getTupleStringRepr(t); } template <typename T> std::string getStringRepr(T t) { return getStringRepr2(t); } template <> std::string getStringRepr(std::string t); template <> std::string getStringRepr(const char t[]); template <> std::string getStringRepr(char t); template <> std::string getStringRepr(bool b); class AssertionResult { public: bool result; ///> True iff assertion passed std::string passExplanation; ///> Optional explanation for passing; std::string failExplanation; ///> Optional explanation for failure; AssertionResult (bool theResult, std::string passExplain, std::string failExplain); }; /** * Main support class for unit test execution. */ class UnitTest { private: static long numSuccesses; static long numFailures; static long numErrors; static std::string currentTest; static std::vector<std::string> failedTests; static std::vector<std::string> callLog; public: /** * Change to false to print diagnostics after the ok/not ok result. */ static bool diagnosticMessagesBeforeResults; typedef void (*TestFunction)(); /** * Exception thrown to indicate a failed assertion. */ class UnitTestFailure: public std::exception { std::string explanation; public: UnitTestFailure (const char* conditionStr, const char* fileName, int lineNumber); UnitTestFailure (const std::string& conditionStr, const char* fileName, int lineNumber); virtual const char* what() const noexcept; }; /** * The main test function - normally called via one of the macros * declared following this class. Does nothing if the assertion * was passed, but throws an exception if the assertion was failed. * * @param result the assertion condition, "" if passed, otherwise * contains an explanation for the failure. * @param conditionStr a string rendering of the assertion condition. * @param fileName Source code file in which the assertion occurs, * @param lineNumber Source code line number at which the assertion occurs, * @throws UnitTestFailure if condition is false. */ static void checkTest (AssertionResult result, std::string conditionStr, const char* fileName, int lineNumber); /** * The main test function - normally called via one of the macros * declared following this class. Does nothing if the assertion * was passed, but throws an exception if the assertion was failed. * * @param condition the assertion condition, true iff passed. * @param conditionStr a string rendering of the assertion condition. * @param fileName Source code file in which the assertion occurs, * @param lineNumber Source code line number at which the assertion occurs, * @throws UnitTestFailure if condition is false. */ // static void checkTest (bool condition, const std::string& conditionStr, // const char* fileName, int lineNumber); // Summary info about tests conducted so far /** * How many tests have been run? * * @return number of tests. */ static long getNumTests() {return numSuccesses + numFailures;} /** * How many tests were terminated by a failed assertion? * * @return number of failed tests. */ static long getNumFailures() {return numFailures;} /** * How many tests were terminated by an unexpected exception, * run-time error, or time-out? * * @return number of uncompleted tests. */ static long getNumErrors() {return numErrors;} /** * How many tests terminated successfully? * * @return number of passed tests. */ static long getNumSuccesses() {return numSuccesses;} /** * Run all units tests whose name contains testNames[i], * for all i in 0..nTests-1. * * Special case: If nTests == 0, runs all unit Tests. * * @param nTests number of test name substrings * @param testNames array of possible substrings of test names * @param programName path to program executable */ static void runTests (int nTests, char** testNames, char* programName); /** * Print a simple summary report. Includes number of tests passed, * failed, and erroneously termnated. * */ static void report (); /** * Register a new UnitTest, making it eligible for running. * * @param functName name of the test function. * @param timeLimit time limit in milliseconds * @param funct the unit test function */ static int registerUT (std::string functName, int timeLimit, TestFunction funct); /** * Reverses the expectation for the current test. A test that fails or halts * with an error will be reported and counted as OK. If that test succeeds, * it will be reported and counted as an error. * * Must be called before any assertions. */ static void expectedToFail(); /* ******************************************************** * The call log is intended as an aid in writing stubs. * ********************************************************/ typedef std::vector<std::string>::const_iterator const_iterator; typedef std::vector<std::string>::const_iterator iterator; /** * Clear the call log. */ static void clearCallLog(); /** * Position of oldest logged call. */ static iterator begin(); /** * Position just after the most recently logged call. */ static iterator end(); /** * Log a call to a zero-parameter function. * * @param functionName name of the function */ static void logCall (const std::string& functionName); /** * Log a call to a function with one parameter. * * Parameter types must support operator<< * * @param functionName name of the function * @param arg1 a parameter to the function call */ template <typename T1> static void logCall (const std::string& functionName, const T1& arg1) { logCall (functionName + "\t" + getStringRepr(arg1)); } /** * Log a call to a function with two parameters. * * Parameter types must support operator<< * * @param functionName name of the function * @param arg1 a parameter to the function call * @param arg2 a parameter to the function call */ template <typename T1, typename T2> static void logCall (const std::string& functionName, const T1& arg1, const T2& arg2) { logCall (functionName + "\t" + getStringRepr(arg1) + "\t" + getStringRepr(arg2)); } /** * Log a call to a function with three parameters. * * Parameter types must support operator<< * * @param functionName name of the function * @param arg1 a parameter to the function call * @param arg2 a parameter to the function call * @param arg3 a parameter to the function call */ template <typename T1, typename T2, typename T3> static void logCall (const std::string& functionName, const T1& arg1, const T2& arg2, const T3& arg3) { logCall (functionName + "\t" + getStringRepr(arg1) + "\t" + getStringRepr(arg2) + "\t" + getStringRepr(arg3)); } /** * Log a call to a function with four parameters. * * Parameter types must support operator<< * * @param functionName name of the function * @param arg1 a parameter to the function call * @param arg2 a parameter to the function call * @param arg3 a parameter to the function call * @param arg4 a parameter to the function call */ template <typename T1, typename T2, typename T3, typename T4> static void logCall (const std::string& functionName, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4) { logCall (functionName + "\t" + getStringRepr(arg1) + "\t" + getStringRepr(arg2) + "\t" + getStringRepr(arg3) + "\t" + getStringRepr(arg4)); } // These should be private, but I wanted to unit test them. static std::string msgComment (const std::string& commentary); static std::string msgFailed (unsigned testNumber, std::string testName, std::string diagnostics, unsigned timeMS); static bool debuggerIsRunning(); private: /** * Internal container for test functions and their associated time limits. */ struct BoundedTest { int timeLimit; TestFunction unitTest; BoundedTest(): timeLimit(0), unitTest(0) {} BoundedTest (int time, TestFunction f): timeLimit(time), unitTest(f) {} }; static std::map<std::string, BoundedTest> *tests; static bool expectToFail; static void runTest(unsigned testNumber, std::string testName, TestFunction u, long timeLimitInMS); static void runTestUntimed(unsigned testNumber, std::string testName, TestFunction u); static int runTestGuarded(unsigned testNumber, std::string testName, TestFunction u, std::string& msg); static std::string extractLocation (const std::string& msg); static void msgRunning (unsigned testNumber, std::string testName); static void msgPassed (unsigned testNumber, std::string testName, unsigned timeMS); static void msgXPassed (unsigned testNumber, std::string testName, unsigned timeMS); //static std::string msgFailed (unsigned testNumber, std::string testName, unsigned timeMS); //static std::string msgComment (const std::string& commentary); static void msgXFailed (unsigned testNumber, std::string testName, std::string diagnostics, unsigned timeMS); static void msgError (unsigned testNumber, std::string testName, std::string diagnostics, unsigned timeMS); static void msgSummary (); static void msg (const std::string& detailMessage); }; inline void expectedToFail() { UnitTest::expectedToFail(); } // Compile-time test for associative containers inline constexpr auto container_has_keytype_impl(...) -> std::false_type { return std::false_type{}; } template <typename C, typename = typename C::key_type> constexpr auto container_has_keytype_impl(C const*) -> std::true_type { return std::true_type{}; } template <typename C> constexpr auto container_has_keytype(C const& c) -> decltype(container_has_keytype_impl(&c)) { return container_has_keytype_impl(&c); } template <typename Container, typename Element> long find_in_container_impl (const Container& c, const Element& e, std::false_type) { long ctr = 0L; for (auto it = c.begin(); it != c.end(); ++it) { if (e == *it) return ctr; ++ctr; } return -1L; } template <typename Container, typename Element> long find_in_container_impl (const Container& c, const Element& e, std::true_type) { auto pos = c.find(e); if (c.find(e) != c.end()) return (long)distance(c.begin(), pos); else return -1L; } template <typename Container, typename Element> long find_in_container (const Container& c, const Element& e) { return find_in_container_impl (c, e, container_has_keytype(c)); } //// Relational Matchers template <typename T> class EqualToMatcher { const T right; public: EqualToMatcher (const T& t) : right(t) {} /** * Evaluate the condition denoted by this matcher. */ AssertionResult eval(const T& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightStr = CppUnitLite::getStringRepr(right); std::string explain = "Expected: " + rightStr + "\n\tObserved: " + leftStr; return AssertionResult(left == right, "Both values were: " + getStringRepr(left), explain ); } }; template <typename T, typename U> class ApproximatelyEqualToMatcher { const T right; const U delta; public: ApproximatelyEqualToMatcher (const T& t, const U& d): right(t), delta(d) {} AssertionResult eval(const T& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightPlusStr = CppUnitLite::getStringRepr(right+delta); std::string rightMinusStr = CppUnitLite::getStringRepr(right-delta); std::string passExplain = leftStr + " is between " + rightMinusStr + " and " + rightPlusStr; if (left < right - delta || left > right + delta) return AssertionResult(false, passExplain, leftStr + " is outside the range " + getStringRepr(right-delta) + " .. " + getStringRepr(right+delta)); else return AssertionResult(true, passExplain, ""); } }; template <typename T> class NotEqualToMatcher { const T right; public: NotEqualToMatcher (const T& t): right(t) {} AssertionResult eval(const T& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightStr = CppUnitLite::getStringRepr(right); std::string explain = "Expected: " + rightStr + "\n\tObserved: " + leftStr; return AssertionResult(!(left == right), explain, "Both values were: " + getStringRepr(left) ); } }; template <typename T> class LessThanMatcher { const T right; public: LessThanMatcher (const T& t): right(t) {} AssertionResult eval(const T& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightStr = CppUnitLite::getStringRepr(right); return AssertionResult(left < right, leftStr + " is less than " + rightStr, leftStr + " is not less than " + rightStr ); } }; template <typename T> class GreaterThanMatcher { const T right; public: GreaterThanMatcher (const T& t): right(t) {} AssertionResult eval(const T& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightStr = CppUnitLite::getStringRepr(right); return AssertionResult(right < left, leftStr + " is greater than " + rightStr, leftStr + " is not greater than " + rightStr ); } }; template <typename T> class LessThanOrEqualToMatcher { const T right; public: LessThanOrEqualToMatcher (const T& t): right(t) {} AssertionResult eval(const T& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightStr = CppUnitLite::getStringRepr(right); return AssertionResult(!(right < left), leftStr + " is less than or equal to " + rightStr, leftStr + " is greater than " + rightStr ); } }; template <typename T> class GreaterThanOrEqualToMatcher { const T right; public: GreaterThanOrEqualToMatcher (const T& t): right(t) {} AssertionResult eval(const T& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightStr = CppUnitLite::getStringRepr(right); return AssertionResult(!(left < right), leftStr + " is greater than or equal to " + rightStr, leftStr + " is less than " + rightStr ); } }; //// String Matchers class StringContainsMatcher { const std::string right; public: StringContainsMatcher (const std::string& t); AssertionResult eval(const std::string& e) const; }; class StringEndsWithMatcher { const std::string right; public: StringEndsWithMatcher (const std::string& t); AssertionResult eval(const std::string& e) const; }; class StringBeginsWithMatcher { const std::string right; public: StringBeginsWithMatcher (const std::string& t); AssertionResult eval(const std::string& e) const; }; // Pointer Matchers class NullMatcher { public: AssertionResult eval(const void* p) const; }; class NotNullMatcher { public: AssertionResult eval(const void* p) const; }; //// Container Matchers template <typename Element> class ContainsMatcher { Element right; public: ContainsMatcher (Element e) : right(e) {} template <typename Container> AssertionResult eval(const Container& c) const { std::string containerStr = CppUnitLite::getStringRepr(c); std::string rightStr = CppUnitLite::getStringRepr(right); long pos = find_in_container(c, right); return AssertionResult(pos >= 0, "Found " + rightStr + " in position " + getStringRepr(pos) + " of " + containerStr, "Could not find " + rightStr + " in " + containerStr ); } }; template <typename Key, typename Data> class HasEntryMatcher { Key key; Data data; public: HasEntryMatcher (const Key& k, const Data& d) : key(k), data(d) {} template <typename Container> AssertionResult eval(const Container& c) const { std::string containerStr = CppUnitLite::getStringRepr(c); std::string keyStr = CppUnitLite::getStringRepr(key); auto pos = c.find(key); if (pos != c.end()) { return AssertionResult(data == pos->second, "Found " + getStringRepr(*pos) + " in " + containerStr, "Could not find <" + keyStr + ", " + getStringRepr(data) + "> in " + containerStr ); } else return AssertionResult(pos != c.end(), "Found " + getStringRepr(*pos) + " in " + containerStr, "Could not find " + keyStr + " in " + containerStr ); } }; template <typename Iterator> class IteratorRange { Iterator start; Iterator stop; public: typedef Iterator iterator; typedef Iterator const_iterator; IteratorRange (Iterator b, Iterator e): start(b), stop(e) {} Iterator begin() const { return start; } Iterator end() const { return stop; } }; template <typename... Ts> class HasItemsMatcher { using Element = typename std::common_type<Ts...>::type; typename std::vector<Element> right; public: HasItemsMatcher (Ts... ts): right({ts...}) { } template <typename Container> AssertionResult eval (const Container& c) const { std::string cStr = getStringRepr(c); std::string foundAll = "Found all of " + getStringRepr(right) + " in " + cStr; for (const Element& e: right) { if (find_in_container(c, e) < 0L) { std::string explain = "Did not find " + getStringRepr(e) + " in " + cStr; return AssertionResult(false, foundAll, explain); } } return AssertionResult(true, foundAll, foundAll); } }; template <typename Iterator1> class MatchesMatcher { const IteratorRange<Iterator1> range1; public: MatchesMatcher (IteratorRange<Iterator1> r1) : range1(r1) {} template <typename Iterator2> AssertionResult eval(IteratorRange<Iterator2> range2) const { auto d1 = std::distance(range1.begin(), range1.end()); auto d2 = std::distance(range2.begin(), range2.end()); if (d1 == d2) { Iterator1 pos1 = range1.begin(); Iterator2 pos2 = range2.begin(); while (pos1 != range1.end()) { if (!(*pos1 == *pos2)) { return AssertionResult (false, "", "In position " + getStringRepr(std::distance(range1.begin(), pos1)) + ", " + getStringRepr(*pos1) + " != " + getStringRepr(*pos2) ); } ++pos1; ++pos2; } return AssertionResult (true, "All corresponding elements were equal.",""); } else return AssertionResult(false, "", "Ranges are of different length (" + getStringRepr(d1) + " and " + getStringRepr(d2) + ")"); } }; template <typename Container> class IsInMatcher { const Container& container; public: IsInMatcher (const Container& c) : container(c) {} template <typename Element> AssertionResult eval(const Element& e) const { std::string cStr = getStringRepr(container); std::string eStr = getStringRepr(e); long pos = find_in_container(container, e); return AssertionResult(pos >= 0L, "Found " + eStr + " in postion " + getStringRepr(pos) + " of " + cStr, "Could not find " + eStr + " in " + cStr); } }; template <typename Iterator> class IsInRangeMatcher { Iterator start; Iterator stop; public: IsInRangeMatcher (Iterator b, Iterator e) : start(b), stop(e) {} template <typename Element> AssertionResult eval(const Element& e) const { std::string eStr = getStringRepr(e); auto pos = find(start, stop, e); return AssertionResult (pos != stop, "Found " + eStr + " in range, " + getStringRepr(distance(start,pos)) + " steps from the start", "Could not find " + eStr + " in the range"); } }; //// Boolean Matchers template <typename T> class NotMatcher { T right; public: NotMatcher (const T& t): right(t) {} template <typename U> AssertionResult eval(const U& u) const { AssertionResult r = right.eval(u); return AssertionResult(!(r.result), r.failExplanation, r.passExplanation); } }; template <typename... Rest> class AllOfMatcher { public: AllOfMatcher (Rest... matchers) { } template <typename T> AssertionResult eval (const T& t) const { return AssertionResult(true, "", ""); } }; template <typename Matcher, typename... Rest> class AllOfMatcher<Matcher, Rest...> { Matcher matcher; AllOfMatcher<Rest...> rest; public: AllOfMatcher (Matcher m, Rest... matchers): matcher(m), rest(matchers...) { } template <typename T> AssertionResult eval (const T& t) const { AssertionResult result1 = matcher.eval(t); if (result1.result) return rest.eval(t); else return AssertionResult(false, "All of the conditions were true", result1.failExplanation); } }; template <typename... Rest> class AnyOfMatcher { public: AnyOfMatcher (Rest... matchers) { } template <typename T> AssertionResult eval (const T& t) const { return AssertionResult(false, "", ""); } }; template <typename Matcher, typename... Rest> class AnyOfMatcher<Matcher, Rest...> { Matcher matcher; AnyOfMatcher<Rest...> rest; public: AnyOfMatcher (Matcher m, Rest... matchers): matcher(m), rest(matchers...) { } template <typename T> AssertionResult eval (const T& t) const { AssertionResult result1 = matcher.eval(t); if (!result1.result) return rest.eval(t); else return AssertionResult(true, result1.passExplanation, "None of the conditions were true"); } }; template <typename... T> class OneOfMatcher { using Element = typename std::common_type<T...>::type; typename std::vector<Element> right; public: OneOfMatcher (T... t): right({std::forward<T>(t)...}) { } AssertionResult eval (const Element& left) const { std::string leftStr = CppUnitLite::getStringRepr(left); std::string rightStr = CppUnitLite::getStringRepr(right); std::string foundMessage = "Found " + leftStr + " in " + rightStr; std::string notFoundMessage = "Could not find " + leftStr + " in " + rightStr; for (const Element& e: right) { if (left == e) return AssertionResult(true, foundMessage, notFoundMessage); } return AssertionResult(false, foundMessage, notFoundMessage); } }; } //// Matchers /// Relational Matchers inline CppUnitLite::EqualToMatcher<std::string> isEqualTo(const char* t) { return CppUnitLite::EqualToMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::EqualToMatcher<T> isEqualTo(const T& t) { return CppUnitLite::EqualToMatcher<T>(t); } inline CppUnitLite::EqualToMatcher<std::string> is(const char* t) { return CppUnitLite::EqualToMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::EqualToMatcher<T> is(const T& t) { return CppUnitLite::EqualToMatcher<T>(t); } template <typename T, typename U> CppUnitLite::ApproximatelyEqualToMatcher<T,U> isApproximately(const T& t, const U& delta) { return CppUnitLite::ApproximatelyEqualToMatcher<T,U>(t, delta); } inline CppUnitLite::NotEqualToMatcher<std::string> isNotEqualTo(const char* t) { return CppUnitLite::NotEqualToMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::NotEqualToMatcher<T> isNotEqualTo(const T& t) { return CppUnitLite::NotEqualToMatcher<T>(t); } inline CppUnitLite::NotEqualToMatcher<std::string> isNot(const char* t) { return CppUnitLite::NotEqualToMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::NotEqualToMatcher<T> isNot(const T& t) { return CppUnitLite::NotEqualToMatcher<T>(t); } inline CppUnitLite::LessThanMatcher<std::string> \ isLessThan(const char* t) { return CppUnitLite::LessThanMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::LessThanMatcher<T> isLessThan(const T& t) { return CppUnitLite::LessThanMatcher<T>(t); } inline CppUnitLite::GreaterThanMatcher<std::string> isGreaterThan(const char* t) { return CppUnitLite::GreaterThanMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::GreaterThanMatcher<T> isGreaterThan(const T& t) { return CppUnitLite::GreaterThanMatcher<T>(t); } inline CppUnitLite::LessThanOrEqualToMatcher<std::string> isLessThanOrEqualTo(const char* t) { return CppUnitLite::LessThanOrEqualToMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::LessThanOrEqualToMatcher<T> isLessThanOrEqualTo(const T& t) { return CppUnitLite::LessThanOrEqualToMatcher<T>(t); } inline CppUnitLite::GreaterThanOrEqualToMatcher<std::string> isGreaterThanOrEqualTo(const char* t) { return CppUnitLite::GreaterThanOrEqualToMatcher<std::string>(std::string(t)); } template <typename T> CppUnitLite::GreaterThanOrEqualToMatcher<T> isGreaterThanOrEqualTo(const T& t) { return CppUnitLite::GreaterThanOrEqualToMatcher<T>(t); } /// String matchers CppUnitLite::StringContainsMatcher contains(const char* t); CppUnitLite::StringContainsMatcher contains(const std::string& t); CppUnitLite::StringEndsWithMatcher endsWith(const char* t); CppUnitLite::StringEndsWithMatcher endsWith(const std::string& t); CppUnitLite::StringBeginsWithMatcher beginsWith(const char* t); CppUnitLite::StringBeginsWithMatcher beginsWith(const std::string& t); CppUnitLite::StringBeginsWithMatcher startsWith(const char* t); CppUnitLite::StringBeginsWithMatcher startsWith(const std::string& t); /// Pointer matchers CppUnitLite::NullMatcher isNull(); CppUnitLite::NotNullMatcher isNotNull(); /// Container matchers template <typename T> CppUnitLite::ContainsMatcher<T> hasItem(const T& e) { return CppUnitLite::ContainsMatcher<T>(e); } template <typename T> CppUnitLite::ContainsMatcher<T> contains(const T& e) { return CppUnitLite::ContainsMatcher<T>(e); } template <typename T> CppUnitLite::ContainsMatcher<T> hasKey(const T& e) { return CppUnitLite::ContainsMatcher<T>(e); } template <typename Key, typename Data> CppUnitLite::HasEntryMatcher<Key, Data> hasEntry(const Key& k, const Data& d) { return CppUnitLite::HasEntryMatcher<Key, Data>(k, d); } template <typename Element> CppUnitLite::IteratorRange<const Element*> arrayOfLength (const Element* start, int n) { return CppUnitLite::IteratorRange<const Element*>(start, start+n); } template <typename Iterator> CppUnitLite::IteratorRange<Iterator> range (Iterator start, Iterator stop) { return CppUnitLite::IteratorRange<Iterator>(start, stop); } template <typename T> CppUnitLite::IteratorRange<typename T::const_iterator> contentsOf (const T& container) { return CppUnitLite::IteratorRange<typename T::const_iterator>(container.begin(), container.end()); } template <typename... Ts> CppUnitLite::HasItemsMatcher<Ts...> hasItems (Ts... t) { return CppUnitLite::HasItemsMatcher<Ts...>(t...); } template <typename T> CppUnitLite::MatchesMatcher<const T*> matches (CppUnitLite::IteratorRange<const T*> arrayrange) { return CppUnitLite::MatchesMatcher<const T*>(arrayrange); } template <typename Iterator> CppUnitLite::MatchesMatcher<Iterator> matches (CppUnitLite::IteratorRange<Iterator> range) { return CppUnitLite::MatchesMatcher<Iterator>(range); } /// Associative container (set & map) matchers template <typename... Ts> CppUnitLite::HasItemsMatcher<Ts...> hasKeys (Ts... t) { return CppUnitLite::HasItemsMatcher<Ts...>(t...); } template <typename Container> CppUnitLite::IsInMatcher<Container> isIn(const Container& c) { return CppUnitLite::IsInMatcher<Container>(c); } template <typename Iterator> CppUnitLite::IsInRangeMatcher<Iterator> isInRange(Iterator b, Iterator e) { return CppUnitLite::IsInRangeMatcher<Iterator>(b, e); } /// Combining matchers template <typename T> CppUnitLite::NotMatcher<T> operator!(const T& t) { return CppUnitLite::NotMatcher<T>(t); } template <typename... Ts> CppUnitLite::AllOfMatcher<Ts...> allOf(Ts... ts) { return CppUnitLite::AllOfMatcher<Ts...>(ts...); } template <typename... Ts> CppUnitLite::AnyOfMatcher<Ts...> anyOf(Ts... ts) { return CppUnitLite::AnyOfMatcher<Ts...>(ts...); } template <typename... T> CppUnitLite::OneOfMatcher<T...> isOneOf (T... t) { return CppUnitLite::OneOfMatcher<T...>(t...); } #endif

xmlcheck.cpp

#include <algorithm> #include <fstream> #include <stack> #include <list> #include "balancer.h" #include "FlexLexer.h" #include "scanner.h" using namespace std; std::string lowercase(std::string s) { using namespace std; for (string::size_type i = 0; i < s.size(); ++i) if ((s[i] >= 'A') && (s[i] <= 'Z')) s[i] = s[i] + 'a' - 'A'; return s; } string location; bool checkStatus(const Balancer& bal, const string& lastTag) { if (bal.status() < 0) { cout << "Mismatched tags detected at tag " << lastTag << endl; return true; } else return false; } void collectFromFile (const string& fileName) { ifstream inFile (fileName); Balancer balancer; if (!inFile) { cout << "Could not open '" << fileName << "'" << endl; return; } yyFlexLexer scanner (&inFile); cout << "Checking " << fileName << endl; location = fileName; bool done = false; while (!done) { int tokenKind = scanner.yylex(); // cerr << "lex: " << tokenKind << " '" << lexeme << "'" << endl; switch (tokenKind) { case WORD: { break; } case NAME: case LINK: case TAG: { // A tag has been detected. //cerr << "Encountered tag " << lexeme << endl; balancer.tag(lexeme); break; } case ENDOFFILE: { done = true; } } if (done) break; done = checkStatus(balancer, lexeme); } if (balancer.status() == 0) { cout << "Unclosed tags detected at end of file " << fileName << endl; } else if (balancer.status() == 1) cout << "OK" << endl; } int main (int argc, char** argv) { if (argc != 2) { cerr << "usage:\n collector htmlfilename" << endl; return 1; } string fileName = argv[1]; collectFromFile (fileName); return 0; }