/* -*- Mode: c -*- */
/*
 * Copyright (c) 2002, The EROS Group, LLC and Johns Hopkins
 * University. All rights reserved.
 * 
 * This software was developed to support the EROS secure operating
 * system project (http://www.eros-os.org). The latest version of
 * the OpenCM software can be found at http://www.opencm.org.
 * 
 * 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.
 * 
 * 3. Neither the name of the The EROS Group, LLC nor the name of
 *    Johns Hopkins 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 BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

%{
#include <string.h>
#include <stdarg.h>
#include <opencm.h>
#include "browseconfig.h"
  
#define YY_NO_UNPUT

#define YY_MALLOC_DECL
#define malloc(x) GC_MALLOC_ATOMIC(x)
#define free(x) 
extern void exit(int);

/* Suppress compiler complaint about yy_flex_realloc: */
static void *yy_flex_realloc( void *, yy_size_t ) __attribute__((unused));

static const Buffer *buffer;
 static ocmoff_t position;

static int showc_lex( SDR_stream *strm );
#define YY_DECL int showc_lex( SDR_stream *strm )

#define ECHO do_html_output(strm, yytext, yyleng)

static void print_func_def(SDR_stream *strm, const char *name);


int show_c(SDR_stream *strm, const Buffer *input);

int show_c(SDR_stream *strm, const Buffer *input)
{
  int result;

  buffer = input;
  position = 0;

  stream_printf(strm, "<br><tt>\n");
  html_output_init();

  result = showc_lex(strm);

  stream_printf(strm, "</tt>\n");

  return result;
}

#define YY_INPUT(buf,result,max_size) \
   { \
     if (position == buffer_length(buffer)) \
       result = YY_NULL; \
     else { \
       buf[0] = buffer_getc(buffer, position++); \
       result = 1; \
     } \
   }

#ifndef output
#define output(x) stream_putc(strm, yyout);
#endif

#undef yyunput
%}

KWD ((if)|(else)|(for)|(while)|(do)|(return)|(void))
TYPE ((struct)|(enum)|(class)|(typedef)|(public)|(private)|(protected))
IDENT [a-zA-Z_][a-zA-Z0-9_]*
     
%x COMMENT CPLUS_COMMENT STRING TYPENAME PREPROC PRE2 INCFILE
%%
\/\*  { html_begin(strm,begin_comment); ECHO; BEGIN(COMMENT); }
\/\/  { html_begin(strm,begin_comment); ECHO; BEGIN(CPLUS_COMMENT); }
\"    { ECHO; html_begin(strm,begin_string); BEGIN(STRING); }
{KWD} { html_begin(strm,begin_kwd); ECHO; html_end(strm,end_kwd); }
^{TYPE} { html_begin(strm,begin_tkwd); ECHO; html_end(strm,end_tkwd); BEGIN(TYPENAME); }
{TYPE} { html_begin(strm,begin_tkwd); ECHO; html_end(strm,end_tkwd); BEGIN(TYPENAME); }
^({IDENT}::)*{IDENT}/[ \t]*\( {
  print_func_def(strm, yytext);
}
^{IDENT}::operator[ \t]+((new)|(delete))/[ \t]*\( {
  print_func_def(strm, yytext);
}

{IDENT} { ECHO; }

^#     { html_begin(strm,begin_preproc); ECHO; BEGIN(PREPROC); }

<COMMENT>\n   { html_end(strm,end_comment); ECHO; html_begin(strm,begin_comment); }

<COMMENT>\*\/ { ECHO; html_end(strm,end_comment); BEGIN(0); }
<CPLUS_COMMENT>\n { html_end(strm,end_comment); ECHO; BEGIN(0); }
<STRING>\"  { html_end(strm,end_string); ECHO; BEGIN(0); }
<STRING>[^\\]\\\" { ECHO; }

<TYPENAME>{IDENT}/[ \t]*[:{] {
  html_begin(strm,begin_type); ECHO; html_end(strm,end_type); BEGIN(0);
}
<TYPENAME>{IDENT} { html_begin(strm,begin_type); ECHO; html_end(strm,end_type); BEGIN(0); }
<TYPENAME>[ \t]  { ECHO; }
<TYPENAME>:      { BEGIN(0); REJECT; }
<TYPENAME>.      { BEGIN(0); REJECT; }

<PREPROC>include { ECHO; BEGIN(PRE2); }
<PREPROC>define  { ECHO; BEGIN(PRE2); }
<PREPROC>ifdef   { ECHO; BEGIN(PRE2); }
<PREPROC>ifndef  { ECHO; BEGIN(PRE2); }
<PREPROC>{IDENT} { ECHO; html_end(strm,end_preproc); BEGIN(0); }

<PRE2>\n      { html_end(strm,end_preproc); ECHO; BEGIN(0); }
<PRE2>{IDENT} { html_end(strm,end_preproc);
                html_begin(strm,begin_macro); ECHO; html_end(strm,end_macro);
		BEGIN(0); }
<PRE2>\"      { html_end(strm,end_preproc); ECHO;
                html_begin(strm,begin_incfile); BEGIN(INCFILE); }
<PRE2>\<      { html_end(strm,end_preproc); ECHO;
                html_begin(strm,begin_incfile); BEGIN(INCFILE); }

<INCFILE>\\\> { ECHO; }
<INCFILE>\\\" { ECHO; }
<INCFILE>\>  { html_end(strm,end_incfile); ECHO; BEGIN(0); }
<INCFILE>\"  { html_end(strm,end_incfile); ECHO; BEGIN(0); }

<*>\<   { ECHO; }
<*>\>   { ECHO; }
<*>&    { ECHO; }
<*>" "  { ECHO; }
<*>\n   { ECHO; }
<*>.    { ECHO; }

%%

static void
print_func_def(SDR_stream *strm, const char *name)
{
  html_begin(strm,begin_func);

  stream_printf(strm, "<a name=\"#%s\">", name);
  do_html_output(strm, name, strlen(name));
  stream_printf(strm, "</a>", name, name);

  /* The following serves to suppress a compiler warning to the effect
     that this procedure is unused. */
  if (0) yy_flex_realloc(0,0);

  html_end(strm,end_func);
}

int yywrap()
{
  return 1;
}
