############################################################################ # # File: based.icn # # Subject: Program to do BASIC-style editing # # Author: Chris Tenaglia # # Date: February 18, 1996 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program models a line editor for BASIC. # ############################################################################ global chars,program,cmd,token,name procedure main(param) local ff, old if find("p",map(param[1])) then ff := "\014" else ff := "\e[2J\e[H" chars := &cset -- '\t ' program := list() name := &null write("Basic Line Editor V1.3 by Tenaglia 910104.1700") write(&host," ",&dateline,"\n") repeat { writes(">") (cmd := read()) | { quit() ; next } if cmd == "!!" then { cmd := old write("> ",cmd) } token := parse(cmd) if integer(token[1]) then { entry(token[1]) token[1] := "" } old := cmd #EJECT case map(token[1]) of { "" : "ignore this case" "load" : write(load()) "save" : write(save()) "resave" : write(resave()) "read" : write(basread()) "write" : write(baswrite()) "merge" : write(merge()) "new" : write(new()) "list" : write(print()) "renum" : write(renum()) "del" : write(del()) "dir" : write(dir()) "size" : write("Buffer contains ",*program," lines.") "find" : write(search()) "cls" : write(ff) "compile": write(compile()) "build" : write(build()) "test" : write(build(),run()) "run" : write(run()) "ver" : write("Basic Line Editor V1.3 by Tenaglia 910104.1700") "date" : write(&host," ",&dateline) "time" : write(&host," ",&dateline) "help" : write(help()) "?" : write(help()) "$" : write(shell()) "exit" : break "quit" : break default : write("\007What ?") } } write("Returning to operating system") write(&host," ",&dateline) end procedure quit() # allows CTRL_Z exit under VMS local test writes("QUIT! Are you sure? Y/N :") (test := read()) | stop("Returning to operating system\n",&host," ",&dateline) if map(test)[1] == "y" then stop("Returning to operating system\n",&host," ",&dateline) return end #SUB LOAD, SAVE, AND RESAVE COMMANDS #EJECT procedure load() local file, in, lnum if not(token[2]) then { writes("_file:") if (file := string(read())) == "" then return } else file := token[2] lnum := 0 (in := open(file)) | return ("Can't open " || file) name := file program := [] while put(program,((lnum+:=10) || " " || read(in))) do not(find("00",lnum)) | (writes(".")) close(in) return ("\n" || file || " loaded.") end procedure save() local file, i, line, lnum, out, text if not(token[2]) then { writes("_file:") if (file := string(read())) == "" then return } else file := token[2] (out := open(file,"w")) | return ("Can't open " || file) name := file every line := !program do { i := upto(' \t',line) lnum := line[1:i] text := line[i+1:0] write(out,text) not(find("00",lnum)) | (writes(".")) } close(out) return ("\n" || file || " saved.") end procedure resave() local i, line, lnum, out, text if not(string(name)) then return("Nothing LOADed to resave.") (out := open(name,"w")) | return ("Can't open " || name) every line := !program do { i := upto(' \t',line) lnum := line[1:i] text := line[i+1:0] write(out,text) not(find("00",lnum)) | (writes(".")) } close(out) return ("\n" || name || " resaved.") end #SUB READ, WRITE, AND MERGE COMMANDS #EJECT procedure basread() local file, in, line, lnum, test if not(token[2]) then { writes("_file:") if (file := string(read())) == "" then return } else file := token[2] lnum := 0 (in := open(file)) | return ("Can't open " || file) name := file program := [] while line := read(in) do { test := (line[1:upto(' \t',line)]) | "" if integer(test) then put(program,line) not(find("00",(lnum+:=10))) | (writes(".")) } close(in) return ("\n" || file || " read in.") end procedure baswrite() local file, lnum, out if not(token[2]) then { writes("_file:") if (file := string(read())) == "" then return } else file := token[2] (out := open(file,"w")) | return ("Can't open " || file) name := file ; lnum := 0 every write(out,!program) do not(find("00",(lnum+:=10))) | (writes(".")) close(out) return ("\n" || file || " writen out.") end procedure merge() local file, i, in, line, lnum if not(token[2]) then { writes("_file:") if (file := string(read())) == "" then return } else file := token[2] (in := open(file)) | return ("Can't open " || file) every line := !in do { (lnum := integer(line[1:(i:=upto(' \t',line))])) | next cmd := line entry(lnum) not(find("00",lnum)) | writes(".") } close(in) return (file || " merged in current buffer.") end #SUB DIR, DEL, AND NEW COMMANDS #EJECT procedure dir() local spec spec := (token[2]) | ("") if &host == "MS-DOS" then { system(("dir/w " || spec)) return "" } if find("nix",map(&host)) then system(("ls -l " || spec || " | more")) else system(("dir " || spec)) return "" end procedure del() local From, To, element, lnum, num, other if (From := integer(token[2])) & (To := integer(token[3])) then { other := [] every element := !program do { lnum := element[1:upto(' \t',element)] if (lnum >= From) & (lnum <= To) then next put(other,element) } program := copy(other) return ("Lines " || From || " - " || To || " deleted.") } if not(num := integer(token[2])) then { writes("_line:") (num := integer(read())) | (return ("Not a line number.")) } other := [] every element := !program do { lnum := element[1:upto(' \t',element)] if lnum = num then next put(other,element) } program := copy(other) return ("Line " || num || " deleted.") end procedure new() program := [] name := &null return ("Buffer cleared.") end #SUB FIND COMMAND #EJECT procedure search() local From, To, delta, diff, i, item, j, k, l, line, lnum if (From := token[2]) & (To := token[3]) then { diff := (*token[3]) - (*token[2]) every i := 1 to *program do { line := program[i] l := upto(' \t',line) + 1 delta:= 0 every j := find(From,line,l) do { k := j + delta line[k+:*From] := "" line[((k-1)|(1))] ||:= To delta +:= diff writes(".") } program[i] := line } return "" } if not(item := token[2]) then { writes("_string:") if (item := read()) == "" then return "" } every i := 1 to *program do { line := program[i] l := upto(' \t',line) + 1 if find(item,line,l) then { lnum := line[1:l-1] writes(lnum,",") } } return "" end #SUB COMPILATION AND RUNNING ROUTINES #EJECT procedure compile() # compile only local fid, opt local i, ext, command, val find(".",name) | return "Can't compile! Language &or Filename not recognized" i := last(".",name) fid := map(name[1:i]) ext := map(name[i:0]) command := case ext of { ".icn" : "icont -c " || name ".c" : "cc " || opt || " " || name ".f" : "f77 "|| opt || " " || name ".asm" : "asm "|| opt || " " || name ".p" : "pc " || opt || " " || name ".for" : "fortran " || name ".bas" : "basic " || name ".cob" : "cobol " || name ".mar" : "macro " || name ".pas" : "pascal " || name default: return "Can't compile! Language &or Filename not recognized" } write("Issuing -> ",command) val := system(command) return " Completion Status = " || val end procedure build() # compile and link local i, ext, command, val1, val2, fid find(".",name) | return "Can't compile! Language &or Filename not recognized" i := last(".",name) fid := map(name[1:i]) ext := map(name[i:0]) command := case ext of { ".icn" : ["icont " || name] ".c" : ["cc " || name] ".f" : ["f77 " || name] ".asm" : ["asm " || name] ".p" : ["pc " || name] ".for" : ["fortran " || name, "link " || fid] ".bas" : ["basic " || name, "link " || fid] ".cob" : ["cobol " || name, "link " || fid] ".mar" : ["macro " || name, "link " || fid] ".pas" : ["pascal " || name, "link " || fid] default: return "Can't compile! Language &or Filename not recognized" } write("Issuing -> ",command[1]) val1 := system(command[1]) val2 := if *command = 2 then { write("And Issuing -> ",command[2]) system(command[2]) } else -1 return " Completion status = " || val1 || " and " || val2 end procedure run() # run built ware local i, ext, command, val, fid find(".",name) | return "Can't compile! Language &or Filename not recognized" i := last(".",name) fid := map(name[1:i]) ext := map(name[i:0]) command := case ext of { ".icn" : "iconx " || fid ".c" : fid ".f" : fid ".asm" : fid ".p" : fid ".com" : "@" || name ".for" : "run " || fid ".bas" : "run " || fid ".cob" : "run " || fid ".mar" : "run " || fid ".pas" : "run " || fid default: return "Can't Run ! Language &or Filename not recognized" } write("Issuing -> ",command) val := system(command) return " Completion status = " || val end #SUB LIST AND RENUM COMMANDS #EJECT procedure print() local From, To, items, line if *token = 1 then { every write(!program) return "" } if not(numeric(token[2])) then return proc_list() From := integer(token[2]) To := integer(token[3]) if not(integer(To)) then { every line := !program do { items := parse(line) if items[1] > From then return "" if items[1] = From then { write(line) return "" } } return "" } every line := !program do { items := parse(line) if items[1] < From then next if items[1] > To then return "" write(line) } return "" end # procedure proc_list() local flag, line flag := 0 every line := !program do { if find("procedure",line) & find(token[2],line) then flag := 1 if flag = 1 then write(line) if (parse(line)[2] == "end") & (flag = 1) then { write("") flag := 0 } } return "" end # procedure renum() local inc, line, lnum, other (lnum := integer(token[2])) | (lnum := 10) (inc := integer(token[3])) | (inc := 10) other := list() every line := !program do { line[1:upto(' \t',line)] := lnum put(other,line) not(find("00",lnum)) | (writes(".")) lnum +:= inc } program := copy(other) return ("\nProgram renumbered.") end #SUB ON LINE HELP DISPLAY #EJECT procedure help() write("Basic Line Editor V1.3 by Tenaglia") write(" This editor works on the same principle as basic interpreter") write(" environments. The lines are all prefixed with line numbers.") write(" These line numbers are used to reference lines in the file.") write(" The line numbers are not written to, or read from the file.") write(" This editor is designed to work on a hard copy terminal like") write(" a teletype or decwriter as well as a crt.") write("Command Summary : (parameters are space delimited)") write(" NEW - erase buffer | CLS - clear screen or form feed") write(" LOAD file - load file | SAVE file - save file") write(" READ file - read w/line numbers | WRITE file - write w/line numbers") write(" RESAVE - resave current file | MERGE file - insert w/line numbers") write(" DIR [spec]- list directory | SIZE - lines in editing buffer") write(" RENUM - renumber the lines | VER - current version number") write(" COMPILE - current source | BUILD - compile & link") write(" TEST - compile,link, & run | RUN - run last compiled") write(" $ - command to system (shell) | HELP or ? - this help screen") write(" TIME or DATE - displays time | !! - repeat last command") write("*---------------------------------+--------------------------------------*") write(" LIST or DEL [from [to]] - list or delete line(s)") write(" FIND str [repl] - find or replace string") return " EXIT or QUIT - return to operating system" end #SUB LINE ENTRY AND HANDY PARSER PROCEDURE #EJECT procedure entry(stuff) local element, finish, flag, lnum, other other := list() flag := "i" finish := 9999999 every element := !program do { lnum := integer(element[1:upto(' \t',element)]) if stuff = lnum then { put(other,cmd) stuff := finish next } if stuff < lnum then { put(other,cmd) stuff := finish } put(other,element) } if stuff ~= finish then put(other,cmd) program := copy(other) end procedure shell() local command command := cmd[find(" ",cmd):0] if trim(detab(command))=="" then return "No shell command" system(command) return "\nReturn to editor" end procedure parse(line) local tokens tokens := [] line ? while tab(upto(chars)) do put(tokens,tab(many(chars))) return tokens end procedure last(substr,str) local i every i := find(substr,str) return i end