/* Stubby - Generate stubs for dynamic-link libraries.
 * Copyright 1999 Tom Rothamel
 *
 * Stubby is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version. It is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * This program generates another computer program. I do not assert a      
 * copyright on the generated program that is the normal output of this    
 * program. This is _not_, however, an authorization for you to modify     
 * this program to cause it to output more of itself than necessary for    
 * its proper operation in order to circumvent my copyright.               
 */

/* This is the lexer for the C-like input language. */

%{
#include "stubby.h"
#include "pte.h"
#include "str.h"
#include "cparser.h"

#define MAX_INCLUDE_DEPTH 128
int include_stack_pointer = 0;
YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
char *infile_stack[MAX_INCLUDE_DEPTH]; 
int yylineno_stack[MAX_INCLUDE_DEPTH];
 
%}

%option yylineno
%option yywrap

%x string comment

CHAR [A-Za-z0-9_]
STARTCHAR [A-Za-z_]

%%

[ \t\n\r]

 /* Quoted strings. */
\" BEGIN(string);
<string>[^\"]*\" {
	yylval.str = strdup(yytext);

	yylval.str[strlen(yylval.str)-1] = 0;
	
	BEGIN(INITIAL);
	return STRING;
}



 /* Comments */
"/*" BEGIN(comment);
<comment>[^*]*
<comment>"*"+[^*/]*
<comment>"*"+"/" BEGIN(INITIAL);

debug { return DEBUG; }
include { return INCLUDE; }
const { return CONST; }
library { return LIBRARY; }
load { return LOAD; }
type { return TYPE; }
void { return VOID; }

struct { return STRUCT; }

extern /* It's ignored. */

{STARTCHAR}{CHAR}* {
	yylval.str = strdup(yytext);
	if (istype(yylval.str)) {
		if (yydebug) debug("*** type %s.", yylval.str);
		return TYPESTR;
	}
	
	if (yydebug) debug("*** name %s.", yylval.str);
	
	return NAME;
}

. { return yytext[0]; }

%%

int yywrap() {
	if (--include_stack_pointer < 0) {
		return 1;
	} else {
		yy_delete_buffer(YY_CURRENT_BUFFER);
		yy_switch_to_buffer(include_stack[include_stack_pointer]);
		
		infile = infile_stack[include_stack_pointer];
		yylineno = yylineno_stack[include_stack_pointer];

		return 0;
	}	
}
	
void include(char *nif) {
	
	if (include_stack_pointer >= MAX_INCLUDE_DEPTH) {
		error("Includes nested too deeply.");
		exit(-1);
	}

	yylineno_stack[include_stack_pointer] = yylineno;
	include_stack[include_stack_pointer] = YY_CURRENT_BUFFER;
	infile_stack[include_stack_pointer++] = infile;

	yyin = fopen(nif, "r");
	if (!yyin) {
		error("Couldn't open include file '%s'.", nif);
		exit(-1);
	}
	infile = nif;
	yylineno = 1;

	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));

	if (yydebug) debug("Now processing file %s.\n", infile);
}
