From 06c7845f0247e77ed861b85b6c48556f6b6b120d Mon Sep 17 00:00:00 2001 From: "Konstantin Kirik (snegovick)" Date: Fri, 12 Dec 2025 06:24:08 +0300 Subject: Reorganize files according to proper directory structure --- appl/cmd/mkfile | 14 + appl/cmd/sh9.b | 857 +++++++++++++++++++++++++++++++++++++++++++++++++++ appl/cmd/sh92.b | 215 +++++++++++++ appl/lib/mkfile | 19 ++ appl/lib/sh9parser.b | 142 +++++++++ appl/lib/sh9util.b | 26 ++ appl/mkfile | 7 + mkconfig | 1 + mkfile | 38 +-- module/mkfile | 9 + module/mkmod | 16 + module/sh9parser.m | 29 ++ module/sh9util.m | 8 + sh9.b | 857 --------------------------------------------------- sh92.b | 208 ------------- sh9parser.b | 130 -------- sh9parser.m | 28 -- sh9util.b | 26 -- sh9util.m | 8 - 19 files changed, 1348 insertions(+), 1290 deletions(-) create mode 100644 appl/cmd/mkfile create mode 100644 appl/cmd/sh9.b create mode 100644 appl/cmd/sh92.b create mode 100644 appl/lib/mkfile create mode 100644 appl/lib/sh9parser.b create mode 100644 appl/lib/sh9util.b create mode 100644 appl/mkfile create mode 100644 mkconfig create mode 100644 module/mkfile create mode 100644 module/mkmod create mode 100644 module/sh9parser.m create mode 100644 module/sh9util.m delete mode 100644 sh9.b delete mode 100644 sh92.b delete mode 100644 sh9parser.b delete mode 100644 sh9parser.m delete mode 100644 sh9util.b delete mode 100644 sh9util.m diff --git a/appl/cmd/mkfile b/appl/cmd/mkfile new file mode 100644 index 0000000..a422ace --- /dev/null +++ b/appl/cmd/mkfile @@ -0,0 +1,14 @@ +<../../mkconfig + +TARG=\ + sh9.dis\ + sh92.dis\ + +SYSMODULES=\ + sh9util.m\ + sh9parser.m\ + sys.m\ + +DISBIN=$ROOT/dis + +<$ROOT/mkfiles/mkdis diff --git a/appl/cmd/sh9.b b/appl/cmd/sh9.b new file mode 100644 index 0000000..64d88e1 --- /dev/null +++ b/appl/cmd/sh9.b @@ -0,0 +1,857 @@ +implement Sh9; + +include "sys.m"; + sys: Sys; + FD: import Sys; + +include "draw.m"; + Context: import Draw; + +include "filepat.m"; + filepat: Filepat; + nofilepat := 0; # true if load Filepat has failed. + +include "bufio.m"; + bufio: Bufio; + Iobuf: import bufio; + +include "env.m"; + env: Env; + +include "hash.m"; + hash: Hash; + HashTable: import hash; + HashVal: import hash; + +include "workdir.m"; + +stdin: ref FD; +stderr: ref FD; +waitfd: ref FD; + +Quoted: con '\uFFF0'; +stringQuoted: con "\uFFF0"; + +Sh9: module +{ + init: fn(ctxt: ref Context, argv: list of string); +}; + +Command: adt +{ + args: list of string; + inf, outf: string; + append: int; +}; + +Async, Seq: con iota; + +Pipeline: adt +{ + cmds: list of ref Command; + term: int; +}; + +usage() +{ + sys->fprint(stderr, "Usage: sh9 [-n] [-c cmd] [file]\n"); +} + +clean_n_chars_seek(sys: Sys, n: int, seek: int) { + for (i:=0; i<(n-seek); i++) { + sys->print("\b"); + } + for (i=0; iprint(" "); + } + for (i=0; iprint("\b"); + } +} + +clean_n_chars(sys: Sys, n: int) { + clean_n_chars_seek(sys, n, 0); +} + +init(ctxt: ref Context, argv: list of string) +{ + sys = load Sys Sys->PATH; + env = load Env Env->PATH; + bufio = load Bufio Bufio->PATH; + hash = load Hash Hash->PATH; + + n: int; + arg: list of string; + buf := array[1024] of byte; + + stderr = sys->fildes(2); + + waitfd = sys->open("#p/"+string sys->pctl(0, nil)+"/wait", sys->OREAD); + if(waitfd == nil){ + sys->fprint(stderr, "sh9: open wait: %r\n"); + return; + } + + eflag := nflag := lflag := 0; + cmd: string; + if(argv != nil) { + argv = tl argv; + } + for(; argv != nil && len hd argv && (hd argv)[0]=='-'; argv = tl argv) { + case hd argv { + "-e" => + eflag = 1; + "-n" => + nflag = 1; + "-l" => + lflag = 1; + "-c" => + argv = tl argv; + if(len argv != 1){ + usage(); + return; + } + cmd = hd argv; + * => + usage(); + return; + } + } + + if (lflag) + startup(ctxt); + + if(eflag == 0) + sys->pctl(sys->FORKENV, nil); + if(nflag == 0) + sys->pctl(sys->FORKNS, nil); + if(cmd != nil){ + arg = tokenize(cmd+"\n"); + if(arg != nil) + runit(ctxt, parseit(arg)); + return; + } + if(argv != nil){ + script(ctxt, hd argv); + return; + } + + cctlfd := sys->open("/dev/consctl", sys->OWRITE); + if(cctlfd == nil) + return; + sys->write(cctlfd, array of byte "rawon", 5); + + dfd := sys->open("/dev/cons", sys->OREAD); + if(dfd == nil) + return; + + #stdin = sys->fildes(0); + + prompt := getusername() + "@" + sysname() + ":" + getcwd() + "; "; + offset : int = 0; + temp : int; + last_cmdline := array[1024] of int; + last_cmdline_length : int = 0; + + cmd1 := 0; + ST_NORMAL : con 0; + ST_WAITCMD1 : con 1; + ST_WAITCMD2 : con 2; + state := ST_NORMAL; + history_len := 1; + history_entry_cur := 0; +# history.entries = nil; +# history.entries = ("", "") :: nil; + history := hash->new(1024); + history.insert("0", (0,0.0,"")); + seek := 0; + + bio := bufio->fopen(dfd, sys->OREAD); + + sys->print("SH9 v0\n"); + sys->print("%s", prompt); + for(;;) { + temp = bio.getb(); + # check if escape + case state { + ST_NORMAL => + # check if escape + if (temp == 27) { + state = ST_WAITCMD1; # is escape + } else if (temp == '\t') { + # tab complete rq + sys->print("tab"); + } else if (temp == '\b') { + if (seek == 0) { + if (offset != 0) { + sys->print("\b"); + sys->print(" "); + sys->print("\b"); + offset --; + } + } else { + cur_buf := array[1024] of byte; + cur_buf[0:] = buf[0:offset]; + correction := 0; + for (i:=0;iprint("%c", int(buf[i])); + } + for (i=0; iprint("\b"); + } + } + } else { + buf[offset] = byte(temp); + offset ++; + if ((offset >= len buf) || (buf[offset-1] == byte('\n'))) { + history_entry_cur = 0; + seek = 0; + sys->print("\n"); + arg = tokenize(string buf[0:offset]); + if(arg != nil) { + runit(ctxt, parseit(arg)); + history.insert(sys->sprint("%d", history_len), (0,0.0,string buf[0:offset-1])); + history_len++; + } + offset = 0; + prompt = getusername() + "@" + sysname() + ":" + getcwd() + "; "; + sys->print("%s", prompt); + } else { + sys->print("%c",temp); + } + } + ST_WAITCMD1 => + if (temp == '[') { + state = ST_WAITCMD2; + cmd1 = temp; + } + ST_WAITCMD2 => + state = ST_NORMAL; + case cmd1 { + '[' => + case temp { + 65 => { #up press + seek = 0; + clean_n_chars(sys, offset); + + offset = 0; + he := history_len; + if (history_entry_cur < history_len) { + history_entry_cur ++; + he -= history_entry_cur; + } + cmdline := history.find(sys->sprint("%d", he)); + if (cmdline != nil) { + sys->print("%s", cmdline.s); + offset = len cmdline.s; + for (i:=0; i { # down key + seek = 0; + if (history_entry_cur > 0) { + history_entry_cur --; + clean_n_chars(sys, offset); + + offset = 0; + he := history_len; + he -= history_entry_cur; + cmdline := history.find(sys->sprint("%d", he)); + if (cmdline != nil) { + sys->print("%s", cmdline.s); + offset = len cmdline.s; + for (i:=0; i { # left key + if (seek > offset) { + seek = offset; + } else { + seek ++; + sys->print("\b"); + } + } + 67 => { # right key + clean_n_chars_seek(sys, offset, seek); + for (i:=0; iprint("%c", int(buf[i])); + } + if (seek > 0) { + seek --; + } + for (i=0; iprint("\b"); + } + } + 70 => { # end key + clean_n_chars_seek(sys, offset, seek); + seek = 0; + for (i:=0; iprint("%c", int(buf[i])); + } + } + 72 => { # home key + seek = offset; + for (i:=0; iprint("\b"); + } + } + * => { + sys->print("no action bind for %d\n", temp); + } + + } + } + } + } +} + +rev(arg: list of string): list of string +{ + ret: list of string; + + while(arg != nil){ + ret = hd arg :: ret; + arg = tl arg; + } + return ret; +} + +waitfor(pid: int) +{ + if(pid <= 0) + return; + buf := array[sys->WAITLEN] of byte; + status := ""; + for(;;){ + n := sys->read(waitfd, buf, len buf); + if(n < 0){ + sys->fprint(stderr, "sh9: read wait: %r\n"); + return; + } + status = string buf[0:n]; + if(status[len status-1] != ':') + sys->fprint(stderr, "%s\n", status); + who := int status; + if(who != 0){ + if(who == pid){ + return; + } + } + } +} + +mkprog(ctxt: ref Context, arg: list of string, infd, outfd: ref Sys->FD, waitpid: chan of int) +{ + fds := list of {0, 1, 2}; + if(infd != nil) + fds = infd.fd :: fds; + if(outfd != nil) + fds = outfd.fd :: fds; + pid := sys->pctl(sys->NEWFD, fds); + console := sys->fildes(2); + + if(infd != nil){ + sys->dup(infd.fd, 0); + infd = nil; + } + if(outfd != nil){ + sys->dup(outfd.fd, 1); + outfd = nil; + } + + waitpid <-= pid; + + if(pid < 0 || arg == nil) + return; + + { + exec(ctxt, arg, console); + }exception{ + "fail:*" => + #sys->fprint(console, "%s:%s\n", hd arg, e.name[5:]); + exit; + "write on closed pipe" => + #sys->fprint(console, "%s: %s\n", hd arg, e.name); + exit; + } +} + +exec(ctxt: ref Context, args: list of string, console: ref Sys->FD) +{ + if (args == nil) + return; + cmd := hd args; + file := cmd; + + if(len file<4 || file[len file-4:]!=".dis") + file += ".dis"; + + c := load Sh9 file; + if(c == nil) { + err := sys->sprint("%r"); + if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){ + c = load Sh9 "/dis/"+file; + if(c == nil) { + err = sys->sprint("%r"); + } + } + if(c == nil){ + sys->fprint(console, "%s: %s\n", cmd, err); + return; + } + } + + c->init(ctxt, args); +} + +script(ctxt: ref Context, src: string) +{ + bufio = load Bufio Bufio->PATH; + if(bufio == nil){ + sys->fprint(stderr, "sh9: load bufio: %r\n"); + return; + } + + f := bufio->open(src, Bufio->OREAD); + if(f == nil){ + sys->fprint(stderr, "sh9: open %s: %r\n", src); + return; + } + for(;;){ + s := f.gets('\n'); + if(s == nil) + break; + arg := tokenize(s); + if(arg != nil) + runit(ctxt, parseit(arg)); + } +} + +sysname(): string +{ + fd := sys->open("#c/sysname", sys->OREAD); + if(fd == nil) + return "anon"; + buf := array[128] of byte; + n := sys->read(fd, buf, len buf); + if(n < 0) + return "anon"; + return string buf[0:n]; +} + +# Lexer. + +tokenize(s: string): list of string +{ + tok: list of string; + token := ""; + instring := 0; + + loop: + for(i:=0; i' or '<' or '\r' => + if(token != "" && s[i]!='\''){ + tok = token :: tok; + token = ""; + } + case s[i] { + '#' => + break loop; + '\'' => + instring = 1; + '>' => + ss := ""; + ss[0] = s[i]; + if(i + ss := ""; + ss[0] = s[i]; + tok = ss :: tok; + } + * => + token[len token] = s[i]; + } + } + if(instring){ + sys->fprint(stderr, "sh9: unmatched quote\n"); + return nil; + } + return rev(tok); +} + +ismeta(char: int): int +{ + case char { + '*' or '[' or '?' or + '#' or '\'' or '|' or + '&' or ';' or '>' or + '<' => + return 1; + } + return 0; +} + +addchar(token: string, char: int): string +{ + if(ismeta(char) && (len token==0 || token[0]!=Quoted)) + token = stringQuoted + token; + token[len token] = char; + return token; +} + +# Parser. + +getcommand(words: list of string): (ref Command, list of string) +{ + args: list of string; + word: string; + si, so: string; + append := 0; + + gather: + do { + word = hd words; + + case word { + ">" or ">>" => + if(so != nil) + return (nil, nil); + + words = tl words; + + if(words == nil) + return (nil, nil); + + so = hd words; + if(len so>0 && so[0]==Quoted) + so = so[1:]; + if(word == ">>") + append = 1; + "<" => + if(si != nil) + return (nil, nil); + + words = tl words; + + if(words == nil) + return (nil, nil); + + si = hd words; + if(len si>0 && si[0]==Quoted) + si = si[1:]; + "|" or ";" or "&" => + break gather; + * => + files := doexpand(word); + while(files != nil){ + args = hd files :: args; + files = tl files; + } + } + + words = tl words; + } while (words != nil); + + return (ref Command(rev(args), si, so, append), words); +} + +doexpand(file: string): list of string +{ + if(file == nil) + return file :: nil; + if(len file>0 && file[0]==Quoted) + return file[1:] :: nil; + if (nofilepat) + return file :: nil; + for(i:=0; iPATH) == nil) { + sys->fprint(stderr, "sh: warning: cannot load %s: %r\n", + Filepat->PATH); + nofilepat = 1; + return file :: nil; + } + } + files := filepat->expand(file); + if(files != nil) + return files; + break; + } + } + return file :: nil; +} + +revc(arg: list of ref Command): list of ref Command +{ + ret: list of ref Command; + while(arg != nil) { + ret = hd arg :: ret; + arg = tl arg; + } + return ret; +} + +getpipe(words: list of string): (ref Pipeline, list of string) +{ + cmds: list of ref Command; + cur: ref Command; + word: string; + + term := Seq; + gather: + while(words != nil) { + word = hd words; + + if(word == "|") + return (nil, nil); + + (cur, words) = getcommand(words); + + if(cur == nil) + return (nil, nil); + + cmds = cur :: cmds; + + if(words == nil) + break gather; + + word = hd words; + words = tl words; + + case word { + ";" => + break gather; + "&" => + term = Async; + break gather; + "|" => + continue gather; + } + return (nil, nil); + } + + if(word == "|") + return (nil, nil); + + return (ref Pipeline(revc(cmds), term), words); +} + +revp(arg: list of ref Pipeline): list of ref Pipeline +{ + ret: list of ref Pipeline; + + while(arg != nil) { + ret = hd arg :: ret; + arg = tl arg; + } + return ret; +} + +parseit(words: list of string): list of ref Pipeline +{ + ret: list of ref Pipeline; + cur: ref Pipeline; + + while(words != nil) { + (cur, words) = getpipe(words); + if(cur == nil){ + sys->fprint(stderr, "sh9: syntax error\n"); + return nil; + } + ret = cur :: ret; + } + return revp(ret); +} + +# Runner. + +runpipeline(ctx: ref Context, pipeline: ref Pipeline) +{ + if(pipeline.term == Async) + sys->pctl(sys->NEWPGRP, nil); + pid := startpipeline(ctx, pipeline); + if(pid < 0) + return; + if(pipeline.term == Seq) + waitfor(pid); +} + +startpipeline(ctx: ref Context, pipeline: ref Pipeline): int +{ + pid := 0; + cmds := pipeline.cmds; + first := 1; + inpipe, outpipe: ref Sys->FD; + while(cmds != nil) { + last := tl cmds == nil; + cmd := hd cmds; + + infd: ref Sys->FD; + if(!first) + infd = inpipe; + else if(cmd.inf != nil){ + infd = sys->open(cmd.inf, Sys->OREAD); + if(infd == nil){ + sys->fprint(stderr, "sh9: can't open %s: %r\n", cmd.inf); + return -1; + } + } + + outfd: ref Sys->FD; + if(!last){ + fds := array[2] of ref Sys->FD; + if(sys->pipe(fds) < 0){ + sys->fprint(stderr, "sh9: can't make pipe: %r\n"); + return -1; + } + outpipe = fds[0]; + outfd = fds[1]; + fds = nil; + }else if(cmd.outf != nil){ + if(cmd.append){ + outfd = sys->open(cmd.outf, Sys->OWRITE); + if(outfd != nil) + sys->seek(outfd, big 0, Sys->SEEKEND); + } + if(outfd == nil) + outfd = sys->create(cmd.outf, Sys->OWRITE, 8r666); + if(outfd == nil){ + sys->fprint(stderr, "sh9: can't open %s: %r\n", cmd.outf); + return -1; + } + } + + rpid := chan of int; + spawn mkprog(ctx, cmd.args, infd, outfd, rpid); + pid = <-rpid; + infd = nil; + outfd = nil; + + inpipe = outpipe; + outpipe = nil; + + first = 0; + cmds = tl cmds; + } + return pid; +} + +runit(ctx: ref Context, pipes: list of ref Pipeline) +{ + while(pipes != nil) { + pipeline := hd pipes; + pipes = tl pipes; + if(pipeline.term == Seq) + runpipeline(ctx, pipeline); + else + spawn runpipeline(ctx, pipeline); + } +} + +strchr(s: string, c: int): int +{ + ln := len s; + for (i := 0; i < ln; i++) + if (s[i] == c) + return i; + return -1; +} + +# PROFILE: con "/lib/profile"; +PROFILE: con "/lib/infernoinit"; + +startup(ctxt: ref Context) +{ + if (env == nil) + return; + # if (env->getenv("home") != nil) + # return; + home := gethome(); + env->setenv("home", home); + escript(ctxt, PROFILE); + escript(ctxt, home + PROFILE); +} + +escript(ctxt: ref Context, file: string) +{ + fd := sys->open(file, Sys->OREAD); + if (fd != nil) + script(ctxt, file); +} + +gethome(): string +{ + fd := sys->open("/dev/user", sys->OREAD); + if(fd == nil) + return "/"; + buf := array[128] of byte; + n := sys->read(fd, buf, len buf); + if(n < 0) + return "/"; + return "/usr/" + string buf[0:n]; +} + +getusername(): string +{ + fd := sys->open("/dev/user", sys->OREAD); + if(fd == nil) + return "/"; + buf := array[128] of byte; + n := sys->read(fd, buf, len buf); + if(n < 0) + return "?"; + return string buf[0:n]; +} + +getcwd(): string +{ + gwd := load Workdir Workdir->PATH; + if (gwd == nil) { + sys->fprint(stderr, "pwd: cannot load %s: %r\n", Workdir->PATH); + raise "fail:bad module"; + } + + wd := gwd->init(); + if(wd == nil) { + sys->fprint(stderr, "pwd: %r\n"); + raise "fail:error"; + } + return wd; +} diff --git a/appl/cmd/sh92.b b/appl/cmd/sh92.b new file mode 100644 index 0000000..9748da7 --- /dev/null +++ b/appl/cmd/sh92.b @@ -0,0 +1,215 @@ +implement Sh92; + +include "sys.m"; +include "draw.m"; +include "sh9util.m"; +include "sh9parser.m"; + +sys: Sys; +sh9u: Sh9Util; +sh9p: Sh9Parser; + +Sh92: module { + init: fn(nil: ref Draw->Context, nil: list of string); +}; + +ModProc: adt { + name: string; + start: int; +}; + +ModVar: adt { + name: string; + val: string; +}; + +ShModule: adt { + global_vars: list of ref ModVar; + procs: list of ref ModProc; +}; + +GrammarNode: import sh9p; +TokNode: import sh9p; +mk_tok: import sh9p; +set_last_tok: import sh9p; +print_toks: import sh9p; +parse_toks: import sh9p; + +reverse_list: import sh9u; +to_array: import sh9u; + +S_UNKNOWN: con "UNK"; +S_ID: con "ID"; +S_STR: con "STR"; +S_EQ: con "EQ"; +S_DOL: con "DOL"; +S_COLON: con "COLON"; +S_SEMIC: con "SEMIC"; +S_LPAR: con "LPAR"; +S_RPAR: con "RPAR"; +S_LCURLY: con "LCURLY"; +S_RCURLY: con "RCURLY"; +S_DQSTR: con "DQSTR"; +S_SQSTR: con "SQSTR"; +S_DQTE: con "DQTE"; +S_SQTE: con "SQTE"; +S_SP: con "SP"; +S_TAB: con "TAB"; +S_EOL: con "EOL"; + +S_STMT: con "STMT"; +S_EXPR: con "EXPR"; +S_CALL: con "CALL"; + +tokenize(line: string, line_n: int): array of ref TokNode { + toks : list of ref TokNode; + last_tok:= ref TokNode; + last_tok.start = -1; + last_tok.line = -1; + last_tok.tok = ""; + last_tok.typ = S_UNKNOWN; + k:=0; + + for (i := 0; i < len line; i++) { + if (last_tok.typ == S_DQSTR) { + case (line[i:i+1]) { + "\"" => { + l := len last_tok.tok; + if ((last_tok.tok[l-1:] != "\\") || ((last_tok.tok[l-1:] == "\\") && (last_tok.tok[l-2:l-1] == "\\"))) { + # end of str + last_tok.tok = last_tok.tok + line[i:i+1]; + (last_tok, toks) = set_last_tok(last_tok, toks); + } else { + # escaped dqte, just continue + last_tok.tok = last_tok.tok + line[i:i+1]; + } + }; + * => { + last_tok.tok = last_tok.tok + line[i:i+1]; + } + } + } else if (last_tok.typ == S_SQSTR) { + case (line[i:i+1]) { + "'" => { + l := len last_tok.tok; + if ((last_tok.tok[l-1:] != "\\") || ((last_tok.tok[l-1:] == "\\") && (last_tok.tok[l-2:l-1] == "\\"))) { + # end of str + last_tok.tok = last_tok.tok + line[i:i+1]; + (last_tok, toks) = set_last_tok(last_tok, toks); + } else { + # escaped sqte, just continue + last_tok.tok = last_tok.tok + line[i:i+1]; + } + }; + * => { + last_tok.tok = last_tok.tok + line[i:i+1]; + } + } + } else { + case (line[i:i+1]) { + " " or "\t" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + }; + "=" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, "=", S_EQ) :: toks; + }; + ";" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, ";", S_SEMIC) :: toks; + }; + "$" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, "$", S_DOL) :: toks; + }; + "(" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, "(", S_LPAR) :: toks; + }; + ")" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, ")", S_RPAR) :: toks; + }; + "{" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, "{", S_LCURLY) :: toks; + }; + "}" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, "}", S_RCURLY) :: toks; + }; + "\"" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + last_tok.start = i; + last_tok.line = line_n; + last_tok.typ = S_DQSTR; + last_tok.tok = last_tok.tok + line[i:i+1]; + }; + "'" => { + (last_tok, toks) = set_last_tok(last_tok, toks); + last_tok.start = i; + last_tok.line = line_n; + last_tok.typ = S_SQSTR; + last_tok.tok = last_tok.tok + line[i:i+1]; + }; + * => { + if (last_tok.start == -1) { + last_tok.start = i; + last_tok.line = line_n; + last_tok.typ = S_ID; + } + last_tok.tok = last_tok.tok + line[i:i+1]; + }; + } + } + } + (last_tok, toks) = set_last_tok(last_tok, toks); + toks = mk_tok(i, line_n, "", S_EOL) :: toks; + toks = reverse_list(toks); + return to_array(toks); +} + +stmt_assign(toks: array of ref TokNode) { + sys->print("ASSIGN STMT\n"); +} + +stmt_cmd_call(toks: array of ref TokNode) { + sys->print("CMD CALL\n"); +} + +empty(toks: array of ref TokNode) { + sys->print("EMPTY\n"); +} + +Te: adt{ + s: string; +}; + +init(ctxt: ref Draw->Context, argv: list of string) { + sys = load Sys Sys->PATH; + sh9u = load Sh9Util Sh9Util->PATH; + sh9p = load Sh9Parser Sh9Parser->PATH; + sh9p->init(); + + + assign_g_semic : GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_SEMIC}, S_UNKNOWN, stmt_assign); + assign_g_eol : GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_EOL}, S_UNKNOWN, stmt_assign); + sqstr_expr_g: GrammarNode = (array [] of {S_SQSTR}, S_EXPR, empty); + str_expr_g: GrammarNode = (array [] of {S_STR}, S_EXPR, empty); + cmd_call_g: GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_SEMIC}, S_UNKNOWN, stmt_cmd_call); + grammar: array of ref GrammarNode; + grammar = array [] of {ref assign_g_semic, ref assign_g_eol, ref sqstr_expr_g, ref str_expr_g, ref cmd_call_g}; + + toks1 := tokenize("AB = 'smth \"test\" ';", 0); + print_toks(toks1); + sys->print("Parse\n"); + parse_toks(toks1, grammar); + sys->print("Parse done\n"); + + # toks2 := tokenize("echo \"smth \" \"test\";", 0); + # print_toks(toks2); + # toks3 := tokenize("if test x\"a\" = x\"b\"; then echo \"1\"; fi", 0); + # print_toks(toks3); + # toks4 := tokenize("echo 'smth2' 'test';", 0); + # print_toks(toks4); +} diff --git a/appl/lib/mkfile b/appl/lib/mkfile new file mode 100644 index 0000000..0becc2b --- /dev/null +++ b/appl/lib/mkfile @@ -0,0 +1,19 @@ +<../../mkconfig + +TARG=\ + sh9util.dis\ + sh9parser.dis\ + + +SYSMODULES=\ + sh9util.m\ + sh9parser.m\ + sys.m\ + + +MODULES=\ + + +DISBIN=$ROOT/dis/lib + +<$ROOT/mkfiles/mkdis diff --git a/appl/lib/sh9parser.b b/appl/lib/sh9parser.b new file mode 100644 index 0000000..ac46b40 --- /dev/null +++ b/appl/lib/sh9parser.b @@ -0,0 +1,142 @@ +implement Sh9Parser; + +include "sys.m"; +include "sh9parser.m"; +include "sh9util.m"; + +sys: Sys; +S_UNKNOWN: con "UNK"; + +sh9u: Sh9Util; + +reverse_list: import sh9u; +to_array: import sh9u; + +GrammarNode.print_expr(gn: self ref GrammarNode) { + lg:= len gn.expr; + for (i:=0; iprint("%s ", gn.expr[i]); + } + if (gn.transform == S_UNKNOWN) { + sys->print("\n"); + } else { + sys->print("-> %s\n", gn.transform); + } +} + +init() +{ + sys = load Sys Sys->PATH; + sh9u = load Sh9Util Sh9Util->PATH; +} + +mk_tok(start: int, line: int, tok: string, typ: string) : ref TokNode { + tok_node: TokNode; + tok_node.start = start; + tok_node.line = line; + tok_node.tok = tok; + tok_node.typ = typ; + return ref tok_node; +} + +set_last_tok(last_tok: ref TokNode, toks: list of ref TokNode): (ref TokNode, list of ref TokNode) { + sys->print("last_tok: %s\n", last_tok.typ); + ret_tok: TokNode; + #ret_tok = *last_tok; + ret_tok.typ = last_tok.typ; + ret_tok.start = last_tok.start; + ret_tok.tok = last_tok.tok; + ret_tok.line = last_tok.line; + if (last_tok.typ != S_UNKNOWN) { + toks = last_tok :: toks; + ret_tok.typ = S_UNKNOWN; + ret_tok.start = -1; + ret_tok.tok = ""; + ret_tok.line = -1; + } + sys->print("ret_tok: %s\n", ret_tok.typ); + return (ref ret_tok, toks); +} + +print_toks(toks: array of ref TokNode) { + lt := len toks; + for (i := 0; i < lt; i ++) { + tok := toks[i]; + sys->print("[%d/%d] %s (%s)\n", i, lt, tok.typ, tok.tok); + } +} + +print_toks_short(toks: array of ref TokNode) { + lt := len toks; + for (i := 0; i < lt; i ++) { + tok := toks[i]; + sys->print("%s ", tok.typ); + } + sys->print("\n"); +} + +check_grammar_node_match(toks: array of ref TokNode, gn: ref GrammarNode): int { + lt:= len toks; + lg:= len gn.expr; + if (lg > lt) { + return 0; + } + #sys->print("Checking grammar "); + gn.print_expr(); + #sys->print("Against "); + print_toks(toks); + for (i:= 0; i < lg; i ++) { + if (toks[i].typ != gn.expr[i]) { + return 0; + } + } + return 1; +} + +replace_toks(src: array of ref TokNode, replace_start: int, replace_len: int, replace_with: array of ref TokNode): array of ref TokNode { + src_len:= len src; + new_toks: list of ref TokNode; + with_len:= len replace_with; + for (i:=0; iprint("Loop %d: ", ctr); + print_toks_short(toks); + ctr ++; + changed = 0; + fast: for (i := 0; i <= lt; i ++) { + for (j := 0; j < lgns; j++) { + gj:= g[j]; + if (check_grammar_node_match(toks[lt - i:], gj) == 1) { + sys->print("Something matched !\n"); + gj.print_expr(); + sys->print("Before replace: "); + print_toks_short(toks); + gj.callback(toks[lt-i: lt-i+len gj.expr]); + toks = replace_toks(toks, lt-i, len gj.expr, array[] of {mk_tok(toks[lt - i].start, toks[lt - i].line, "", gj.transform)}); + sys->print("After replace: "); + changed = 1; + break fast; + } + } + } + } while(changed); + return toks; +} diff --git a/appl/lib/sh9util.b b/appl/lib/sh9util.b new file mode 100644 index 0000000..7452a13 --- /dev/null +++ b/appl/lib/sh9util.b @@ -0,0 +1,26 @@ +implement Sh9Util; + +include "sh9util.m"; + +reverse_list[T](toks: list of T): list of T +{ + lt := len toks; + out : list of T; + for (i := 0; i < lt; i ++) { + tok := hd toks; + toks = tl toks; + out = tok :: out; + } + return out; +} + +to_array[T](toks: list of T): array of T { + lt := len toks; + out := array[lt] of T; + for (i := 0; i < lt; i ++) { + tok := hd toks; + toks = tl toks; + out[i] = tok; + } + return out; +} diff --git a/appl/mkfile b/appl/mkfile new file mode 100644 index 0000000..1946c4f --- /dev/null +++ b/appl/mkfile @@ -0,0 +1,7 @@ +<../mkconfig + +DIRS=\ + lib\ + cmd\ + +<$ROOT/mkfiles/mksubdirs diff --git a/mkconfig b/mkconfig new file mode 100644 index 0000000..b72b198 --- /dev/null +++ b/mkconfig @@ -0,0 +1 @@ +<$ROOT/mkconfig diff --git a/mkfile b/mkfile index cf68f33..ded2d68 100644 --- a/mkfile +++ b/mkfile @@ -1,35 +1,7 @@ -<../../../mkconfig +fprint(stderr, "Usage: sh9 [-n] [-c cmd] [file]\n"); -} - -clean_n_chars_seek(sys: Sys, n: int, seek: int) { - for (i:=0; i<(n-seek); i++) { - sys->print("\b"); - } - for (i=0; iprint(" "); - } - for (i=0; iprint("\b"); - } -} - -clean_n_chars(sys: Sys, n: int) { - clean_n_chars_seek(sys, n, 0); -} - -init(ctxt: ref Context, argv: list of string) -{ - sys = load Sys Sys->PATH; - env = load Env Env->PATH; - bufio = load Bufio Bufio->PATH; - hash = load Hash Hash->PATH; - - n: int; - arg: list of string; - buf := array[1024] of byte; - - stderr = sys->fildes(2); - - waitfd = sys->open("#p/"+string sys->pctl(0, nil)+"/wait", sys->OREAD); - if(waitfd == nil){ - sys->fprint(stderr, "sh9: open wait: %r\n"); - return; - } - - eflag := nflag := lflag := 0; - cmd: string; - if(argv != nil) { - argv = tl argv; - } - for(; argv != nil && len hd argv && (hd argv)[0]=='-'; argv = tl argv) { - case hd argv { - "-e" => - eflag = 1; - "-n" => - nflag = 1; - "-l" => - lflag = 1; - "-c" => - argv = tl argv; - if(len argv != 1){ - usage(); - return; - } - cmd = hd argv; - * => - usage(); - return; - } - } - - if (lflag) - startup(ctxt); - - if(eflag == 0) - sys->pctl(sys->FORKENV, nil); - if(nflag == 0) - sys->pctl(sys->FORKNS, nil); - if(cmd != nil){ - arg = tokenize(cmd+"\n"); - if(arg != nil) - runit(ctxt, parseit(arg)); - return; - } - if(argv != nil){ - script(ctxt, hd argv); - return; - } - - cctlfd := sys->open("/dev/consctl", sys->OWRITE); - if(cctlfd == nil) - return; - sys->write(cctlfd, array of byte "rawon", 5); - - dfd := sys->open("/dev/cons", sys->OREAD); - if(dfd == nil) - return; - - #stdin = sys->fildes(0); - - prompt := getusername() + "@" + sysname() + ":" + getcwd() + "; "; - offset : int = 0; - temp : int; - last_cmdline := array[1024] of int; - last_cmdline_length : int = 0; - - cmd1 := 0; - ST_NORMAL : con 0; - ST_WAITCMD1 : con 1; - ST_WAITCMD2 : con 2; - state := ST_NORMAL; - history_len := 1; - history_entry_cur := 0; -# history.entries = nil; -# history.entries = ("", "") :: nil; - history := hash->new(1024); - history.insert("0", (0,0.0,"")); - seek := 0; - - bio := bufio->fopen(dfd, sys->OREAD); - - sys->print("SH9 v0\n"); - sys->print("%s", prompt); - for(;;) { - temp = bio.getb(); - # check if escape - case state { - ST_NORMAL => - # check if escape - if (temp == 27) { - state = ST_WAITCMD1; # is escape - } else if (temp == '\t') { - # tab complete rq - sys->print("tab"); - } else if (temp == '\b') { - if (seek == 0) { - if (offset != 0) { - sys->print("\b"); - sys->print(" "); - sys->print("\b"); - offset --; - } - } else { - cur_buf := array[1024] of byte; - cur_buf[0:] = buf[0:offset]; - correction := 0; - for (i:=0;iprint("%c", int(buf[i])); - } - for (i=0; iprint("\b"); - } - } - } else { - buf[offset] = byte(temp); - offset ++; - if ((offset >= len buf) || (buf[offset-1] == byte('\n'))) { - history_entry_cur = 0; - seek = 0; - sys->print("\n"); - arg = tokenize(string buf[0:offset]); - if(arg != nil) { - runit(ctxt, parseit(arg)); - history.insert(sys->sprint("%d", history_len), (0,0.0,string buf[0:offset-1])); - history_len++; - } - offset = 0; - prompt = getusername() + "@" + sysname() + ":" + getcwd() + "; "; - sys->print("%s", prompt); - } else { - sys->print("%c",temp); - } - } - ST_WAITCMD1 => - if (temp == '[') { - state = ST_WAITCMD2; - cmd1 = temp; - } - ST_WAITCMD2 => - state = ST_NORMAL; - case cmd1 { - '[' => - case temp { - 65 => { #up press - seek = 0; - clean_n_chars(sys, offset); - - offset = 0; - he := history_len; - if (history_entry_cur < history_len) { - history_entry_cur ++; - he -= history_entry_cur; - } - cmdline := history.find(sys->sprint("%d", he)); - if (cmdline != nil) { - sys->print("%s", cmdline.s); - offset = len cmdline.s; - for (i:=0; i { # down key - seek = 0; - if (history_entry_cur > 0) { - history_entry_cur --; - clean_n_chars(sys, offset); - - offset = 0; - he := history_len; - he -= history_entry_cur; - cmdline := history.find(sys->sprint("%d", he)); - if (cmdline != nil) { - sys->print("%s", cmdline.s); - offset = len cmdline.s; - for (i:=0; i { # left key - if (seek > offset) { - seek = offset; - } else { - seek ++; - sys->print("\b"); - } - } - 67 => { # right key - clean_n_chars_seek(sys, offset, seek); - for (i:=0; iprint("%c", int(buf[i])); - } - if (seek > 0) { - seek --; - } - for (i=0; iprint("\b"); - } - } - 70 => { # end key - clean_n_chars_seek(sys, offset, seek); - seek = 0; - for (i:=0; iprint("%c", int(buf[i])); - } - } - 72 => { # home key - seek = offset; - for (i:=0; iprint("\b"); - } - } - * => { - sys->print("no action bind for %d\n", temp); - } - - } - } - } - } -} - -rev(arg: list of string): list of string -{ - ret: list of string; - - while(arg != nil){ - ret = hd arg :: ret; - arg = tl arg; - } - return ret; -} - -waitfor(pid: int) -{ - if(pid <= 0) - return; - buf := array[sys->WAITLEN] of byte; - status := ""; - for(;;){ - n := sys->read(waitfd, buf, len buf); - if(n < 0){ - sys->fprint(stderr, "sh9: read wait: %r\n"); - return; - } - status = string buf[0:n]; - if(status[len status-1] != ':') - sys->fprint(stderr, "%s\n", status); - who := int status; - if(who != 0){ - if(who == pid){ - return; - } - } - } -} - -mkprog(ctxt: ref Context, arg: list of string, infd, outfd: ref Sys->FD, waitpid: chan of int) -{ - fds := list of {0, 1, 2}; - if(infd != nil) - fds = infd.fd :: fds; - if(outfd != nil) - fds = outfd.fd :: fds; - pid := sys->pctl(sys->NEWFD, fds); - console := sys->fildes(2); - - if(infd != nil){ - sys->dup(infd.fd, 0); - infd = nil; - } - if(outfd != nil){ - sys->dup(outfd.fd, 1); - outfd = nil; - } - - waitpid <-= pid; - - if(pid < 0 || arg == nil) - return; - - { - exec(ctxt, arg, console); - }exception{ - "fail:*" => - #sys->fprint(console, "%s:%s\n", hd arg, e.name[5:]); - exit; - "write on closed pipe" => - #sys->fprint(console, "%s: %s\n", hd arg, e.name); - exit; - } -} - -exec(ctxt: ref Context, args: list of string, console: ref Sys->FD) -{ - if (args == nil) - return; - cmd := hd args; - file := cmd; - - if(len file<4 || file[len file-4:]!=".dis") - file += ".dis"; - - c := load Sh9 file; - if(c == nil) { - err := sys->sprint("%r"); - if(err != "permission denied" && err != "access permission denied" && file[0]!='/' && file[0:2]!="./"){ - c = load Sh9 "/dis/"+file; - if(c == nil) { - err = sys->sprint("%r"); - } - } - if(c == nil){ - sys->fprint(console, "%s: %s\n", cmd, err); - return; - } - } - - c->init(ctxt, args); -} - -script(ctxt: ref Context, src: string) -{ - bufio = load Bufio Bufio->PATH; - if(bufio == nil){ - sys->fprint(stderr, "sh9: load bufio: %r\n"); - return; - } - - f := bufio->open(src, Bufio->OREAD); - if(f == nil){ - sys->fprint(stderr, "sh9: open %s: %r\n", src); - return; - } - for(;;){ - s := f.gets('\n'); - if(s == nil) - break; - arg := tokenize(s); - if(arg != nil) - runit(ctxt, parseit(arg)); - } -} - -sysname(): string -{ - fd := sys->open("#c/sysname", sys->OREAD); - if(fd == nil) - return "anon"; - buf := array[128] of byte; - n := sys->read(fd, buf, len buf); - if(n < 0) - return "anon"; - return string buf[0:n]; -} - -# Lexer. - -tokenize(s: string): list of string -{ - tok: list of string; - token := ""; - instring := 0; - - loop: - for(i:=0; i' or '<' or '\r' => - if(token != "" && s[i]!='\''){ - tok = token :: tok; - token = ""; - } - case s[i] { - '#' => - break loop; - '\'' => - instring = 1; - '>' => - ss := ""; - ss[0] = s[i]; - if(i - ss := ""; - ss[0] = s[i]; - tok = ss :: tok; - } - * => - token[len token] = s[i]; - } - } - if(instring){ - sys->fprint(stderr, "sh9: unmatched quote\n"); - return nil; - } - return rev(tok); -} - -ismeta(char: int): int -{ - case char { - '*' or '[' or '?' or - '#' or '\'' or '|' or - '&' or ';' or '>' or - '<' => - return 1; - } - return 0; -} - -addchar(token: string, char: int): string -{ - if(ismeta(char) && (len token==0 || token[0]!=Quoted)) - token = stringQuoted + token; - token[len token] = char; - return token; -} - -# Parser. - -getcommand(words: list of string): (ref Command, list of string) -{ - args: list of string; - word: string; - si, so: string; - append := 0; - - gather: - do { - word = hd words; - - case word { - ">" or ">>" => - if(so != nil) - return (nil, nil); - - words = tl words; - - if(words == nil) - return (nil, nil); - - so = hd words; - if(len so>0 && so[0]==Quoted) - so = so[1:]; - if(word == ">>") - append = 1; - "<" => - if(si != nil) - return (nil, nil); - - words = tl words; - - if(words == nil) - return (nil, nil); - - si = hd words; - if(len si>0 && si[0]==Quoted) - si = si[1:]; - "|" or ";" or "&" => - break gather; - * => - files := doexpand(word); - while(files != nil){ - args = hd files :: args; - files = tl files; - } - } - - words = tl words; - } while (words != nil); - - return (ref Command(rev(args), si, so, append), words); -} - -doexpand(file: string): list of string -{ - if(file == nil) - return file :: nil; - if(len file>0 && file[0]==Quoted) - return file[1:] :: nil; - if (nofilepat) - return file :: nil; - for(i:=0; iPATH) == nil) { - sys->fprint(stderr, "sh: warning: cannot load %s: %r\n", - Filepat->PATH); - nofilepat = 1; - return file :: nil; - } - } - files := filepat->expand(file); - if(files != nil) - return files; - break; - } - } - return file :: nil; -} - -revc(arg: list of ref Command): list of ref Command -{ - ret: list of ref Command; - while(arg != nil) { - ret = hd arg :: ret; - arg = tl arg; - } - return ret; -} - -getpipe(words: list of string): (ref Pipeline, list of string) -{ - cmds: list of ref Command; - cur: ref Command; - word: string; - - term := Seq; - gather: - while(words != nil) { - word = hd words; - - if(word == "|") - return (nil, nil); - - (cur, words) = getcommand(words); - - if(cur == nil) - return (nil, nil); - - cmds = cur :: cmds; - - if(words == nil) - break gather; - - word = hd words; - words = tl words; - - case word { - ";" => - break gather; - "&" => - term = Async; - break gather; - "|" => - continue gather; - } - return (nil, nil); - } - - if(word == "|") - return (nil, nil); - - return (ref Pipeline(revc(cmds), term), words); -} - -revp(arg: list of ref Pipeline): list of ref Pipeline -{ - ret: list of ref Pipeline; - - while(arg != nil) { - ret = hd arg :: ret; - arg = tl arg; - } - return ret; -} - -parseit(words: list of string): list of ref Pipeline -{ - ret: list of ref Pipeline; - cur: ref Pipeline; - - while(words != nil) { - (cur, words) = getpipe(words); - if(cur == nil){ - sys->fprint(stderr, "sh9: syntax error\n"); - return nil; - } - ret = cur :: ret; - } - return revp(ret); -} - -# Runner. - -runpipeline(ctx: ref Context, pipeline: ref Pipeline) -{ - if(pipeline.term == Async) - sys->pctl(sys->NEWPGRP, nil); - pid := startpipeline(ctx, pipeline); - if(pid < 0) - return; - if(pipeline.term == Seq) - waitfor(pid); -} - -startpipeline(ctx: ref Context, pipeline: ref Pipeline): int -{ - pid := 0; - cmds := pipeline.cmds; - first := 1; - inpipe, outpipe: ref Sys->FD; - while(cmds != nil) { - last := tl cmds == nil; - cmd := hd cmds; - - infd: ref Sys->FD; - if(!first) - infd = inpipe; - else if(cmd.inf != nil){ - infd = sys->open(cmd.inf, Sys->OREAD); - if(infd == nil){ - sys->fprint(stderr, "sh9: can't open %s: %r\n", cmd.inf); - return -1; - } - } - - outfd: ref Sys->FD; - if(!last){ - fds := array[2] of ref Sys->FD; - if(sys->pipe(fds) < 0){ - sys->fprint(stderr, "sh9: can't make pipe: %r\n"); - return -1; - } - outpipe = fds[0]; - outfd = fds[1]; - fds = nil; - }else if(cmd.outf != nil){ - if(cmd.append){ - outfd = sys->open(cmd.outf, Sys->OWRITE); - if(outfd != nil) - sys->seek(outfd, big 0, Sys->SEEKEND); - } - if(outfd == nil) - outfd = sys->create(cmd.outf, Sys->OWRITE, 8r666); - if(outfd == nil){ - sys->fprint(stderr, "sh9: can't open %s: %r\n", cmd.outf); - return -1; - } - } - - rpid := chan of int; - spawn mkprog(ctx, cmd.args, infd, outfd, rpid); - pid = <-rpid; - infd = nil; - outfd = nil; - - inpipe = outpipe; - outpipe = nil; - - first = 0; - cmds = tl cmds; - } - return pid; -} - -runit(ctx: ref Context, pipes: list of ref Pipeline) -{ - while(pipes != nil) { - pipeline := hd pipes; - pipes = tl pipes; - if(pipeline.term == Seq) - runpipeline(ctx, pipeline); - else - spawn runpipeline(ctx, pipeline); - } -} - -strchr(s: string, c: int): int -{ - ln := len s; - for (i := 0; i < ln; i++) - if (s[i] == c) - return i; - return -1; -} - -# PROFILE: con "/lib/profile"; -PROFILE: con "/lib/infernoinit"; - -startup(ctxt: ref Context) -{ - if (env == nil) - return; - # if (env->getenv("home") != nil) - # return; - home := gethome(); - env->setenv("home", home); - escript(ctxt, PROFILE); - escript(ctxt, home + PROFILE); -} - -escript(ctxt: ref Context, file: string) -{ - fd := sys->open(file, Sys->OREAD); - if (fd != nil) - script(ctxt, file); -} - -gethome(): string -{ - fd := sys->open("/dev/user", sys->OREAD); - if(fd == nil) - return "/"; - buf := array[128] of byte; - n := sys->read(fd, buf, len buf); - if(n < 0) - return "/"; - return "/usr/" + string buf[0:n]; -} - -getusername(): string -{ - fd := sys->open("/dev/user", sys->OREAD); - if(fd == nil) - return "/"; - buf := array[128] of byte; - n := sys->read(fd, buf, len buf); - if(n < 0) - return "?"; - return string buf[0:n]; -} - -getcwd(): string -{ - gwd := load Workdir Workdir->PATH; - if (gwd == nil) { - sys->fprint(stderr, "pwd: cannot load %s: %r\n", Workdir->PATH); - raise "fail:bad module"; - } - - wd := gwd->init(); - if(wd == nil) { - sys->fprint(stderr, "pwd: %r\n"); - raise "fail:error"; - } - return wd; -} diff --git a/sh92.b b/sh92.b deleted file mode 100644 index bce58c3..0000000 --- a/sh92.b +++ /dev/null @@ -1,208 +0,0 @@ -implement Sh92; - -include "sys.m"; -include "draw.m"; -include "sh9util.m"; -include "sh9parser.m"; - -sys: Sys; -sh9u: Sh9Util; -sh9p: Sh9Parser; - -Sh92: module { - init: fn(nil: ref Draw->Context, nil: list of string); -}; - -ModProc: adt { - name: string; - start: int; -}; - -ModVar: adt { - name: string; - val: string; -}; - -ShModule: adt { - global_vars: list of ref ModVar; - procs: list of ref ModProc; -}; - -GrammarNode: import sh9p; -TokNode: import sh9p; -mk_tok: import sh9p; -set_last_tok: import sh9p; -print_toks: import sh9p; -parse_toks: import sh9p; - -reverse_list: import sh9u; -to_array: import sh9u; - -S_UNKNOWN: con "UNK"; -S_ID: con "ID"; -S_STR: con "STR"; -S_EQ: con "EQ"; -S_DOL: con "DOL"; -S_COLON: con "COLON"; -S_SEMIC: con "SEMIC"; -S_LPAR: con "LPAR"; -S_RPAR: con "RPAR"; -S_LCURLY: con "LCURLY"; -S_RCURLY: con "RCURLY"; -S_DQSTR: con "DQSTR"; -S_SQSTR: con "SQSTR"; -S_DQTE: con "DQTE"; -S_SQTE: con "SQTE"; -S_SP: con "SP"; -S_TAB: con "TAB"; -S_EOL: con "EOL"; - -S_STMT: con "STMT"; -S_EXPR: con "EXPR"; -S_CALL: con "CALL"; - -tokenize(line: string, line_n: int): array of ref TokNode { - toks : list of ref TokNode; - last_tok: TokNode; - last_tok.start = -1; - last_tok.line = -1; - last_tok.tok = ""; - last_tok.typ = S_UNKNOWN; - - for (i := 0; i < len line; i++) { - if (last_tok.typ == S_DQSTR) { - case (line[i:i+1]) { - "\"" => { - l := len last_tok.tok; - if ((last_tok.tok[l-1:] != "\\") || ((last_tok.tok[l-1:] == "\\") && (last_tok.tok[l-2:l-1] == "\\"))) { - # end of str - last_tok.tok = last_tok.tok + line[i:i+1]; - (last_tok, toks) = set_last_tok(ref last_tok, toks); - } else { - # escaped dqte, just continue - last_tok.tok = last_tok.tok + line[i:i+1]; - } - }; - * => { - last_tok.tok = last_tok.tok + line[i:i+1]; - } - } - } else if (last_tok.typ == S_SQSTR) { - case (line[i:i+1]) { - "'" => { - l := len last_tok.tok; - if ((last_tok.tok[l-1:] != "\\") || ((last_tok.tok[l-1:] == "\\") && (last_tok.tok[l-2:l-1] == "\\"))) { - # end of str - last_tok.tok = last_tok.tok + line[i:i+1]; - (last_tok, toks) = set_last_tok(ref last_tok, toks); - } else { - # escaped sqte, just continue - last_tok.tok = last_tok.tok + line[i:i+1]; - } - }; - * => { - last_tok.tok = last_tok.tok + line[i:i+1]; - } - } - } else { - case (line[i:i+1]) { - " " or "\t" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - }; - "=" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, "=", S_EQ) :: toks; - }; - ";" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, ";", S_SEMIC) :: toks; - }; - "$" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, "$", S_DOL) :: toks; - }; - "(" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, "(", S_LPAR) :: toks; - }; - ")" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, ")", S_RPAR) :: toks; - }; - "{" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, "{", S_LCURLY) :: toks; - }; - "}" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, "}", S_RCURLY) :: toks; - }; - "\"" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - last_tok.start = i; - last_tok.line = line_n; - last_tok.typ = S_DQSTR; - last_tok.tok = last_tok.tok + line[i:i+1]; - }; - "'" => { - (last_tok, toks) = set_last_tok(ref last_tok, toks); - last_tok.start = i; - last_tok.line = line_n; - last_tok.typ = S_SQSTR; - last_tok.tok = last_tok.tok + line[i:i+1]; - }; - * => { - if (last_tok.start == -1) { - last_tok.start = i; - last_tok.line = line_n; - last_tok.typ = S_ID; - } - last_tok.tok = last_tok.tok + line[i:i+1]; - }; - } - } - } - (last_tok, toks) = set_last_tok(ref last_tok, toks); - toks = ref mk_tok(i, line_n, "", S_EOL) :: toks; - toks = reverse_list(toks); - return to_array(toks); -} - -stmt_assign(toks: array of ref TokNode) { - sys->print("ASSIGN STMT\n"); -} - -stmt_cmd_call(toks: array of ref TokNode) { - sys->print("CMD CALL\n"); -} - -empty(toks: array of ref TokNode) { - sys->print("EMPTY\n"); -} - -init(ctxt: ref Draw->Context, argv: list of string) { - sys = load Sys Sys->PATH; - sh9u = load Sh9Util Sh9Util->PATH; - sh9p = load Sh9Parser Sh9Parser->PATH; - - assign_g_semic : GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_SEMIC}, S_UNKNOWN, stmt_assign); - assign_g_eol : GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_EOL}, S_UNKNOWN, stmt_assign); - sqstr_expr_g: GrammarNode = (array [] of {S_SQSTR}, S_EXPR, empty); - str_expr_g: GrammarNode = (array [] of {S_STR}, S_EXPR, empty); - cmd_call_g: GrammarNode = (array [] of {S_ID, S_EQ, S_EXPR, S_SEMIC}, S_UNKNOWN, stmt_cmd_call); - grammar: array of ref GrammarNode; - grammar = array [] of {ref assign_g_semic, ref assign_g_eol, ref sqstr_expr_g, ref str_expr_g, ref cmd_call_g}; - - toks1 := tokenize("A = 'smth \"test\" ';", 0); - print_toks(toks1); - sys->print("Parse\n"); - parse_toks(toks1, grammar); - sys->print("Parse done\n"); - - # toks2 := tokenize("echo \"smth \" \"test\";", 0); - # print_toks(toks2); - # toks3 := tokenize("if test x\"a\" = x\"b\"; then echo \"1\"; fi", 0); - # print_toks(toks3); - # toks4 := tokenize("echo 'smth2' 'test';", 0); - # print_toks(toks4); -} diff --git a/sh9parser.b b/sh9parser.b deleted file mode 100644 index fcae119..0000000 --- a/sh9parser.b +++ /dev/null @@ -1,130 +0,0 @@ -implement Sh9Parser; - -include "sys.m"; -include "sh9parser.m"; -include "sh9util.m"; - -sys: Sys; -S_UNKNOWN: con "UNK"; - -sh9u: Sh9Util; - -reverse_list: import sh9u; -to_array: import sh9u; - -GrammarNode.print_expr(gn: self ref GrammarNode) { - lg:= len gn.expr; - for (i:=0; iprint("%s ", gn.expr[i]); - } - if (gn.transform == S_UNKNOWN) { - sys->print("\n"); - } else { - sys->print("-> %s\n", gn.transform); - } -} - -mk_tok(start: int, line: int, tok: string, typ: string) : TokNode { - tok_node: TokNode; - tok_node.start = start; - tok_node.line = line; - tok_node.tok = tok; - tok_node.typ = typ; - return tok_node; -} - -set_last_tok(last_tok: ref TokNode, toks: list of ref TokNode): (TokNode, list of ref TokNode) { - ret_tok: TokNode; - ret_tok = *last_tok; - if (last_tok.typ != S_UNKNOWN) { - toks = last_tok :: toks; - ret_tok.typ = S_UNKNOWN; - ret_tok.start = -1; - ret_tok.tok = ""; - ret_tok.line = -1; - } - return (ret_tok, toks); -} - -print_toks(toks: array of ref TokNode) { - lt := len toks; - for (i := 0; i < lt; i ++) { - tok := toks[i]; - sys->print("[%d/%d] %s (%s)\n", i, lt, tok.typ, tok.tok); - } -} - -print_toks_short(toks: array of ref TokNode) { - lt := len toks; - for (i := 0; i < lt; i ++) { - tok := toks[i]; - sys->print("%s ", tok.typ); - } - sys->print("\n"); -} - -check_grammar_node_match(toks: array of ref TokNode, gn: ref GrammarNode): int { - lt:= len toks; - lg:= len gn.expr; - if (lg > lt) { - return 0; - } - #sys->print("Checking grammar "); - gn.print_expr(); - #sys->print("Against "); - print_toks(toks); - for (i:= 0; i < lg; i ++) { - if (toks[i].typ != gn.expr[i]) { - return 0; - } - } - return 1; -} - -replace_toks(src: array of ref TokNode, replace_start: int, replace_len: int, replace_with: array of ref TokNode): array of ref TokNode { - src_len:= len src; - new_toks: list of ref TokNode; - with_len:= len replace_with; - for (i:=0; iprint("Loop %d: ", ctr); - print_toks_short(toks); - ctr ++; - changed = 0; - fast: for (i := 0; i <= lt; i ++) { - for (j := 0; j < lgns; j++) { - gj:= g[j]; - if (check_grammar_node_match(toks[lt - i:], gj) == 1) { - sys->print("Something matched !\n"); - gj.print_expr(); - sys->print("Before replace: "); - print_toks_short(toks); - gj.callback(toks[lt-i: lt-i+len gj.expr]); - toks = replace_toks(toks, lt-i, len gj.expr, array[] of {ref mk_tok(toks[lt - i].start, toks[lt - i].line, "", gj.transform)}); - sys->print("After replace: "); - changed = 1; - break fast; - } - } - } - } while(changed); - return toks; -} diff --git a/sh9parser.m b/sh9parser.m deleted file mode 100644 index cbad2f6..0000000 --- a/sh9parser.m +++ /dev/null @@ -1,28 +0,0 @@ -Sh9Parser: module -{ -PATH: con "sh9parser.dis"; -DESCR: con "Mostly generic parser for sh9"; - -mk_tok: fn(start: int, line: int, tok: string, typ: string) : TokNode; -set_last_tok: fn(last_tok: ref TokNode, toks: list of ref TokNode): (TokNode, list of ref TokNode); -print_toks: fn(toks: array of ref TokNode); -print_toks_short: fn(toks: array of ref TokNode); -check_grammar_node_match: fn(toks: array of ref TokNode, gn: ref GrammarNode): int; -replace_toks: fn(src: array of ref TokNode, replace_start: int, replace_len: int, replace_with: array of ref TokNode): array of ref TokNode; -parse_toks: fn(toks: array of ref TokNode, g: array of ref GrammarNode): array of ref TokNode; - -TokNode: adt { - start: int; - line: int; - tok: string; - typ: string; -}; - -GrammarNode: adt { - expr: array of string; - transform: string; - - callback: ref fn(toks: array of ref TokNode); - print_expr: fn(gn: self ref GrammarNode); -}; -}; diff --git a/sh9util.b b/sh9util.b deleted file mode 100644 index f74032e..0000000 --- a/sh9util.b +++ /dev/null @@ -1,26 +0,0 @@ -implement Sh9Util; - -include "sh9util.m"; - -reverse_list[T](toks: list of T): list of T -{ - lt := len toks; - out : list of T; - for (i := 0; i < lt; i ++) { - tok := hd toks; - #toks = tl toks; - out = tok :: out; - } - return out; -} - -to_array[T](toks: list of T): array of T { - lt := len toks; - out := array[lt] of T; - for (i := 0; i < lt; i ++) { - tok := hd toks; - toks = tl toks; - out[i] = tok; - } - return out; -} diff --git a/sh9util.m b/sh9util.m deleted file mode 100644 index aa44c3f..0000000 --- a/sh9util.m +++ /dev/null @@ -1,8 +0,0 @@ -Sh9Util: module -{ -PATH: con "sh9util.dis"; -DESCR: con "Utility functions for sh9"; - -reverse_list: fn[T](toks: list of T): list of T; -to_array: fn[T](toks: list of T): array of T; -}; -- cgit v1.2.3