%{

/*
 * file: parser/dpuser.l
 * Purpose: flex input for dpuser parser
 * Author: Thomas Ott
 *
 * History: October 1999: file created
 *
 *************************************************************************
 **                                                                     **
 **    SINCE THIS LEXICAL ANALYSER USES EXCLUSIVE START STATES,         **
 **    IT IS NOT POSSIBLE TO USE AT&T lex TO COMPILE; USE FLEX INSTEAD  **
 **                                                                     **
 *************************************************************************
 */

#include <fits.h>
#include <stdlib.h>
#include "dpuser.h"
#include <platform.h>
#include "dpuser.yacchelper.h"
#include "dpuser.pgplot.h"
#include "dpuser_funcs.h"
#include "dpuser_utils.h"
#include "y.tab.h"
#include "dpuser.h"
#include "dpuser2c/dpuserType.h"
#include "dpuser2c/utils.h"
#include "dpuser2c/functions.h"
#include "dpuser2c/procedures.h"

/*#if QT_VERSION >= 0x040000
#define contains count
#endif*/

#ifdef WIN32
#pragma warning (disable: 4996) // disable warning for deprecated POSIX name
#pragma warning (disable: 4018) // disable warning for comparing signed and unsigned
#endif

static void skip_until_eol(void);
static void skip_comment(void);
static void generateUserProc(int);
static void generateUserFunc(int);

int getInput(char *buf, int max_size);
extern int include_stack_ptr;
#define MAX_INCLUDE_DEPTH 10
extern FILE* include_stack[MAX_INCLUDE_DEPTH];
extern FILE* rl_instream;
#define YY_INPUT(buf,result,max_size) result=getInput(buf,max_size)

#ifdef CYGWIN
int isatty(int i) { return 1; }
#endif

char *s;
char stringbuf[256];
dpStringList userprocedures;
int currentUserProcedure;
dpStringList userfunctions;
int currentUserFunction;
int nfncpro = 0;
%}

%array

%x STRINGCON
%x FITSCON
%x HELPMODE
%x INCL
%x SCRIPT
%x PROCEDUREDEF
%x USERPROCEDURE
%x USERPROBODY
%x USERFUNCTION
%x USERFUNCBODY

dig [0-9]

asc [a-zA-Z0-9]
spa [ \t]
ascspa {asc}|{spa}

num1 {dig}+\.?([eEdD][-+]?{dig}+)?
num2 {dig}*\.{dig}+([eEdD][-+]?{dig}+)?
number {num1}|{num2}

stringtext				([^"])|(\\.)

%%

"!"[a-zA-Z0-9]+[ \t]*.*";"    system(yytext + 1);

@           BEGIN INCL;

<INCL>[ \t]*  ;

<INCL>[^ \t\n;]+  {
/* got the include file name */
	if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
		dp_output("Includes nested too deeply\n");
		exit( 1 );
	}  
	include_stack[include_stack_ptr++] = rl_instream;
	include_stack[include_stack_ptr] = fopen( yytext, "r" ); 
	if (!include_stack[include_stack_ptr]) {
		dp_output("Could not open file %s\n", yytext);
		include_stack_ptr--;
	}
	rl_instream = include_stack[include_stack_ptr];
	BEGIN 0;
} 

"EOF" { 
	if (include_stack_ptr) {
		fclose(include_stack[include_stack_ptr]);
		include_stack_ptr--;
		rl_instream = include_stack[include_stack_ptr];
	} else return EXIT;
}

"debug"     {
/*							dp_output("Number of oStrings:\t%li\n", numberOfOStrings); */
							dp_output("Number of dpComplex:\t%li\n", numberOfdpComplex);
							dp_output("Number of Fits:\t%li\n", numberOfFits);
							FitsInfo = TRUE;
						}

[0-9]+      {
                yylval.iValue = atoi(yytext);
                return INTEGER;
            }

([0-9]+\.?([eEdD][-+]?[0-9]+)?)|([0-9]*\.[0-9]+([eEdD][-+]?[0-9]+)?)    {
								for (int _c_ = 0; _c_ < strlen(yytext); _c_++) {
									if (yytext[_c_] == 'd') yytext[_c_] = 'e';
									else if (yytext[_c_] == 'D') yytext[_c_] = 'E';
								}
								yylval.dValue = atof(yytext);
								return REAL;
						}

([0-9]+"i")|(([0-9]+\.?([eEdD][-+]?[0-9]+)?)|([0-9]*\.[0-9]+([eEdD][-+]?[0-9]+)?)"i") {
								yylval.cValue = CreateComplex(0.0, atof(yytext));
								return COMPLEX;
						}

","" "*"/"[a-zA-Z][a-zA-Z0-9]* {
	int i;
	i = 1;
	while (yytext[i] != '/') i++;
	i++;
	yylval.sValue = strdup(yytext + i);
	return OPTION;
}

[-()<>=+*/;:,{}\[\].^!?#%] {
                return *yytext;
             }

">="|" ge "|" GE "       return GE;
"<="|" le "|" LE "       return LE;
"=="|" eq "|" EQ "       return EQ;
"!="|" ne "|" NE "       return NE;
"&&"|" and "|" AND "     return AND;
"||"|" or "|" OR "       return OR;
" GT "|" gt "|" Gt "     return '>';

" do "|" DO "|" Do "|" then "	;
"begin"|"BEGIN"|"Begin"	return '{';
"endfor"|"ENDFOR"|"Endfor"|"end"|"END"	return '}';

"+="            return PlusE;
"-="            return MinusE;
"*="            return MulE;
"/="            return DivE;
"++"            return PlusP;
"--"            return MinusM;

"exit"          return EXIT;
"quit"          return EXIT;
"bye"           return EXIT;

"help"" "*","?          { BEGIN HELPMODE; }
<HELPMODE>[a-zA-Z0-9]* {
									yylval.sValue = strdup(yytext);
									BEGIN 0;
									return HELP;
								}
<HELPMODE>" "   ;
<HELPMODE>";"   {
									yylval.sValue = strdup("");
									unput(';');
									BEGIN 0;
									return HELP;
								}
<HELPMODE>.     BEGIN 0;

"procedure "" "*[a-zA-Z][a-zA-Z0-9_]* {
									int i;
									i = 9;
									while(yytext[i] == ' ') i++;
									currentUserProcedure = lookupUserProcedure(yytext + i);
									if (currentUserProcedure == -1) {
										userpronames += (yytext + i);
										userprovars += "";
										userprocedures += "";
										userfncnames += "";
										userfncvars += "";
										userfunctions += "";
										currentUserProcedure = lookupUserProcedure(yytext + i);
									} else {
										userpronames[currentUserProcedure] = (yytext + i);
										userprovars[currentUserProcedure] = "";
										userprocedures[currentUserProcedure] = "";
									}
									BEGIN USERPROCEDURE;
								}
<USERPROCEDURE>" "*","" "*[a-zA-Z][a-zA-Z0-9_]* {
									int i;
									i = 0;
									while(yytext[i] != ',') i++;
									i++;
									while(yytext[i] == ' ') i++;
									userprovars[currentUserProcedure] += yytext + i;
									userprovars[currentUserProcedure] += " ";
								}

<USERPROCEDURE>"{"             { unput('{'); BEGIN USERPROBODY; }

<USERPROBODY>"//"          { skip_until_eol(); }

<USERPROBODY>"/*"            { skip_comment(); }

<USERPROBODY>"\n" ;
<USERPROBODY>.                {
									userprocedures[currentUserProcedure] += yytext;
									if (userprocedures[currentUserProcedure].contains('{') != 0) {
										if (userprocedures[currentUserProcedure].contains('{') - userprocedures[currentUserProcedure].contains('}') == 0) {
											// Check if this procedure has the same name as a builtin or a compiled procedure
											switch (pgWord_for_store(userpronames[currentUserProcedure])) {
											case -1:
												dp_output(">>> \"%s\" exists already as builtin procedure!\n", userpronames[currentUserProcedure].c_str());
												userpronames.pop_back();
												userprovars.pop_back();
												userprocedures.pop_back();
												break;
											case -2:
												dp_output(">>> \"%s\" exists already as stored procedure!\n", userpronames[currentUserProcedure].c_str());
												userpronames.pop_back();
												userprovars.pop_back();
												userprocedures.pop_back();
												break;
											default:
												// doesn't exist as builtin or stored procedure
                                                dp_output("Stored procedure %s\n", userpronames[currentUserProcedure].c_str());
												if (userprovars[currentUserProcedure] != "") {
													userprovars[currentUserProcedure].replace(dpRegExp(","), " ");
													userprovars[currentUserProcedure] = userprovars[currentUserProcedure].simplifyWhiteSpace();
												}
												break; 
											}
/*											if (userprocedures[currentUserProcedure].contains('{') > 1) {
												dp_output("ERROR - nesting not allowed in a procedure\n");
												userprocedures[currentUserProcedure] = "";
												userpronames[currentUserProcedure] = "";
												userprovars[currentUserProcedure] = "";
											} else {
												userprocedures[currentUserProcedure].replace(dpRegExp("{"), " ");
												userprocedures[currentUserProcedure].replace(dpRegExp("}"), " ");
											}*/
											BEGIN 0;
										}
									}
								}

"function "" "*[a-zA-Z][a-zA-Z0-9_]* {
									int i;
									i = 9;
									while(yytext[i] == ' ') i++;
									currentUserFunction = lookupUserFunction(yytext + i);
									if (currentUserFunction == -1) {
										userfncnames += (yytext + i);
										userfncvars += "";
										userfunctions += "";
										userpronames += "";
										userprovars += "";
										userprocedures += "";
										currentUserFunction = lookupUserFunction(yytext + i);
									} else {
										userfncnames[currentUserFunction] = (yytext + i);
										userfncvars[currentUserFunction] = "";
										userfunctions[currentUserFunction] = "";
									}
									BEGIN USERFUNCTION;
								}
<USERFUNCTION>" "*","" "*[a-zA-Z][a-zA-Z0-9_]* {
									int i;
									i = 0;
									while(yytext[i] != ',') i++;
									i++;
									while(yytext[i] == ' ') i++;
									userfncvars[currentUserFunction] += yytext + i;
									userfncvars[currentUserFunction] += " ";
								}

<USERFUNCTION>"{"             { unput('{'); BEGIN USERFUNCBODY; }

<USERFUNCBODY>"//"          { skip_until_eol(); }

<USERFUNCBODY>"/*"            { skip_comment(); }

<USERFUNCBODY>"\n" ;
<USERFUNCBODY>.                {
									userfunctions[currentUserFunction] += yytext;
									if (userfunctions[currentUserFunction].contains('{') != 0) {
										if (userfunctions[currentUserFunction].contains('{') - userfunctions[currentUserFunction].contains('}') == 0) {
											// Check if this function has the same name as a builtin or a compiled function
											switch (funcWord_for_store(userfncnames[currentUserFunction])) {
											case -1:
												dp_output(">>> \"%s\" exists already as builtin function!\n", userfncnames[currentUserFunction].c_str());
												userfncnames.pop_back();
												userfncvars.pop_back();
												userfunctions.pop_back();
												break;
											case -2:
												dp_output(">>> \"%s\" exists already as stored function!\n", userfncnames[currentUserFunction].c_str());
												userfncnames.pop_back();
												userfncvars.pop_back();
												userfunctions.pop_back();
												break;
											default:
												// doesn't exist as builtin or stored function
                                                dp_output("Stored function %s\n", userfncnames[currentUserFunction].c_str());
												if (userfncvars[currentUserFunction] != "") {
													userfncvars[currentUserFunction].replace(dpRegExp(","), " ");
													userfncvars[currentUserFunction] = userfncvars[currentUserFunction].simplifyWhiteSpace();
												}
												break; 
											}
											BEGIN 0;
										}
									}
								}

[a-zA-Z][a-zA-Z0-9]*" "+[a-zA-Z0-9]       { 
								int i, fail;
								fail = 0;
								i = 2;
								while (yytext[yyleng-i] == ' ') { yytext[yyleng - i] = 0; i++; }
								if (yytext[yyleng-i] == ',') { yytext[yyleng - i] = 0; i++; }
								while (yytext[yyleng-i] == ' ') { yytext[yyleng - i] = 0; i++; }
								unput(yytext[yyleng-1]);
								if (strcmp(yytext, "help") == 0) BEGIN HELPMODE;
								else {
									if ((i = pgWord(yytext)) != -10000) {
										if (i < 0) generateUserProc(-i-1);
										else {
											yylval.iValue = i;
											return PGPLOT;
										}
									} else fail = 1;
									if (strcmp(yytext, "if") == 0) {
										return IF;
									}
									if (strcmp(yytext, "else") == 0) {
										return ELSE;
									}
									if (strcmp(yytext, "for") == 0) {
										return FOR;
									}
									if (fail == 1) dp_output("%s: Unknown procedure.\n", yytext);
								}
            }

[a-zA-Z][a-zA-Z0-9_.]*       { 
								int i;
								if (strcmp(yytext, "if") == 0) {
									return IF;
								}
								if (strcmp(yytext, "else") == 0) {
									return ELSE;
								}
								if (strcmp(yytext, "for") == 0) {
									return FOR;
								}
								yylval.sIndex = lookupVariable(yytext);
								if (yylval.sIndex == -1) {
  									if ((i = pgWord(yytext)) != -10000) {
										if (i < 0) generateUserProc(-i-1);
										else {
	  										yylval.iValue = i;
											return PGPLOT;
										}
									} else {
										dp_output("%s: no such variable; assuming filename.\n", yytext);
										yylval.sValue = strdup(yytext);
										return FITSFILE;
									}
								} else {
									return VARIABLE;
								}
							}

[a-zA-Z0-9][a-zA-Z0-9_]*" "*"("       { 
								int i;

								yytext[yyleng-1]=0;
								i = yyleng - 2;
								while (yytext[i] == ' ') yytext[i--] = 0;
								if ((i = funcWord(yytext))) {
									unput('(');
									if (i < 0) generateUserFunc(-i-1);
									else {
										yylval.iValue = i;
										return FUNCTION;
									}
								} else {
									if ((i = pgWord(yytext)) != -10000) {
										yylval.iValue = i;
										unput('(');
										return PGPLOT;
									}
									if (strcmp(yytext, "for") == 0) {
										unput('(');
										return FOR;
									}
									if (strcmp(yytext, "if") == 0) {
										unput('(');
										return IF;
									}
									if (strcmp(yytext, "else") == 0) {
										unput('(');
										return ELSE;
									}
									if (strcmp(yytext, "while") == 0) {
										unput('(');
										return WHILE;
									}
									if (strcmp(yytext, "where") == 0) {
										unput('(');
										return WHERE;
									}
									dp_output("%s: Unknown function\n", yytext);
								}
							}

[a-zA-Z_][a-zA-Z0-9_]*" "*"="/[^=]		{
								int i;
								yytext[strlen(yytext)-1] = '\0';
								i = yyleng - 2;
								while (yytext[i] == ' ') yytext[i--] = 0;
                yylval.sIndex = createVariable(yytext);
								unput('=');
                return VARIABLE;
            }


\"             { BEGIN STRINGCON; s = stringbuf; }
<STRINGCON>\\\\   { *s++ = '\\'; }
<STRINGCON>\\t    { *s++ = '\t'; }
<STRINGCON>\\n    { *s++ = '\n'; }
<STRINGCON>\\\"   { *s++ = '"'; }
<STRINGCON>\"     { *s++ = '\0';
                 BEGIN 0;
								 yylval.sValue = strdup(stringbuf);
								 return STRING;
					  		}
<STRINGCON>\n     { s[-1] = '\0';
                 BEGIN 0;
								 unput(';');
								 unput('\n');
								 dp_output("Warning: Unterminated string constant\n");
								 yylval.sValue = strdup(stringbuf);
								 return STRING;
					  		}
<STRINGCON>.       { *s++ = *yytext; }

\'             { BEGIN FITSCON; s = stringbuf; }
<FITSCON>\\\'   { *s++ = '\''; }
<FITSCON>\'     { *s++ = '\0';
                 BEGIN 0;
								 yylval.sValue = stringbuf;
								 yylval.sValue = strdup(stringbuf);
								 return FITSFILE;
					  		}
<FITSCON>\n     { s[-1] = '\0';
                 BEGIN 0;
								 unput(';');
								 unput('\n');
								 yylval.sValue = stringbuf;
								 yylval.sValue = strdup(stringbuf);
								 dp_output("Warning: Unterminated FITS file name\n");
								 return FITSFILE;
					  		}
<FITSCON>.       { *s++ = *yytext; }

[ \t\n+]        ;       /* ignore whitespace */

"//"          { skip_until_eol(); }

"/*"            { skip_comment(); }

"§"[0-9]+";" {
				nunderscores = atoi(yytext + 1);
			}

.               dp_output("%s", yytext); yyerror(": Unknown character");

%%
int yywrap(void) {
    return 1;
}

static void skip_comment(void)
{
	int c1, c2;

	c1 = yyinput();
	c2 = yyinput();

	while (c2 != EOF && !(c1 == '*' && c2 == '/')) {
//		if (c1 == '\n')
//			++lineno;
		c1 = c2;
		c2 = yyinput();
	}
}

static void skip_until_eol(void)
{
	int c;

	while ((c = yyinput()) != EOF && c != '\n')
		;
	unput(';');
	unput('\n');
}

dpString generateArg(const dpString &arg, int underscore) {
	dpString rv;
	int counter = 0;

	while ((counter < arg.length())
			&& (arg[counter] != '+')
			&& (arg[counter] != '-')
			&& (arg[counter] != '/')
			&& (arg[counter] != '*')
			&& (arg[counter] != '[')) {
		rv += arg[counter];
		counter++;
	}
	bool anumber;
	arg.mid(0, 1).toFloat(&anumber);
	if ((arg.mid(0, 1) != "\"") && (arg.mid(0, 1) != ".") && (arg.mid(0, 1) != "-") && (arg.mid(0, 1) != "+") && (!anumber)) {
		if (underscore > 0) {
			rv += "_";
			rv += dpString::number(underscore);
			rv += "_";
		}
	}
	while (counter < arg.length()) {
		rv += arg[counter];
		counter++;
	}
	return rv;
}

static void generateUserFunc(int which) {
	dpString args = "";
	dpString output = "";
	int i, j = 0, i1, i2, j1, j2, nargs, nnargs, oldnunderscores = nunderscores;

	while ((j = yyinput()) != '(');
	i = 1;
	while (i != 0) {
		j = yyinput();
		args += (char)j;
		i = args.contains('(') - args.contains(')') + 1;
	}
	args.remove(args.length() - 1, 1);
	args = args.simplifyWhiteSpace();

// WARNING - the next line needs to be tested
	args.replace(" ", "");

	for (i = 0; i < args.length(); i++) {
		if (args.mid(0, i).contains('(') - args.mid(0, i).contains(')') == 0) {
			if (args.mid(0, i).contains('[') - args.mid(0, i).contains(']') == 0) {
				if (args[i] == ',') args[i] = ' ';
			}
		}
	}
	if (args[0] == ',') args.remove(0, 1);
	args = args.simplifyWhiteSpace();
	if (args == "") nargs = 0;
	else nargs = args.contains(" ") + 1;
	if (userfncvars[which] == "") nnargs = 0;
	else nnargs = userfncvars[which].contains(" ") + 1;
	if (nargs > nnargs) {
        dp_output("%s: Too many arguments - must be at most %i: %s\n", userfncnames[which].c_str(), nnargs, userfncvars[which].c_str());
		return;
	}
	output += "%{§0;";
	output += "nparams";
	output += "_";
	output += dpString::number(which+1);
	output += "_";
	output += "=";
	output += dpString::number(nargs);
	output += ";";
	if (nnargs > 0) {
		i1 = j1 = 0;
		for  (i = 0; i < nnargs; i++) {
			i2 = userfncvars[which].find(" ", i1);
			if (i2 == -1) i2 = userfncvars[which].length() + 1;
			j2 = args.find(" ", j1);
			if (j2 == -1) j2 = args.length() + 1;
			output += userfncvars[which].mid(i1, i2-i1);
			output += "_";
			output += dpString::number(which+1);
			output += "_";
			output += "=";
			if (i < nargs) {
				output += generateArg(args.mid(j1, j2-j1), oldnunderscores);
/*				output += args.mid(j1, j2-j1);
				bool anumber;
				args.mid(j1, 1).toFloat(&anumber);
				if ((args.mid(j1, 1) != "\"") && (args.mid(j1, 1) != ".") && (args.mid(j1, 1) != "-") && (args.mid(j1, 1) != "+") && (!anumber)) {
					if (oldnunderscores > 0) {
						output += "_";
						output += dpString::number(oldnunderscores);
						output += "_";
					}
				} */
			} else {
				output += "0";
			}
			output += ";";
			i1 = i2 + 1;
			j1 = j2 + 1;
		}
	}
	output += "§";
	output += dpString::number(which + 1);
	output += ";";
	output += "indexbasehere = indexbase();";
	output += "fortrannotation;";
    output += userfunctions[which].c_str();
	output += "setindexbase(indexbasehere);";
	output += "§0;";
	nfncpro++;
	output += userfncnames[which];
	output += "_";
	output += dpString::number(which+1);
	output += "_";
	output += dpString::number(nfncpro);
	output += "_=";
	output += userfncnames[which];
	output += "_";
	output += dpString::number(which+1);
	output += "_;";
	if (nargs > 0) {
		i1 = j1 = 0;
		for  (i = 0; i < nargs; i++) {
			i2 = userfncvars[which].find(" ", i1);
			if (i2 == -1) i2 = userfncvars[which].length() + 1;
			j2 = args.find(" ", j1);
			if (j2 == -1) j2 = args.length() + 1;
            if (lookupVariable(args.mid(j1, j2-j1).c_str()) != -1) {
				output += args.mid(j1, j2-j1);
				if (oldnunderscores > 0) {
					output += "_";
					output += dpString::number(oldnunderscores);
					output += "_";
				}
				output += "=";
				output += userfncvars[which].mid(i1, i2-i1);
				output += "_";
				output += dpString::number(which+1);
				output += "_";
				output += ";";
			}
			i1 = i2 + 1;
			j1 = j2 + 1;
		}
	}
	output += "§";
	output += dpString::number(oldnunderscores);
	output += ";";
	output += "}%";
	output += userfncnames[which];
	output += "_";
	output += dpString::number(which+1);
	output += "_";
	output += dpString::number(nfncpro);
	output += "_";
//	dp_output("Executing %s\n", output.c_str());

    if (output.length() > YYLMAX) dp_output("Function %s is too long - max size is %i bytes\n", userfncnames[which].c_str(), YYLMAX);
    else for (j = output.length() - 1; j >= 0; j--) unput(output.c_str()[j]);

//	yy_scan_string(output.c_str());
}

static void generateUserProc(int which) {
	dpString args = "";
	dpString output = "";
	int i, j = 0, i1, i2, j1, j2, nargs, nnargs, oldnunderscores = nunderscores;

	while ((j = yyinput()) != ';') args += (char)j;
	args = args.simplifyWhiteSpace();

// WARNING - the next line needs to be tested
	args.replace(" ", "");

	for (i = 0; i < args.length(); i++) {
		if (args.mid(0, i).contains('(') - args.mid(0, i).contains(')') == 0) {
			if (args.mid(0, i).contains('[') - args.mid(0, i).contains(']') == 0) {
				if (args[i] == ',') args[i] = ' ';
			}
		}
	}
	if (args[0] == ',') args.remove(0, 1);
	args = args.simplifyWhiteSpace();
	if (args == "") nargs = 0;
	else nargs = args.contains(" ") + 1;
	if (userprovars[which] == "") nnargs = 0;
	else nnargs = userprovars[which].contains(" ") + 1;
	if (nargs > nnargs) {
        dp_output("%s: Too many arguments - must be at most %i: %s\n", userpronames[which].c_str(), nnargs, userprovars[which].c_str());
		return;
	}
	output += "{§0;";
	output += "nparams";
	output += "_";
	output += dpString::number(which+1);
	output += "_";
	output += "=";
	output += dpString::number(nargs);
	output += ";";
	if (nnargs > 0) {
		i1 = j1 = 0;
		for  (i = 0; i < nnargs; i++) {
			i2 = userprovars[which].find(" ", i1);
			if (i2 == -1) i2 = userprovars[which].length() + 1;
			j2 = args.find(" ", j1);
			if (j2 == -1) j2 = args.length() + 1;
			output += userprovars[which].mid(i1, i2-i1);
			output += "_";
			output += dpString::number(which+1);
			output += "_";
			output += "=";
			if (i < nargs) {
				output += generateArg(args.mid(j1, j2-j1), oldnunderscores);
/*				output += args.mid(j1, j2-j1);
				bool anumber;
				args.mid(j1, 1).toFloat(&anumber);
				if ((args.mid(j1, 1) != "\"") && (args.mid(j1, 1) != ".") && (args.mid(j1, 1) != "-") && (args.mid(j1, 1) != "+") && (!anumber)) {
					if (oldnunderscores > 0) {
						output += "_";
						output += dpString::number(oldnunderscores);
						output += "_";
					}
				} */
			} else {
				output += "0";
			}
			output += ";";
			i1 = i2 + 1;
			j1 = j2 + 1;
		}
	}
	output += "§";
	output += dpString::number(which + 1);
	output += ";";
	output += "indexbasehere = indexbase();";
	output += "fortrannotation;";
    output += userprocedures[which].c_str();
	output += "setindexbase(indexbasehere);";
	output += "§0;";
	if (nargs > 0) {
		i1 = j1 = 0;
		for  (i = 0; i < nargs; i++) {
			i2 = userprovars[which].find(" ", i1);
			if (i2 == -1) i2 = userprovars[which].length() + 1;
			j2 = args.find(" ", j1);
			if (j2 == -1) j2 = args.length() + 1;
            if (lookupVariable(args.mid(j1, j2-j1).c_str()) != -1) {
				output += args.mid(j1, j2-j1);
				if (oldnunderscores > 0) {
					output += "_";
					output += dpString::number(oldnunderscores);
					output += "_";
				}
				output += "=";
				output += userprovars[which].mid(i1, i2-i1);
				output += "_";
				output += dpString::number(which+1);
				output += "_";
				output += ";";
			}
			i1 = i2 + 1;
			j1 = j2 + 1;
		}
	}
	output += "§";
	output += dpString::number(oldnunderscores);
	output += ";";
	output += "}";
//	printf("Executing %s\n", output.c_str());
	unput(';');

    if (output.length() > YYLMAX) dp_output("Procedure %s is too long - max size is %i bytes\n", userpronames[which].c_str(), YYLMAX);
    else for (j = output.length() - 1; j >= 0; j--) unput(output.c_str()[j]);
//	yy_scan_string(output.c_str());
}
