Beispiel #1
0
int filewritefln(ub4 fln,int fd, const void *buf,ub4 len,const char *name)
{
  long n;

  if (len == 0) return errorfln(fln,0,FLN,"nil write to %s",name);
  n = oswrite(fd,buf,len);
  if (n == -1) return oserrorfln(fln,0,"cannot write \ah%u bytes to %s",len,name);
  else if (n != (long)len) return errorfln(fln,0,FLN,"partial write \ah%ld of \ah%u bytes to %s",n,len,name);
  else return 0;
}
Beispiel #2
0
zysef()
{
	register struct fcblk *fcb = WA(struct fcblk *);
	register struct ioblk *iob = MK_MP(fcb->iob, struct ioblk *);

	/* ensure the file is open */
	if ( !(iob->flg1 & IO_OPN) )
		return EXIT_1;

	/* write the data, fail if unsuccessful */
	if ( oswrite( fcb->mode, fcb->rsz, ffscblk.len, iob, &ffscblk) != 0 )
		return EXIT_2;

	return NORMAL_RETURN;
}
Beispiel #3
0
function main() {
	var cmd=SENTENCE.substr(2);
	var file,key;
	file.select(cmd);

	var nkeys=0;
	var keys="";
	while (file.readnext(key)) {
		if (nkeys) {
			keys^="\n";
		}
		nkeys++;
		keys^=key;
	}
	var result;
	if (nkeys) {
		oswrite(keys,"sselect.lst");
		printl(nkeys^" record(s) selected");
	} else {
		printl("No records found");
	}
	return nkeys==0;//0=success/1=failure
}
Beispiel #4
0
program()
{
        //hard coded editor at the moment
        //http://www.nano-editor.org/docs.php
        var editor="nano";
//restrict to editing records for now
//#define ALLOW_EDIC
#ifdef ALLOW_EDIC
        if (dcount(COMMAND,FM)<3) {
#else
        if (dcount(COMMAND,FM)<2) {
#endif

                //quit if arguments
                if (dcount(COMMAND,FM)<2)
					abort(
						"Syntax is:"
                        "\nedit databasefilename key ..."
#ifdef ALLOW_EDIC
                        "\nor"
                        "\nedit osfilename"
#endif
					);

                //switch to edic if only one argument
                osshell(COMMAND.replace(1,0,0,"edic").convert(FM," "));
                stop();
        }

        var filename=COMMAND.a(2);
        var key=COMMAND.a(3);

        //connect to the database
        if (not connect())
                stop("Please login");

        //check the file exists
        var file;
        if (not open(filename,file))
                stop("Cannot open file " ^ filename);

        //get the record from the database
        var record;
        if (not read(record,file,key)) {
                //check if exists in upper or lower case
                var key2=key.ucase();
                if (key2 eq key)
                        key2.lcaser();
                if (read(record,file,key2))
                        key=key2;
                else
                        record="";
        }

        //convert to text format
        record.swapper("\\","\\\\");
        record.swapper("\n","\\n");
        record.swapper(FM,"\n");

        //put the record on a temp file in order to edit it
        var temposfilename=filename^ "~" ^ key;
        var invalidfilechars=L"\"\'\u00A3$%^&*(){}[]:;#<>?,./\\|";
        temposfilename.converter(invalidfilechars,str("-",len(invalidfilechars)));
        temposfilename^=".tmp";
        oswrite(record,temposfilename);

        //record file update timedate
        var fileinfo=osfile(temposfilename);
        if (not fileinfo)
                abort("Couldnt write local copy for editing "^temposfilename);

        //fire up the editor
        var editcmd=editor ^ " " ^ temposfilename.quote();
        printl(editcmd);
        osshell(editor ^ " " ^ temposfilename);

        //if the file has been updated
        var fileinfo2=osfile(temposfilename);
        if (fileinfo2 eq fileinfo) {
                //file has not been edited
                osdelete(temposfilename);
        } else {
                //file has been edited
                var record2;
                osread(record2,temposfilename);

                //remove trailing lf or cr or crlf
                trimmerb(record2,"\r\n");

                //convert to record format
                record2.swapper("\n",FM);
                record2.swapper("\\n","\n");
                record2.swapper("\\\\","\\");

                if (record2 ne record) {

                        //print("Ok to update? ");
                        //var reply=inputl();
                        var reply="Y";

                        //keep trying to update - perhaps futilely
                        //at least temp file will be left in the directory
                        while (ucase(reply)[1] eq "Y" and true) {

                                if (write(record2,file,key)) {
                                        printl(filename^" written "^key);
                                        osdelete(temposfilename);
                                        break;
                                }
                                var temp;
                                temp.input();

                        }
                }
        }
}
Beispiel #5
0
function main(in mode, in select, in nfilters, dim& filters) {

	if (false && mode && select && nfilters && filters(0,0)){};

	var filename = SENTENCE.field(" ", 2);
	var file;
	if (not(file.open(filename))) {
		return fsmsg();
	}

	var sentencex = SENTENCE;
	sentencex.converter(" ", VM);
	if (sentencex.locate("SELECT", temp, 1)) {
		selectx = SENTENCE.field(" ", temp + 1, 9999);
		sentencex = SENTENCE.field(" ", 1, temp - 1);
	}else{
		sentencex = SENTENCE;
		selectx = "";
	}

	var normalise = sentencex.index(" NORMALISE", 1);
	if (normalise) {
		sentencex.swapper(" NORMALISE", "");
	}

	var raw = sentencex.index(" RAW", 1);
	if (raw) {
		sentencex.swapper(" RAW", "");
	}
	var mvgroupno = "";

	var colheaderrow = not sentencex.index(" NOCOLHEADER", 1);
	if (not colheaderrow) {
		sentencex.swapper(" NOCOLHEADER", "");
	}

	if (filename.substr(1,4) == "DICT") {
		tt = "VOC";
	}else{
		tt = filename;
	}
	if (not(DICT.open("dict_"^tt))) {
		return fsmsg();
	}

//	var converter = "";
//	if (not((tt!!!).read(DEFINITIONS, "CONVERTER*" ^ filename))) {
//		tt!!! = "";
//	}
//	if (tt!!!.a(1)) {
//		converter = "CONVERTER." ^ tt!!!.a(1);
//	}

	var xx;
	if (xx.read(DICT, "AUTHORISED")) {
		dicthasauthorised = 1;
	}else{
		dicthasauthorised = 0;
	}

	var notexportable = "";
	var exportable = sentencex.field(" ", 3, 9999);
	if (exportable) {
		exportable.converter(" ", FM);
		if (exportable.a(1) == "EXCEPT") {
			notexportable = exportable.field(FM, 2, 9999);
			exportable = "";
		}
	}

	//expand any group fields in notexportable
	if (notexportable) {
		for (var ii = 1; ii <= notexportable.count(FM) + 1; ++ii) {
			var dictrec;
			if (dictrec.read(DICT, notexportable.a(ii))) {
				if (dictrec.a(1) == "G") {
					temp = dictrec.a(3);
					temp.converter(VM ^ " ", FM ^ FM);
					notexportable.r(ii, temp);
				}
			}
		};//ii;
	}

	var listkey = var(1000000).rnd();

	if (not exportable) {

		if (exportable.read(DICT, "exportable")) {
			if (exportable.a(1) == "G") {
				exportable = exportable.a(3);
				exportable.converter(VM ^ " ", FM ^ FM);
			}
			keyx = exportable.substr(1,exportable.index(FM ^ FM, 1) - 1);
			nkeys = keyx.count(FM) + 1;
			if (nkeys > 2) {
				//call msg('Key field(s) should be followed by a blank line or space in EXPORTABLE')
				//stop
				nkeys = 0;
			}
		}else{
			exportable = "";
			keyx = "";
		}

	}

	var exportable2 = exportable;

//nextmvgroup:

	if (mvgroupno) {
		tt = keyx ^ FM ^ "LINE_NO" ^ FM;
	}else{
		tt = "";
	}

	exportable = tt ^ exportable2.field("%", 1);
	exportable2 = exportable2.field("%", 2, 9999);

	outfilename = SYSTEM.a(2);
	//zzz if mvgroupno then outfilename[8,1]=mvgroupno
	if (outfilename.lcase().substr(-4, 4) == ".htm") {
		outfilename.splicer(-3, 3, "xls");
		SYSTEM.r(2, outfilename);
	}

	var excel = outfilename.lcase().substr(-3, 3) == "xls";

//retry:
	outfilename.osdelete();
	if (outfilename.osfile()) {
		return exit2("CANNOT EXPORT BECAUSE " ^ outfilename ^ " IS ALREADY|OPEN IN ANOTHER PROGRAM, OR CANNOT BE ACCESSED");
	}

	//call note2("Exporting " ^ outfilename ^ "||Please wait ...", "UB", buffer, "");

	files.redim(255);
	filenames.redim(255);
	oconvxs.redim(255);
	fmtxs.redim(255);
	dictrecs.redim(255);
	filenames="";
	oconvxs="";
	fmtxs="";
	var nfields = 0;
	
	var selectlist = LISTACTIVE;
	if (selectlist) {
		savelistactive=LISTACTIVE;
	}

	if (exportable) {
		//call makelist("", exportable, "", "");
		//write exportable on lists,listkey
		//perform 'GET-LIST ':listkey:' (S)'
		//delete lists,listkey
		var tt="select dict_" ^ filename ^ " " ^ exportable.swap(FM, "\" \"").quote();
		DICT.select(tt);

	}else{
		if (filename.substr(1,4).lcase() == "dict") {
			dict = "";
		}else{
			dict = "dict_";
		}
		DICT.select("select " ^ dict ^ filename ^ " BY FMC WITH FMC BETWEEN 1 AND 999999 AND WITH @ID NOT STARTING \'%\' AND WITH MASTER.FLAG (S)");
		if (not LISTACTIVE) {
			return exit2(dict ^ filename ^ " has no exportable columns");
		}
	}

	dictids.redim(255);
	colgroups.redim(255);

	dictids = "";
	colgroups = "";
	var headingx = "";
	var coln = 0;

	var dictid;
	while (DICT.readnext(dictid, MV)) {

		if (notexportable.locateusing(dictid, FM, xx)) {
			continue;
		}

		if (dictid[1] == "%") {
			continue;
		}

		if (dictid == "LINE_NO") {
			coln += 1;
			dictids(coln) = dictid;
			headingx.r(coln, dictid);
			fmtxs(coln) = "R";
			dictrecs(coln) = "";
		}else{
			if (dict.read(DICT, dictid)) {
//				call dicti2a(dict);
				coln += 1;
				//if dict<2> matches '0N' then
				var fn = dict.a(2);
				if (fn > nfields) {
					nfields = fn;
				}

				fmtxs(coln) = dict.a(9)[1];

				if (raw) {
					headingx.r(coln, dictid);
				}else{

					//extract title
					var title = dict.a(3).trim();
					title.swapper("<WBR/>", "");
					title.swapper("<wbr/>", " ");
					title.converter(UPPERCASE ^ "|_" _VM_ "", LOWERCASE ^ "   ");

					//t=title[1,1]
					//convert @lower.case to @upper.case in t
					//title[1,1]=t
					title = capitalise(title);

					title.swapper("(Base)", "(" ^ gen.company.a(3) ^ ")");

					//swap ' code' with '' in title

					headingx.r(coln, title.trim());
				}

				//extract file
				if (dict.a(11)[1] == "<") {
					temp = dict.a(11).substr(2,9999).field(">", 1);
					filenames(coln) = temp;
					if (not(files(coln).open(temp, ""))) {
						return exit2(DQ ^ (temp ^ DQ) ^ " file cannot be found in dict " ^ (DQ ^ (dictid ^ DQ)));
					}
					var title = headingx.a(coln);
					if (title.ucase().substr(-5,5) == " CODE") {
						title.splicer(-5, 5, "");
						headingx.r(coln, title);
					}
				}

				//extract conversion
				if (dict.a(7)) {
					var oconvx = dict.a(7);

					//force long date format
					if (oconvx.index("DATE", 1) or oconvx[1] == "D") {
						//if raw then
						// oconvx='D4/J'
						//end else
						if (oconvx == "[SCH.DATES]") {
							oconvx = "";
						}else{
							oconvx = "D4/E";
						}
						//end
					}

					oconvxs(coln) = oconvx;
				}

				colgroups(coln) = dict.a(4)[1] == "M";
				dictids(coln) = dictid;
				dictrecs(coln) = dict;

			}
			//end
		}
	}//nextdict
	var ncols = coln;

	//if @username='******' then oswrite matunparse(dictids) on 'csv'

	if (selectlist) {
		LISTACTIVE=savelistactive;
	}

	call oswrite("", outfilename);
	if (not outfile.osopen(outfilename)) {
		return exit2(outfilename.quote()^" file cannot be created");
	}
	var ptr = 0;

	//suppress headerrow if not required
	if (not colheaderrow) {
		headingx = "";
	}

	if (selectx) {
	//selectx:=' AND WITH PERSON_CODE "HARRIS"'
		//perform 'SELECT ':filename:' ':selectx
		tt = "SELECT " ^ filename ^ " " ^ selectx;
		//call xselect(tt);
		file.select(tt);
/*		if (not LISTACTIVE) {
			outfile.osclose();
			outfilename.osdelete();
			return exit2("No records found");
		}
*/
	}else{
		if (not LISTACTIVE) {
			file.select();
		}
	}

	var recn = 0;

	rec.redim(ncols);
	mvrec.redim(ncols);

/////
//nextrecord:
/////

	//get the next key and mv
	var mvx;
	while (file.readnext(ID, mvx)) {

		//user interrupt
		if (esctoexit()) {
			outfile.osclose();
			//osdelete outfilename
			return exit2("Interrupted by User");
		}

		//skip "" key
		if (ID == "") {
			continue;
		}

		recn += 1;

		//cout << AW.a(30)<< var().cursor(0)<< var().cursor(-4);
		//cout << var().cursor(39, _CRTHIGH / 2)<< recn<< ". ";

		//get the record
		if (not(RECORD.read(file, ID))) {
			continue;
		}

		//skip record if not authorised
		if (dicthasauthorised and not calculate("AUTHORISED")) {
			continue;
		}

		//skip zero hours in timesheets
		//TODO get this hack into a special dictionary item like LIMIT
		if (filename == "TIMESHEETS" and mvx and not RECORD.a(2, mvx)) {
			continue;
		}
		
		//get the data and work out maximum vn
		mvrec = "";
		var maxvn=0;
		for (var coln = 1; coln <= ncols; ++coln) {

			dictid = dictids(coln);
			if (dictid eq "LINE_NO")
				continue;

			MV = mvx;
			var cell = calculate(dictid);
			if (not cell.length())
				continue;
				
			if (oconvxs(coln)) {
				cell = cell.oconv(oconvxs(coln));
			}

			mvrec(coln) = cell;

			var temp = cell.dcount(VM);
			if (temp > maxvn)
				maxvn = temp;
				
		}

		//skip if no data
		if (not maxvn)
			continue;

		//normalise the data and output to csv file
		
		//output the lines
		for (var vn=1; vn <= maxvn; ++vn) {

			rec="";
					
			//conversions
			for (var coln = 1; coln <= ncols; ++coln) {

				var cell;
				
				if (dictids(coln) == "LINE_NO") {
					cell = vn;

				//select right multivalue if multivalued field/column
				//non-multivalued fields/columns are repeated on every line
				}else if (colgroups(coln)) {
						cell=mvrec(coln).a(1,vn);
						
				//not multivalued so repeat on every line
				} else {
						cell = mvrec(coln);
				}
								
				//skip empty cells
				if (not cell.length())
					continue;

				//conversions
				if (mvx or vn == 1) {

					//convert codes to names
					if (filenames(coln) and not raw) {
						var rec2;
						if (rec2.read(files(coln), cell)) {
							if (filenames(coln) == "BRANDS") {
								cell = rec2.a(2, 1);
							}else{
								cell = rec2.a(1);
							}
						}
					}

				}

				//remove any initial + sign - on numbers only
				if (cell[1] == "+") {
					if ((cell.substr(2,9999)).isnum()) {
						cell.splicer(1, 1, "");
					}
				}
				
				//a single double quote gets changed to ''
				if (cell == DQ) {
					cell = "\'\'";
				}
				
				//swap double quotes for '' unless already double quoted
				if (cell[1] ne DQ or cell[-1] ne DQ) {
					cell.swapper(DQ, "\'\'");
				}
				
				//WARNING prevent cell length more than 255
				if (cell.length() > 255) {
					cell = cell.substr(1,250) ^ " ...";
				}
				
				//double quote non-numerics
				if (fmtxs(coln) ne "R") {

					//make sure "1-12" is not interpreted as a formula (by prefixing a space?)
					if (1 or excel) {
						if (var(".-+0123456789").index(cell[1])) {
							if (not cell.isnum()) {
								cell.splicer(1, 0, " ");
							}
						}
					}

					//convert any existing double quotes to '' for T columns which are not already double quoted
					if (cell.index(DQ, 1)) {
						if (fmtxs(coln) == "T") {
							if (cell[1] ne DQ or cell[-1] ne DQ) {
								cell.swapper(DQ, "\'\'");
								cell = DQ ^ (cell ^ DQ);
							}
						}
					//otherwise just double quote stuff
					}else{
						cell = DQ ^ (cell ^ DQ);
					}

				}

				rec(coln) = cell;

			};//coln;

			var line = rec.unparse();
			
			//remove trailing or all tab chars
			line.trimmerb(FM);

			//suppress output of empty amv rows
			if (mvgroupno and nkeys) {
				if (line.field(FM, nkeys + 2, 9999) == "") {
					line = "";
				}
			}

			//output one line
			if (not line.length())
				continue;

			//remove leading equal signs in order not to confuse Excel
			line.swapper(FM ^ "=", FM);

			//output header row if first line and not suppressed

			if (headingx) {

//				if (converter) {
//					//headingx will come back converted and maybe as multiple lines
//					//converterparams initially contains first line so heading can put some columns into heading if required
//					//converterparams comes back with info to speed convertion of lines
//					converterparams = line;
//					call onverter("HEAD", headingx, converterparams, filename);
//				}else{
					headingx.converter(FM, var().chr(9));
					headingx ^= "\r\n";
//				}

				osbwrite(headingx, outfile, ptr);

				headingx = "";
			}

			//output line

//			if (converter) {
//				call @converter("LINE", line, converterparams, filename);
//			}else{
				line.swapper(FM, var().chr(9));
				line ^= "\r\n";
//			}

			osbwrite(line, outfile, ptr);

		}//next vn

	}//goto nextrecord
	
/////
//exit:
/////
	outfile.osclose();
//	call uconvfile(outfile, "CODEPAGE", "UTF16", result, errors);
	//general result code
	SYSTEM.r(34, 1);
	
//exit3:
//	if (raw and exportable2) {
//		mvgroupno += 1;
//		if (mvgroupno == 1) {
//			mvgroupno = 2;
//		}
//		goto nextmvgroup;
//	}
	return 1;
}
Beispiel #6
0
program()
{

    //check command syntax
    //edit filename
    if (dcount(COMMAND,FM)<2)
        abort("Syntax is 'edic osfilename'");

    var verbose=OPTIONS.ucase().index("V");

    var editor=osgetenv("VISUAL");
    var linenopattern="$LINENO ";
    if (not editor)
        editor.osgetenv("EDITOR");

    //TODO simplify this editor finding code

    //enable edit at first error for crimson editor (no quotes around filename for cedt)
    if (editor.lcase().index("cedt") and not editor.index("$") )
        editor^=" /L:$LINENO $FILENAME";

    //look for installed nano
    //if (SLASH eq "\\" and not index(PLATFORM_,"x64")) {
    var nanopath="";
    if (SLASH eq "\\") {

        //look for nano.exe next to edic.exe
        if (not editor)
            nanopath=EXECPATH.swap("edic","nano");
        if (nanopath.osfile())
            editor="nano $LINENO'$FILENAME'";
    }

    //look for nano in parent bin
    if (not editor) {
        nanopath="..\\bin\\nano.exe";
        if (nanopath.osfile())
            editor="nano $LINENO'$FILENAME'";
    }

    //look for nano in release directory during exodus development
    if (not editor) {
        nanopath="..\\..\\release\\cygwin\\bin\\nano.exe";
        if (nanopath.osfile())
            editor="..\\..\\release\\cygwin\\bin\\nano $LINENO'$FILENAME'";
        else {
            nanopath="..\\"^nanopath;
            if (nanopath.osfile())
                editor="..\\..\\..\\release\\cygwin\\bin\\nano $LINENO'$FILENAME'";
        }
    }

    if (editor.index("nano"))
        linenopattern="+$LINENO ";

    //otherwise on windows try to locate CYGWIN nano or vi
    var cygwinpath="";
    if (not editor and SLASH eq "\\") {
        //from environment variable
        cygwinpath=osgetenv("CYGWIN_BIN");
        //else from current disk
        if (not cygwinpath)
            cygwinpath="\\cygwin\\bin\\";
        //else from c:
        if (not osdir(cygwinpath))
            cygwinpath="c:\\cygwin\\bin\\";
        //else give up
        if (not osdir(cygwinpath))
            cygwinpath="";

        if (cygwinpath and cygwinpath[-1] ne SLASH)
            cygwinpath^=SLASH;
        //editor=cygwinpath^"bash --login -i -c \"/bin/";
        editor=cygwinpath;
        if (osfile(cygwinpath^"nano.exe") or osfile("nano.exe")) {
            editor="nano $LINENO'$FILENAME'";
            if (osfile(cygwinpath^"nano.exe"))
                editor.splicer(1,0,cygwinpath);
            //editor^="\"";
            linenopattern="+$LINENO ";
        } else if (osfile(cygwinpath^"vi.exe") or osfile("vi.exe")) {
            editor="vi -c \":$LINENO\" $FILENAME";
            if (osfile(cygwinpath^"vi.exe"))
                editor.splicer(1,0,cygwinpath);
            //editor^="\"";
        } else
            editor="";
    }
    if (SLASH eq "\\") {
        //configure nanorc (on windows)
        //TODO same for non-windows
        //nano on windows looks for nanorc config file as follows (probably merges all found)
        //C:\cygwin\usr\local\etc\nanorc
        //C:\cygwin\etc\nanorc (only if cygwin exists)
        //C:\Documents and Settings\USERNAME\.nanorc  ($HOMEDRIVE$HOMEPATH)
        var nanorcfilename;
        if (cygwinpath) {
            nanorcfilename=cygwinpath.field(SLASH,1,dcount(cygwinpath,SLASH)-2) ^ SLASH ^ "etc" ^ SLASH ^ "nanorc";
        } else {
            nanorcfilename=osgetenv("HOME");
            if (not nanorcfilename)
                nanorcfilename=osgetenv("HOMEDRIVE") ^ osgetenv("HOMEPATH");
            if (nanorcfilename[-1] ne SLASH)
                nanorcfilename^=SLASH;
            nanorcfilename^=".nanorc";
        }
        if (not osfile(nanorcfilename)) {
            //var nanorctemplatefilename=EXECPATH.field(SLASH,1,dcount(EXECPATH,SLASH)-1) ^ SLASH ^ "nanorc";
            var nanorctemplatefilename=nanopath.field(SLASH,1,dcount(nanopath,SLASH)-1) ^ SLASH ^ "nanorc";
            if (not osfile(nanorctemplatefilename))
                nanorctemplatefilename.swapper("release","..\\release");
            //if (not osfile(nanorctemplatefilename))
            //	nanorctemplatefilename.swapper("release","..\\"^PLATFORM_^"\\release");
            if (oscopy(nanorctemplatefilename,nanorcfilename)) {
                printl("Copied " ^ nanorctemplatefilename.quote() ^ " to " ^ nanorcfilename.quote());
                var ().input("Note: nano c++ syntax highlighting has been installed. Press Enter ... ");
            } else {
                errputl("Could not copy " ^ nanorctemplatefilename.quote() ^ " to " ^ nanorcfilename.quote());
                if (not osfile(nanorctemplatefilename))
                    errputl("nano syntax highlighting file is missing.");
            }
        }
        if(not osgetenv("HOME"))
            ossetenv("HOME",osgetenv("HOMEDRIVE") ^ osgetenv("HOMEPATH"));
    }

    if (not editor) {
        if (SLASH eq "/")
            editor="nano ";
        else
            editor="notepad";
        printl("Environment EDITOR not set. Using " ^ editor);
    }

    //editor="vi";
    editor.swapper("nano ", "nano --const --nowrap --autoindent --suspend ");

    if (editor.index("nano"))
        printl("http://www.nano-editor.org/dist/v2.1/nano.html");

    //configure nano syntax highlighting
    var filenames=field(COMMAND,FM,2,99999);
    var nfiles=dcount(filenames,FM);
    var filen=0;
    while (filen<nfiles) {
        filen+=1;
        var filename=filenames.a(filen).unquote();

        //split out trailing line number after :
        var startatlineno=field(filename,":",2);
        if (startatlineno.isnum())
            filename=field(filename,":",1);
        else
            startatlineno="";

        filename.trimmerb(".");
        if (not index(field2(filename,SLASH,-1),"."))
            filename^=".cpp";

        var iscompilable=filename.field2(".",-1)[1].lcase() ne "h";

        //make absolute in case EDITOR changes current working directory
        var editcmd=editor;
        if (editcmd.index("$ABSOLUTEFILENAME")) {
            editcmd.swapper("$ABSOLUTEFILENAME","$FILENAME");

            filename=oscwd()^SLASH^filename;
        }
        //prepare a skeleton exodus cpp file
        var newfile=false;
        if (iscompilable and not osfile(filename)) {

            var basefilename=field2(filename,SLASH,-1);
            basefilename=basefilename.field(".",dcount(basefilename,".")-1);

            var progtype;
            var question="1=Normal Program, 2=External Subroutine or Function";
            //question^="\n3=main(), 4=simple so/dll\n";
            question^="\n"^basefilename.quote()^" does not exist. Create what? (1-2) ";
            while (true) {
                if (basefilename.substr(1,5).lcase() eq "dict_")
                    progtype=5;
                else
                    progtype.input(question);
                if (progtype eq 2)
                    progtype="classlib";
                else if (progtype eq 3)
                    progtype="main";
                else if (progtype eq 4)
                    progtype="mainlib";
                else if (progtype eq 1)
                    progtype="class";
                else if (progtype eq 5)
                    progtype="dict";
                else
                    stop();
                break;
            }

            newfile=true;
            var blankfile="";
            if (progtype eq "main" or progtype eq "mainlib") {
                startatlineno="4,9";
                blankfile^="#include <exodus/exodus.h>\n";
                blankfile^="\n";
                blankfile^="program() {\n";
                blankfile^="\tprintl(\""^basefilename^" says 'Hello World!'\");\n";
                if (progtype eq "mainlib")
                    blankfile^="\treturn 0;\n";
                blankfile^="}\n";
                if (progtype eq "mainlib")
                    blankfile.swapper("program()","function "^basefilename^"()");
            } else if (progtype eq "class" or progtype eq "classlib") {
                startatlineno="6,9";
                blankfile^="#include <exodus/program.h>\n";
                //programinit() as 2nd line to avoid ppl in external functions before programinit
                //blankfile^="\n";
                blankfile^="programinit()\n";
                blankfile^="\n";
                blankfile^="function main(";
                //the .h maker not able to parse this yet and is rather clumsy anyway
                //if (progtype eq "classlib")
                //	blankfile^="/*in arg1, out arg2*/";
                blankfile^=") {\n";
                blankfile^="\tprintl(\""^basefilename^" says 'Hello World!'\");\n";
                blankfile^="\treturn 0;\n";
                blankfile^="}\n";
                blankfile^="\nprogramexit()";
                blankfile^="\n";

                if (progtype eq "classlib")
                    blankfile.swapper("program","library");
            } else if (progtype eq "dict") {
                startatlineno="6,9";
                blankfile^="#include <exodus/dict.h>\n\n";
                //programinit() as 2nd line to avoid ppl in external functions before programinit
                //blankfile^="\n";
                blankfile^="dict(EXAMPLEDICTID1) {\n";
                blankfile^="\tANS=RECORD(1)^\"x\";\n";
                blankfile^="}\n\n";

                blankfile^="dict(EXAMPLEDICTID2) {\n";
                blankfile^="\tANS=RECORD(2)^\"x\";\n";
                blankfile^="}\n";

            }

            if (blankfile[1] ne "\n")
                blankfile^="\n";
            if (SLASH ne "/")
                blankfile.swapper("\n","\r\n");

            if (not oswrite(blankfile,filename))
                stop("Cannot create "^filename^". Invalid file name, or no rights here.");
            //      startatlineno="4,9";
            //startatlineno="";
        }

        var editcmd0=editcmd;
        var linenopattern0=linenopattern;

        //keep editing and compiling until no errors
        while (true) {

            editcmd=editcmd0;
            linenopattern=linenopattern0;

            //record the current file update timestamp
            var fileinfo=osfile(filename);

            //build the edit command
            if (editcmd.index("$LINENO")) {
                if (not startatlineno)
                    linenopattern="";
                else
                    linenopattern.swapper("$LINENO",startatlineno.field(",",1));
                editcmd.swapper("$LINENO",linenopattern);
            }
            if (editcmd.index("$FILENAME"))
                editcmd.swapper("$FILENAME",filename);
            else
                editcmd ^= " " ^ filename;

            //call the editor
            if (verbose)
                printl(editcmd);
            osshell(editcmd);

            //if the file hasnt been updated
            var fileinfo2=osfile(filename);
            if (fileinfo2 ne fileinfo)
                newfile=false;
            else {
                //delete the skeleton
                printl("File unchanged. Not saving.");
                if (newfile)
                    osdelete(filename);
                //move to the next file
                break;
            }

            //clear the screen (should be cls on win)
            if (SLASH eq "/")
                osshell("clear");
            //else
            //	osshell("cls");

            if (not iscompilable)
                break;

            //build the compiler command
            var compiler="compile";
            var compileoptions="";
            var compilecmd=compiler ^ " " ^ filename.quote() ^ compileoptions;
            //capture the output
            var compileoutputfilename=filename ^ ".2";
            if (SLASH eq "/")
                compilecmd ^= " 2>&1 | tee " ^ compileoutputfilename.quote();
            else
                compilecmd ^= " > " ^ compileoutputfilename.quote() ^ " 2>&1";

            //call the compiler
            if (verbose)
                printl(compilecmd);
            osshell(compilecmd);

            //var tt;
            //tt.inputl("Press Enter ...");

            //if any errors then loop back to edit again
            var errors;
            if (osread(errors,compileoutputfilename)) {
                osdelete(compileoutputfilename);

                if (SLASH ne "/")
                    print(errors);

                startatlineno="";
                var charn;
                //gnu style error lines
                if (charn=index(errors, ": error:")) {
                    startatlineno=errors.substr(charn-9,9);

                    //printl(startatlineno);
                    startatlineno=startatlineno.field2(":",2);
                    //printl(startatlineno);
                    //msvc style error lines
                    //test.cpp(6) : error C2143: syntax error : missing ';' before '}'
                } else if (charn=index(errors,") : error ")) {
                    startatlineno=errors.substr(charn-10,10).field2("(",2);
                }
                if (startatlineno) {
                    print("Press any key to re-edit at line "^startatlineno^" ... ");
                    var().input("");
                    continue;
                }
            }

            break;
        }

    }
}