#ifdef WIN
#pragma warning (disable: 4786) // disable warning for STL maps
#pragma warning (disable: 4018) // disable warning for comparing signed and unsigned
#endif /* WIN */

#include "tools.h"
#include <string.h>
#include "dpuser2c.h"
#include "dpuser_utils.h"
#include "functions.h"
#include "procedures.h"
#include <stdarg.h>

#ifdef WIN
#include <windows.h>
#include <winbase.h>
#endif

//using namespace std;

extern std::string name;

std::vector<std::string> output;
std::vector<std::string>  tools_variables;      // in parser/y.tab.cpp exists also a conValue named variables
std::vector<std::string>  constants_variables; 
std::vector<std::string> arguments;
std::string tmpvar;
std::string preline;

int bracketcounter = 0;
int TNameCounter = 0;
bool idlcode = false;
char ___tmpcounter = 'a';

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

void eatCcomment(char *src) {
	int i;
	char *start;
	char *end;
	
	start = src;
	
	while (start != NULL) {
		start = strstr(start, "/*");
		if (start != NULL) {
			end = strstr(start, "*/");
			if (end != NULL) {
				for (i = 0; i < end-start+2; i++) start[i] = ' ';
				start = end;
			}
		}
	}
}

void eatCCcomment(char *src) {
	int i;
	char *start;
	start = src;
	
	while (start != NULL) {
		start = strstr(start, "//");
		if (start != NULL) {
			i = 0;
			while (start[i] != '\n' && i < strlen(start)) start[i++] = ' ';
		}
	}
}

void eatIDLComment(char *src) {
	int i;
	char *start;
	start = src;
	
	while (start != NULL) {
		start = strstr(start, ";");
		if (start != NULL) {
			i = 0;
			while (start[i] != '\n' && i < strlen(start)) start[i++] = ' ';
		}
	}
}

void IDLtoDPUSERcommands(dpString &src) {
	long index;
	dpString idlcode;
	
	idlcode = "on_error";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 8, "print");
	}
	idlcode = "n_elements";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 10, "nelements");
	}
	idlcode = "n_params()";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 10, "nparams");
	}
	idlcode = "fltarr";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 6, "floatarray");
	}
	idlcode = "!radeg";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 6, "(180/pi())");
	}
	idlcode = "!dpi";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 4, "pi()");
	}
	idlcode = "alog";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 4, "ln");
	}
	idlcode = "alog10";
	while ((index = src.strpos(idlcode, FALSE)) != -1) {
		src.replace(index, 6, "log");
	}
/*
	idlcode = "where(";
	if ((index = src.strpos(idlcode, FALSE)) != -1) {
		long i = index + 6;
		while ((src[i] != ',') && (src[i] != ')')) i++;
		if (src[i] == ',') {
			i++;
			long j = i+1;
			dpString varname;
			varname = "";
			while (src[j] != ')') {
				varname += src[j];
				j++;
			}
			
		}
	}
*/
}

// dpStringList splitIntoLines(const char sep, dpString source) {
// 	dpStringList rv;
// 	dpint64 pos = 0, oldpos = 0;
// 
// 	while (pos < source.size()) {
// 		oldpos = pos;
// 		pos = source.find(sep, pos);
// 		if (pos < source.size()) {
// 			rv.push_back(source.mid(oldpos, pos-oldpos+1));
// 			pos++;
// 		}
// 	}
// //	rv.push_back(source.mid(oldpos, source.size()-oldpos+1));
// 
// dpStringList::iterator iter = rv.begin();
// int cnt = 1;
// while (iter != rv.end()) {
// 	printf("rv : %s\n", (*iter).c_str());
// 	iter++;
// 	cnt++;
// }
// printf("xxxxx\n");
// 
// 	return rv;
// }

std::string extractVariable(const char *str) {
	std::string rv;
	int i = 0;
	
	while((str[i] == ' ')
		|| (str[i] == '\t')) i++;
    while((str[i] != '\0')
        && (str[i] != '=')
		&& (str[i] != ' ')
		&& (str[i] != '\t')) rv += str[i++];
	
	return rv;
}

bool isVariable(const char *str) {
	int i;
	
	for (i = 0; i < tools_variables.size(); i++) if (tools_variables[i] == str) return TRUE;
	for (i = 0; i < arguments.size(); i++) if (arguments[i] == str) return TRUE;
	return FALSE;
}

std::string extractsetvar(const char *str) {
	std::string rv;
	int i = 0;
	
	while(str[i] != '=' && str[i] != ' ') rv += str[i++];
	return rv;
}

void flushOutput(dpString name, dpString cCode) {
#ifdef WIN
	if(GetFileAttributes((std::string(name) + ".cpp").c_str()) != 0xFFFFFFFF) {
#ifdef CYGWIN
		std::string del_cmd = "rm " + name + ".cpp";
#else
		std::string del_cmd = "del " + name + ".cpp";
#endif
		if (system(del_cmd.c_str()) != 0) {
			del_cmd = ">>> Failed deleting file: " + std::string(name) + ".cpp";
			throw dpuserTypeException((char*)del_cmd.c_str());
			return;
		}
	}
#endif
	FILE *ofd = fopen((name + ".cpp").c_str(), "wb");
	if (ofd == NULL) {
		dp_output(">>> Error creating cpp-file.\n");
		return;
	}

	std::vector<std::string> vars;
	std::string var;
	if ((output.size() == 0) && (cCode.size() == 0)) return;
	int i, j;
	int alreadyThere;

	// ############# WRITE HEADER #############

	// print pragma
    #ifdef WIN
	fprintf(ofd, "#pragma warning (disable: 4786)\n"); // disable warning for STL maps
	fprintf(ofd, "\n");
	#endif

	// print c-includes
	fprintf(ofd, "#include <map>\n");
	fprintf(ofd, "#include <vector>\n");
	fprintf(ofd, "#include <ctype.h>\n");
	fprintf(ofd, "#include <string>\n");
	fprintf(ofd, "#include <math.h>\n\n");
	
	// our very own integer type
	fprintf(ofd, "typedef long long dpint64;\n\n");
	
	// print forward-declarations
	fprintf(ofd, "class dpStringList;\n");
	fprintf(ofd, "class dpComplex;\n");
	fprintf(ofd, "class Fits;\n");
  fprintf(ofd, "class dpuserTypeList;\n");
	fprintf(ofd, "class CJulianDay;\n");
	fprintf(ofd, "class dpRegExp;\n\n");

	// print dp_output-definition from fits.h (line 29)
	#ifdef DPQT
	fprintf(ofd, "int dp_output(const char *, ...);\n");
	#else
    fprintf(ofd, "#include <stdio.h>\n#define dp_output printf\n");
	#endif
	
	fprintf(ofd, "\n");

	// determine length of header_str
	int ll= 0, lp = 0;	
	while (ll < 2) {
		lp++;
		if (strlen(header_str[lp]) == 0) ll++;
		else ll = 0;
	}

	// loop header_str and add to file
	ll = 0;
	while (ll < lp) {
		fprintf(ofd, "%s\n", header_str[ll]);
		ll++;
	}

	// ############# WRITE COMPILED FUNCTIONS #############
	// (add extern "C" declarations so previously compiled functions and procedures are known)
	fprintf(ofd, "// function declarations\n");
	for (i = 0; i < compiledfunctions.size(); i++) {
		if (name != compiledfunctions[i].name) {
         fprintf(ofd, "extern \"C\" %s ;\n", compiledfunctions[i].displaySyntax.c_str());
		}
	}
	fprintf(ofd, "// procedure declarations\n");
	for (i = 0; i < compiledprocedures.size(); i++) {
		if (name != compiledprocedures[i].name) {
         fprintf(ofd, "extern \"C\" %s ;\n", compiledprocedures[i].displaySyntax.c_str());
		}
	}

	// (add extern "C" declarations for functions and procedures to be compiled,
   // which are defined in the same file)
	fprintf(ofd, "// function or procedure declarations of same file\n");

   // omit last function stored in funcProcOrder! For this one we don't need a forward declaration
   // because it is written below at ###### WRITE FUNCTION ########
   std::list<FuncProcInfo>::iterator iter = funcProcOrder.begin();
   int cnt = funcProcOrder.size();
   while ((iter != funcProcOrder.end()) && (cnt > 1)) {
		// check if the name isn't already defined in  compiledfunctions or compiledprocedures
      // (due to recompilation)
		bool existsFuncOrProc = false;
		for (j = 0; j < compiledfunctions.size(); j++) {
			std::string::size_type loc = (*iter).displaySyntax.find(compiledfunctions[j].name.c_str(), 0);
			if (loc != std::string::npos) {
				existsFuncOrProc = true;
				break;
			}
		}

		for (j = 0; j < compiledprocedures.size(); j++) {
			std::string::size_type loc = (*iter).displaySyntax.find(compiledprocedures[j].name.c_str(), 0);
			if (loc != std::string::npos) {
				existsFuncOrProc = true;
				break;
			}
		}

		if (!existsFuncOrProc) {
         fprintf(ofd, "extern \"C\" %s;\n", (*iter).displaySyntax.c_str());
		}
      iter++;
      cnt--;
	}

	// ############# WRITE FUNCTION #############
	fprintf(ofd, "// the function itself\n");
	if (cCode.size() == 0) {
		// code has been parsed and stored to the variable output (somehow...)
		fprintf(ofd, "extern \"C\" %s\n", output[0].c_str());
		fprintf(ofd, "\tdpuserType ");
		for (i = 0; i < tools_variables.size(); i++) {
			var = tools_variables[i];
			alreadyThere = 0;
			for (j = 0; j < vars.size(); j++) {
				if (strcmp(var.c_str(), vars[j].c_str()) == 0) alreadyThere = 1;
			}
			for (j = 0; j < arguments.size(); j++) {
				if (strcmp(var.c_str(), arguments[j].c_str()) == 0) alreadyThere = 1;
			}
			if (alreadyThere == 0) vars.push_back(var);
		}
		for (i = 0; i < vars.size()-1; i++) fprintf(ofd, "%s, ", vars[i].c_str());
		fprintf(ofd, "%s;\n\n", vars[vars.size() - 1].c_str());
		
		fprintf(ofd, "// The constants!\n");
		for (i = 0; i < constants_variables.size(); i++) {
			fprintf(ofd, "%s;\n", constants_variables[i].c_str());
		}	
		
		if (idlcode) {
			fprintf(ofd, "\tdpuserProcedure_cnotation();\n");
		}
		fprintf(ofd, "try {\n");
		
		for (i = 1; i < output.size(); i++) {
			if (output[i].size() > 1) fprintf(ofd, "%s\n", output[i].c_str());
		}
		fprintf(ofd, "\n} catch (dpuserTypeException e) {\n\tdp_output(\"%%s\", e.reason());\n}\n");
		if (output[0][0] == 'd') {
			fprintf(ofd, "\treturn %s;\n}\n", tools_variables[0].c_str());
		} else {
			fprintf(ofd, "}\n");
		}
		
		tools_variables.clear();
		constants_variables.clear();
		TNameCounter = 0;
		arguments.clear();
		output.clear();
	} else {
	  // c-code has been compiled (and not parsed!)
	  fprintf(ofd, "%s", cCode.c_str());
	  fprintf(ofd, "%s", "\n"); // all whitespace has been removed in compileCcode()
	}
	fclose(ofd);
}

void addLineToOutput(const std::string &what) {
	std::string l;
	int i;
// output compiled code to console
	if (preline != "") output.push_back(preline);
	for (i = 0; i < bracketcounter; i++) l += '\t';
	l += what;
	output.push_back(l);
	preline = "";
}

// tweak the input such that the parser can savely go through
char *tweakInput(char *buf) {
	int i, l, p;
	char *result, *pp;
	dpString inp;

	p = 1;
	l = strlen(buf);
	for (i = 0; i < l; i++) if (buf[i] == '}') p++;
	result = (char *)malloc((l + p + 1) * sizeof(char));
	strcpy(result, buf);
	for (i = 0; i < l; i++) if (result[i] == '\n') result[i] = ' ';

/* delete trailing blanks */
    while ((l > 0) && ((result[l - 1] == ' ') || (result[l - 1] == '\t'))) {
		l--;
		result[l] = (char)0;
	}

/* Insert a ';' before each '}', if necessary */
	pp = result;
	while ((pp = strchr(pp, '}')) != NULL) {
		if (pp != result) {
// is this within a string?
			dpString test;
			int i;
			for (i = 0; result + i < pp; i++) test += result[i];
			if (!(test.contains('"') % 2) && !(test.contains('\'') % 2)) {
				p = -1;
                while ((pp + p >= result) && ((pp[p] == ' ') || (pp[p] == '\t'))) p--;
                if ((pp + p >= result) && (pp[p] != '}') && (pp[p] != ';')) {
					for (i = l; i >= pp-result; i--) result[i + 1] = result[i];
					pp[0] = ';';
				}
			}
		}
		pp++;
		if (pp[0] == (char)0) break;
	}

/* Insert a ';' at the end if necessary */
	l = strlen(result);
    if ((l > 0) && (result[l - 1] != '}') && (result[l - 1] != '{') && (result[l - 1] != ';')) {
		result[l] = ';';
		result[l + 1] = (char)0;
	}

/* replace @script; by run "script";
   only do this if at the beginning of a line (excluding whitespaces) */
	inp = result;
        inp = inp.stripWhiteSpace();
        if (inp[0] == '@') {
            i = 0;
            p = -1;
            inp.replace(i, 1, "run \"");
            p = inp.find(';', i);
            inp.replace(p, 1, "\";");
        }

	if (p != -1) {
		result = (char *)realloc(result, inp.length() * sizeof(char) + 1);
        strcpy(result, inp.c_str());
	}

	return result;
}		

std::string createRangeArguments(const char *str) {
//printf(">>>> createRangeArguments()\n");
	std::string rv, substr;
	std::string sub1;
	std::string act;
	int i = 0;
	char lasttoken = '[';
	bool start = TRUE;
	
	rv = "\n";
	while ((str[i] == ' ')
		|| (str[i] == '[')
		|| (str[i] == '\t')) i++;
	
	while (str[i] != ']') {
		substr = "";
		while ((str[i] != ',')
			&& (str[i] != ':')
			&& (str[i] != ']')) substr += str[i++];

		if (start) act = ".initappend(";
		else act = ".append(";
		if (lasttoken == '[' && str[i] == ',') rv += "\n" + tmpvar + act + substr + ");";
		if (lasttoken == '[' && str[i] == ']') rv += "\n" + tmpvar + act + substr + ");";
		if (lasttoken == ',' && str[i] == ',') rv += "\n" + tmpvar + act + substr + ");";
		if (lasttoken == ',' && str[i] == ']') rv += "\n" + tmpvar + act + substr + ");";
		if (str[i] == ':') {
			sub1 = substr;
			substr = "";
		} else start = FALSE;
		if (lasttoken == ':') rv += "\n" + tmpvar + act + "findgen(" + substr + "-" + sub1 + " + 1) + " + sub1 + ");";

		lasttoken = str[i];

		if (str[i] != ']') i++;
	}
	rv += "\n";
	return rv;
}

std::string createRange(const char *str) {
	___tmpcounter++;
	tmpvar = std::string("___dpusertmp___") + ___tmpcounter;
	tools_variables.push_back(tmpvar);
//printf(">>>> createRange()\n");
//printf(">>>> createRange(): preline: %s\n", preline);
//printf(">>>> createRange(): preline: %s\n", str);
	preline += createRangeArguments(str);
//printf(">>>> createRange(): preline: %s\n", preline);
	return tmpvar;
}

// Creates arrays, vectors in cpp from dpuser-scripts
dpuserType CREATE(int nargs, ...) {
	dpuserType rv;
 	va_list ap;
 	int i;
 	va_start(ap, nargs);

	// check if first argument is of type typeFits
 	for (i = 0; i < nargs; i++) {
		rv.append(va_arg(ap, dpuserType*));
	}		
 	va_end(ap);

	return rv;
}

std::string CREATErange(const char *str) {
	std::string rv;
	rv = "";

	std::string sub1, substr;
	int i = 0;
	char lasttoken = '[';
	bool start = TRUE;
	bool create = FALSE;
	int nargs = 0;
	int parenthesis;
	
	while ((str[i] == ' ')
		|| (str[i] == '[')
		|| (str[i] == '\t')) i++;
	
	while (str[i] != ']') {
		create = (strlen(&str[i]) > 7 && str[i] == 'C');
		if (create) lasttoken = '[';
		if (str[i] == '&') substr = "";
		else substr = "&";
		if (!create) substr += "(";
		parenthesis = 0;
		while (((str[i] != ',')
			&& (str[i] != ':')
			&& (str[i] != ']'))
			|| (parenthesis > 0)) {
				if (str[i] == '(') parenthesis++;
				else if (str[i] == ')') parenthesis--;
				substr += str[i++];
		}
		if (lasttoken == '[' && str[i] == ',') {
			if (create) rv += substr + ",";
			else rv += substr + "),";
		}
		if (lasttoken == '[' && str[i] == ']') if (create) rv += substr + ")"; else rv += substr + "))";
		if (lasttoken == ',' && str[i] == ',') rv += substr + "),";
		if (lasttoken == ',' && str[i] == ']') rv += substr + "))";
//Alex 		if (lasttoken == '[' && str[i] == ',') rv += "(double)" + substr + ",";
//Alex		if (lasttoken == '[' && str[i] == ']') rv += "(double)" + substr + ")";
//Alex 		if (lasttoken == ',' && str[i] == ',') rv += "(double)" + substr + ",";
//Alex 		if (lasttoken == ',' && str[i] == ']') rv += "(double)" + substr + ");";
		if (str[i] == ':') {
			sub1 = substr;
			substr = "";
		} else start = FALSE;
		if (lasttoken == ':') rv += "findgen(" + substr + "-" + sub1 + " + 1) + " + sub1 + ",";

		lasttoken = str[i];
		nargs++;

		if (str[i] != ']') i++;
	}

// find occurences of nested CREATE statements and decrement nargs accordingly
	i = 0;
	while (i < rv.length()) {
		i = rv.find("CREATE(", i);
		if (i < rv.length()) {
			i += 7;
//			nargs -= atoi(&(rv.c_str()[i]));
		}
	}


	rv = "CREATE(" + dpString::number(nargs) + "," + rv;

	return rv;
}

std::string extractRangeArguments(const char *str) {
	std::string rv, substr, subnowhite;
	int i = 0, j;
	char lasttoken = '[';
	
	while ((str[i] == ' ')
		|| (str[i] == '[')
		|| (str[i] == '\t')) i++;
	
	if (strncmp(str+i, "where", 5) == 0) {
		while (str[i] != ']') rv += str[i++];
	} else while (str[i] != ']') {
		substr = "";
		while ((str[i] != ',')
			&& (str[i] != ':')
			&& (str[i] != ']')) substr += str[i++];

		if (lasttoken == '[' && str[i] == ',') substr = substr + ", " + substr + ", ";
		if (lasttoken == ',' && str[i] == ',') substr = substr + ", " + substr + ", ";
		if (lasttoken == '[' && str[i] == ']') substr = substr + ", " + substr;
		if (lasttoken == ',' && str[i] == ']') substr = substr + ", " + substr;
		if (lasttoken == ':' || str[i] == ':') if (str[i] != ']') substr = substr + ", ";

		subnowhite = "";
		for (j = 0; j < substr.size(); j++) if (substr[j] != ' ') subnowhite += substr[j];
		if (subnowhite == "*,*") substr = "-1, -1";
		else if (subnowhite == "*,*,") substr = "-1, -1, ";
		
		lasttoken = str[i];
		rv += substr;

		if (str[i] != ']') i++;
	}
	return rv;
}

std::string extractWhereArguments(const char *str) {
	std::string rv;
	int i = 0;
	
	while (str[i] != '='
		&& str[i] != '<'
		&& str[i] != '>'
		&& str[i] != '!') rv += str[i++];
	
	rv += ", \"";
	rv += str[i];
	i++;
	if (str[i] == '=') rv += "=\", ";
	else {
		rv += "\", ";
		rv += str[i];
	}
	i++;
	while (i < strlen(str)) rv += str[i++];
	
	return rv;
}

std::string insertTabs() {
	std::string rv = "";
	int i;
	
	for (i = 0; i < bracketcounter; i++) rv += '\t';
	
	return rv;
}

std::string renameFunction(const char *str) {
	std::string rv;
	bool builtin = FALSE;
	int i;

	rv = str;
	for (i = 0; i < funcs.size(); i++) {
		if (funcs[i].name == rv) {
			builtin = TRUE;
			break;
		}
	}
	if (builtin) rv = std::string("dpuserFunction_") + str;

	return rv;
}

std::string renameProcedure(const char *str) {
	std::string rv;
	bool builtin = FALSE;
	int i;

	rv = str;
	for (i = 0; i < procs.size(); i++) {
		if (procs[i].name == rv) {
			builtin = TRUE;
			break;
		}
	}
	if (builtin) rv = std::string("dpuserProcedure_") + str;

	return rv;
}

void createInfo(const funcorproc_ID type, const int nargs, const std::string name, const std::string displaySyntax) {
	FuncProcInfo info;
	info.nargs = nargs;
	info.name = dpString(name);
	info.id = type;
   info.displaySyntax = dpString(displaySyntax);
	funcProcOrder.push_back(info);
}

std::string createTName(void) {
	std::string rv = "_c";
	char num[256];

	::sprintf(num, "%li", TNameCounter);
	rv += num;
	TNameCounter++;

	return rv;
}

std::string ExtractRangeArgs(char *str) {
	std::string rv = "";
	std::string substr;
	int i = 0;

	while (i < strlen(str)) {
		switch (str[i]) {
			case '#': i++; break;
			case '%':
				i++;
				substr = "";
				while (str[i] != '%') {
					substr += str[i];
					i++;
				}
				rv += substr;
				rv += ", ";
				rv += substr;
				i++;
				break;
			default:
				rv += str[i];
				i++;
				break;
		}
	}
	return rv;
}

std::string CreateRangeArgs(char *str) {
	std::string rv = "";
	std::string rrv;
	std::string substr;
	int i = 0;
	int count = 0;
	char ncount[10];

	while (i < strlen(str)) {
		switch (str[i]) {
			case '#':
				i++;
				substr = "";
				while (str[i] != '#') {
					substr += str[i];
					i++;
				}
				rv += "&createrange(";
				rv += substr;
				rv += ")";
				i++;
				count++;
				break;
			case '%':
				i++;
				substr = "";
				while (str[i] != '%') {
					substr += str[i];
					i++;
				}
				rv += "&(";
				rv += substr;
				rv += ")";
				i++;
				count++;
				break;
			default:
				rv += str[i];
				i++;
				break;
		}
	}

	rrv = "CREATE(";
	sprintf(ncount, "%i", count);
	rrv += ncount;
	rrv += ", ";
	rrv += rv;
	rrv += ")";

	return rrv;
}


int nrCommas(dpString str) {
    int nr = 0;
    if (str.size() > 2) {
        nr = 1;
        for (int i = 0; i < str.size(); i++) {
            if (str[i] == ',')
                nr++;
        }
    }
    return nr;
}

void compileCcode(char *fname) {
   // open script-file for reading
   FILE *fd = fopen(fname, "rb");
   if (fd != NULL) {
        dpint64 length;
        char *input;
        dpString iinput, name, dispSyntax;
        dpStringList lines;
        int n;
        std::string line;
        int bracket_open, bracket_close;
        int procLength = 4;
        int funcLength = 10;
        int externLength = 11;
        
        // get length of input file
        fseek(fd, 0L, SEEK_END);
        length = ftell(fd);
        fseek(fd, 0L, SEEK_SET);

        input = (char *)calloc(length+1, sizeof(char));
        if (input != NULL) {
            // read script into input-variable
            fread(input, sizeof(char), length, fd);
                
            for (n = 0; n < length; n++) if (input[n] == '\r') input[n] = '\n';
            input[length] = 0;
            iinput = input;
            //iinput = iinput.simplifyWhiteSpace();
            lines = dpStringList::split('\n', iinput);

            // find lines beginning with "extern" -> several functions/procedures in one file possible
            n = 0;
            std::vector<int> linesWhitExtern;
            while (n < lines.size()) {
                    lines[n] = lines[n].simplifyWhiteSpace();
                    if (lines[n].left(6) == "extern") {
                        linesWhitExtern.push_back(n);
		    }
                    n++;
            }
            linesWhitExtern.push_back(lines.size());

            // take first line of each function/procedure, check if it is a function or procedure
            // get numer of arguments, get name then add up all lines beloging to that function (or procedure)
            // an pass this string to flushOutput()
            n = 0;
            dpString actualLine;
            while(n < linesWhitExtern.size() - 1) {
                actualLine = lines[linesWhitExtern[n]];
                dispSyntax = actualLine.mid(externLength, actualLine.size() - externLength - 2);
                bracket_open = dispSyntax.find("(");
                bracket_close = dispSyntax.find(")");
                int nrArgs = nrCommas(dispSyntax.mid(bracket_open, bracket_close - bracket_open + 1));

                if ((dispSyntax.size() > procLength) && (dispSyntax.left(procLength) == "void")) {
                    //procedure
			           name = dispSyntax.mid(procLength + 1, bracket_open - procLength - 1);
			           createInfo(procID, nrArgs, name, dispSyntax);
                }
                else if ((dispSyntax.size() > funcLength) && (dispSyntax.left(funcLength) == "dpuserType")) {
                    //function
                    name = dispSyntax.mid(funcLength + 1, bracket_open - funcLength - 1);
                    createInfo(funcID, nrArgs, name, dispSyntax);
                }
                actualLine += "\n";
                for (int i = linesWhitExtern[n] + 1; i < linesWhitExtern[n + 1]; i++) {
                    actualLine += lines[i];
                    actualLine += "\n"; // add carriage return, has ben removed with simplifyWhitespace()
                }
                flushOutput(name, actualLine);
                n++;
            }
	         free(input);
            fclose(fd);
        } else {
            dp_output(">>> Could not open script-file for reading\n");
        }
    }
}
