SC	[\\'"netbgr\ @#]
C	[a-zA-Z0-9öäüßåÖÄÜÅ_\\=$%£@&/!\^\~;:.,\?\{\}\(\)\[\]\<\>\-\+\*\|\'\`]

E	[\ ]*"="[\ ]*

L	[a-zA-ZöäüßåÖÄÜÅ0-9_]
D	[0-9]

PC	\\[0-3][0-7][0-7]

EX      [" "\t]*

%{

#define YYDEBUG

#include <string.h>
#include "conf_yacc.h"
#include "report.h"
#include "list.h"
#include "symboltable.h"
#include "commandconf.h"
#include "db_config.h"

void includehandler() ;
void conf_put_token(const char*);

int firstnotempty(char* s);

typedef struct conf_buffer_type {
  char* buff;
  char* pos;
} conf_buffer_type;

list* l_symt=NULL;
list* conf_buffer=NULL;
int condition=0;
int varbol=0;

long conf_lineno=1;

#define MAX_INCLUDE_DEPTH 10
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
int include_stack_ptr = 0;

int var_in_conflval=0;

%}

%Start A EXPR DEFSTMT DEFSTMT2 IFDEFSTMT INCLUDE EXPREQUHUNT VARSUB CONFVALHUNT

%%

^[\t \ ]*"#"[^\n]* {
 }


^[^\n]*"\@\@\{"({L}+)"}"[^\n]* {
  
  putbackvariable(conftext);

  error(230,"%i:Variable substitution\n",conf_lineno);
  
}



^[\ \t]*"=/"({C}|{PC})* {
  conflval.s=strdup(conftext+1+firstnotempty(conftext));
  BEGIN(EXPR);
  return (TEQURXRULE);
}

^[\ \t]*"/"({C}|{PC})* {
  conflval.s=strdup(conftext+firstnotempty(conftext));
  error(230,"Selrule\n");
  BEGIN(EXPR);
  return (TSELRXRULE );
}

^[\ \t]*"!/"({C}|{PC})* {  
  conflval.s=strdup(conftext+1+firstnotempty(conftext));
  error(230,"Negrule\n");
  return (TNEGRXRULE );
}

^[\ \t]*({L})+ {
  conflval.s=strdup(conftext+firstnotempty(conftext));
  error(230,"Equrule\n");
  BEGIN(EXPREQUHUNT);
  return (TSTRING);
}

<EXPREQUHUNT>[\ \t]*"="[\ \t]* {
  BEGIN(EXPR);
  return('=');
}


<EXPR>[\ \t]*({L}|{D}|">")+ {
  conflval.s=strdup(conftext+firstnotempty(conftext));
  return (TSTRING);
}

<EXPR>[\ \t]*\n {
  conf_lineno++;
  return (TNEWLINE);
  BEGIN 0;
}

<EXPR>\+ {
  return ('+');
}

<EXPR>\- {
  return ('-');
}

<DEFSTMT>({L})+ {
  error(230," %s",conftext);
  conflval.s=strdup(conftext);
  BEGIN (DEFSTMT2);
  return (TSTRING);
}

<DEFSTMT2>({C})+ {
  error(230," %s",conftext);
  conflval.s=strdup(conftext);
  return (TSTRING);
}

<DEFSTMT2>[\ \t]*"\n" { 
  error(230,"\n");
  conf_lineno++;
  BEGIN 0;
  return (TNEWLINE);
}

^[\ \t]*"\@\@define" {
  error(230,"@@define");
  BEGIN DEFSTMT;
  return (TDEFINE);
}

^[\ \t]*"\@\@undef" {
  error(230,"@@undef");
  BEGIN IFDEFSTMT;
  return (TUNDEF);
}


^[\ \t]*"\@\@ifndef" {
  error(230,"@@ifndef");
  BEGIN IFDEFSTMT;
  return (TIFNDEF);
}

^[\ \t]*"\@\@ifdef" {
  error(230,"@@ifdef");
  BEGIN IFDEFSTMT;
  return (TIFDEF);
}

^[\ \t]*"\@\@else" {
  error(230,"@@else");
  BEGIN 0;
  return (TELSE);
}

^[\ \t]*"\@\@endif" {
  error(230,"@@endif");
  BEGIN 0;
  return (TENDIF);
}

<IFDEFSTMT>({L})+ {
  error(230," %s",conftext);
  conflval.s=strdup(conftext);
  BEGIN 0;
  return (TSTRING);
}


^[\ \t]*"\@\@ifhost" {
  error(230,"@@ifhost");
  BEGIN IFDEFSTMT;
  return (TIFHOST);
}

^[\ \t]*"\@\@ifnhost" {
  error(230,"@@ifnhost");
  BEGIN IFDEFSTMT;
  return (TIFNHOST);
}

^[\ \t]*"\@\@db_spec" {
  conf_put_token("\n@@db_spec");
  error(230,"@@db_spec");
  return (TDBSPEC);
}

^[\ \t]*"\@\@include" {
  BEGIN INCLUDE;
}

<INCLUDE>[^ \t\n]+ {
  includehandler();
  BEGIN 0;
  error(230,"@@include\n");
  return (TNEWLINE);
}

<<EOF>> {
        if ( --include_stack_ptr < 0 )
            {
            yyterminate();
            }

        else
            {

            if (confin != stdin ) {
              fclose(confin);
              }

            conf_delete_buffer( YY_CURRENT_BUFFER );
            conf_switch_to_buffer(
                 include_stack[include_stack_ptr] );
            }
}


[\t\ ]+ {}

"\n" { 
  conf_lineno++;
  BEGIN 0;
  return (TNEWLINE);
 }

^[\t\ ]*"database"{E} {
  error(230,"database =\n");
  BEGIN CONFVALHUNT;
  return (TDATABASE);
} 

^[\t\ ]*"database_out"{E}  {
  error(230,"database_out =\n");
  BEGIN CONFVALHUNT;
  return (TDATABASE_OUT);
}

^[\t\ ]*"verbose"{E} {
  error(230,"verbose =\n");
  return (TVERBOSE);  
}

^[\t\ ]*"report_url"{E} {
  error(230,"report_url =\n");
  BEGIN CONFVALHUNT;
  return (TREPORT_URL);  
}


<CONFVALHUNT>({C})+ {
  conflval.s=strdup(conftext);
  BEGIN 0;
  return (TSTRING);
}


({L})+ {
  conflval.s=strdup(conftext);
  return (TSTRING);
}


[^\n] { return(conftext[0]); }

%%

int confwrap(){
  return 1;
}

void conf_put_token(const char* s){

  int i=0;

  for(i=strlen(s)-1;i>=0;i--){
       unput(s[i]);
       if(s[i]=='\n'){
          conf_lineno--;
       }
  }
  
}

int firstnotempty(char* s){
  
  int i=0;

  if (s==NULL) {
    return i;
  }


  while( s[i]==' ' || s[i]=='\t') {
    i++;
  }

  return i;

}

void includehandler() { 
  /* got the include file name */
  if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
    {
      error( 0, "Includes nested too deeply" );
      exit( 1 );
    }

  if (strcmp(conftext,"-")==0) {
      confin = stdin;
    } else {
      confin = fopen( conftext, "r" );
    }
  if ( ! confin ) {
    error(0,"Cannot open config file %s\n",conftext);
  } else {
    include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
    conf_switch_to_buffer(conf_create_buffer( confin, YY_BUF_SIZE ) );
  }
  
}

