.TH SH 2.SH NAMESh \- module interface to the shell.SH SYNOPSIS.EX.ps -1.vs -1include "sh.m";sh := load Sh Sh->PATH;Context, Listnode: import sh; system: fn(drawctxt: ref Draw->Context, cmd: string): string;run: fn(drawctxt: ref Draw->Context, argv: list of string): string;parse: fn(s: string): (ref Cmd, string);cmd2string: fn(c: ref Cmd): string;list2stringlist: fn(nl: list of ref Listnode): list of string;stringlist2list: fn(sl: list of string): list of ref Listnode; Context: adt { new: fn(drawcontext: ref Draw->Context): ref Context; get: fn(c: self ref Context, name: string): list of ref Listnode; set: fn(c: self ref Context, name: string, value: list of ref Listnode); setlocal: fn(c: self ref Context, name: string, value: list of ref Listnode); envlist: fn(c: self ref Context): list of (string, list of ref Listnode); push, pop: fn(c: self ref Context); copy: fn(c: self ref Context, copyenv: int): ref Context; run: fn(c: self ref Context, args: list of ref Listnode, last: int): string; addmodule: fn(c: self ref Context, name: string, mod: Shellbuiltin); addbuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); removebuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); addsbuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); removesbuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); fail: fn(c: self ref Context, ename, msg: string); options: fn(c: self ref Context): int; setoptions: fn(c: self ref Context, flags, on: int): int;}; Listnode: adt { cmd: ref Cmd; word: string;}; Cmd: adt { # private data}; Shellbuiltin: module { initbuiltin: fn(ctxt: ref Context, sh: Sh): string; whatis: fn(ctxt: ref Sh->Context, sh: Sh, name: string, wtype: int): string; runbuiltin: fn(ctxt: ref Context, sh: Sh, cmd: list of ref Listnode, last: int): string; runsbuiltin: fn(ctxt: ref Context, sh: Sh, cmd: list of ref Listnode): list of ref Listnode; getself: fn(): Shellbuiltin;}; .ps +1.vs +1.EE.SH DESCRIPTION.I Shis a command-line interpreter and a scripting language;it also presents a module interface to allow Limbomodules to access its functionality at a lower level.The.B Shmodule can be used in several different ways.At the simplest level, it can be run as a command-lineprogram; for details of this, see.IR sh (1).The simplest access at the Limbo level is throughthe.B systemfunction, which given a.I draw.B Context(see.IR draw-context (2))and a stringexecutes the.I shcommand contained in.I sand returns its result. It catches any exceptions raised by the command.Almost as simple is.BR exec ,which runs.I argvas a command, taking the first word as the command to beexecuted (it can be a braced block) and giving the rest as arguments,catching any exceptions raised..PPAlthough program arguments are passed to external programsas lists of strings, at the.B Shmodule level, an argument list is held as a.BR "list of ref Listnode" .A.B Listnodeholds either a simple string, or a braced blockthat has been parsed by the shell. Sometimes it can holdboth; in this case the string and the block both representthe same thing..B Parseconverts from a string to a.B Cmd(a braced block). It returns a tuple.RI ( cmd ,\ error )where.I cmdholds the parsed block,and.I erroris non-empty if an error has occurred doing so..B Cmd2stringperforms the opposite conversion; it returnsa string that when parsed will yield the same commandblock it was passed.The utility functions.B List2stringlistand.B stringlist2listconvert from and to a.B list of ref Listnodeto or from a.B list of stringrespectively..PPA.B Contextholds all the state information needed by a currently running.I shprocess; this adt holds current values of environment variablesand a list of currently loaded modules and builtin commands.It is specific to the process within which it was created.If it is desired to run.I shcommands in a newly spawned process, a new.B Contextmust be created, or a copy of an existing Context made (makingsure to synchronise access until the copy has been made)..TP 10.BI Context.new( drawcontext ).B Newcreates a new context..I Drawcontextrepresents the current graphics contextwithin which.I shcommands will be run(see.IR draw-context (2))..TP.IB ctxt .get(\fPname\fP).B Getretrieves the value of environment variable.I namefrom.IR ctxt .It is retrieved from the innermost scope in whicha value for.I namehas been set..TP.IB ctxt .set(\fPname\fP,\ \fPvalue\fP).B Setsets the value of environment variable.I namein.IR ctxtto.IR value .It is set in the innermost scope in which a valuefor.I namehas been set, or the outermost level if it hasnot been set..TP.IB ctxt .setlocal(\fPname\fP,\ \fPvalue\fP)Similar to.B set()except that the value is set in the innermost scopethat has been pushed..TP.IB ctxt .envlist().B Envlistretrieves the list of all the environment variablescurrently in scope, and their values.It returns a list of.RI ( name ,\ value )tuples, where.I nameis the name of the variable and.I valueis its value..TP.IB ctxt .push().B Pushcreates a new innermost environment variable scope..TP.IB ctxt .pop().B Popdiscards the current innermost scope, losing thevalues of all variables that have been defined there.It is an error to.B popa context that has not been pushed.Care must be taken to ensure that a.B pushis always matched by a.BR pop.In particular, exceptions should be caught,the context popped, and the exception re-raised..TP.IB ctxt .copy(\fPcopyenv\fP)The shell's.B Contextis associated with a particular process;.B copyreturns a copy of.I ctxtassociated with the current process. If.I copyenvis non-zero, the whole environment will be copied - thisshould be set if the new process is to run asynchronously - i.e.if there is a chance that there might be two processes accessing thecontext in parallel. It is an error to copy a context if notwithin a new process..TP.IB ctxt .run(\fPargs\fP,\ \fPlast\fP).B Runexecutes a.I shcommand..I Lastshould be non-zero if this is the last timethat.B runwill be called, so.I shdoes not have to spawn a new process in orderto hide file redirection side-effects..TP.IB ctxt .addmodule(\fPname\fP,\ \fPmod\fP).B Addmoduleadds the.B Shellbuiltinmodule.I modto its list of builtin modules.The module will be initialised as described in``Builtin modules'', below..TP.IB ctxt .addbuiltin(\fPname\fP,\ \fPmod\fP).B Addbuiltinmay be called by a module that has previouslybeen loaded by.B addmoduleor by the.B load.I shcommand to add a new builtin commandto the shell. Any subsequent invocation of.I namewithin.I ctxtwill result in a call of.B runbuiltin()to.IR mod .Any attempt to redefine the command.RB `` builtin ''will be ignored..TP.IB ctxt .removebuiltin(\fPname\fP,\ \fPmod\fP).B Removebuiltinremoves.I namefrom the list of builtin commands in.IR ctxt .If.I namehad not previously been defined by.IR mod ,or had subsequently been replaced, thenthis function does nothing..TP.IB ctxt .addsbuiltin(\fPname\fP,\ \fPmod\fP).B Addsbuiltinmay be called by a module that has previouslybeen loaded by.B addmoduleor by the.B load.I shcommand to add a new builtin substitution operatorto the shell.Any subsequent invocation of.BI ${ name }within.I ctxtwill result in a call of.B runsbuiltin()to.IR mod ..TP.IB ctxt .removesbuiltin(\fPname\fP,\ \fPmod\fP).B Removesbuiltinremoves.I namefrom the list of builtin substitution operators in.IR ctxt .If.I namehad not previously been defined by.IR mod ,or had subsequently been replaced, thenthis function does nothing..TP.IB ctxt .fail(\fPename\fP,\ \fPmsg\fP).B Failprints.I msgto the standard error if message printingis currently enabled, and raisesthe exception.BI fail: ename\f1.\fP.TP.IB ctxt .options().B Optionsreturns a bitmask of the options currently enabled in.IR ctxt .The bits are defined by constants declared within.BR Context .They include:.RS.TP.IB ctxt .INTERACTIVE.I Shis currently being run from an interactive command-line..TP.IB ctxt .VERBOSEMessage printing is currently enabled..TP.IB ctxt .EXECPRINTCommands are printed to standard erroras they are executed..TP.IB ctxt .ERROREXITAn exception will be raised when the firstsimple command returns an error status..PPOptions are defined in the innermost scopeof.I ctxtand will be lost when it is.BR pop ped..RE.TP.IB ctxt .setoptions(\fPflags\fP,\ \fPon\fP).B Setoptionssets the specified.I flagswithin.IR ctxt ..I Flagsis a bitmask of options, as described in.BR options ,above. If.I onis non-zero, the specified bits will be set;otherwise they will be reset..B Setoptionsreturns the previously set options bitmask..SS Builtin modules.B Shellbuiltinspecifies the interface to a loadable.I shbuiltin module. Any Limbo module.I modadhering to thisinterface may be loaded into the shell..TP 10.IB mod ->initbuiltin(\fPctxt\fP,\ \fPsh\fP).B Initbuiltinis called when.I shloads.I modeither via the.B loadcommand, or via the.B loadmodule()function..I Ctxtis the context within which the builtin has beenloaded, and.I shis the.B Shmodule itself. When.B initbuiltinis called,.I modis expected to call.IB ctxt .addbuiltinand.IB ctxt .addsbuiltinto define any builtin commands and builtin substitutionoperators that it wants. If an error occurs oninitialisation,.B initbuiltinshould return a non-nil value; this will cause the load to fail..TP.IB mod ->runbuiltin(\fPctxt\fP,\ \fPsh\fP,\ \fPcmd\fP,\ \fPlast\fP).B Runbuiltinis invoked when.I shexecutes a command that has previously beendefined as a builtin command by.IR mod ..I Ctxtis the current execution context (which may not bethe original context passed to.BR initbuiltin() ),.I shis the running.B Shmodule, and.I cmdis the command to be executed..I Lastis true if this is the last command to be executedin the current process; it can be passed to.IB ctxt .run()as appropriate.The name of the command can be found in.BR "(hd cmd).word" ..B Runbuiltinreturns its exit status; by convention thisis the exit status of the last command executed.A non-nil exit status is usually treated as false.By convention, if an invalid set of arguments arepassed to a builtin command, a.B usageexception is raised by calling .IB ctxt .failwith.B "usage"and an explanatory usage message as arguments..TP.IB mod ->runsbuiltin(\fPctxt\fP,\ \fPsh\fP,\ \fPcmd\fP)Similar to.BR runbuiltin ,.B runsbuiltinis called when.I shencounters a builtin substitution operatorthat has previously been defined by.IR mod .It returns the list of values that will besubstituted in place of the operator..TP.IB mod ->getself().B Getselfshould return the.B Shellbuiltinmodule handle for.IR mod ,usually obtained by invoking.BR "load $self" .N.B. it is important that the value returnedby.B getselfis the same as that passed to.B addbuiltinor.BR addsbuiltin .As the Limbo.B loadoperator returns a different value each time,the value to be returned by.B getself()should be initialised once,during the call to Lines 1–500 of 560. Load more
.TH SH 2 .SH NAME Sh \- module interface to the shell .SH SYNOPSIS .EX .ps -1 .vs -1 include "sh.m"; sh := load Sh Sh->PATH; Context, Listnode: import sh; system: fn(drawctxt: ref Draw->Context, cmd: string): string; run: fn(drawctxt: ref Draw->Context, argv: list of string): string; parse: fn(s: string): (ref Cmd, string); cmd2string: fn(c: ref Cmd): string; list2stringlist: fn(nl: list of ref Listnode): list of string; stringlist2list: fn(sl: list of string): list of ref Listnode; Context: adt { new: fn(drawcontext: ref Draw->Context): ref Context; get: fn(c: self ref Context, name: string): list of ref Listnode; set: fn(c: self ref Context, name: string, value: list of ref Listnode); setlocal: fn(c: self ref Context, name: string, value: list of ref Listnode); envlist: fn(c: self ref Context): list of (string, list of ref Listnode); push, pop: fn(c: self ref Context); copy: fn(c: self ref Context, copyenv: int): ref Context; run: fn(c: self ref Context, args: list of ref Listnode, last: int): string; addmodule: fn(c: self ref Context, name: string, mod: Shellbuiltin); addbuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); removebuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); addsbuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); removesbuiltin: fn(c: self ref Context, name: string, mod: Shellbuiltin); fail: fn(c: self ref Context, ename, msg: string); options: fn(c: self ref Context): int; setoptions: fn(c: self ref Context, flags, on: int): int; }; Listnode: adt { cmd: ref Cmd; word: string; }; Cmd: adt { # private data }; Shellbuiltin: module { initbuiltin: fn(ctxt: ref Context, sh: Sh): string; whatis: fn(ctxt: ref Sh->Context, sh: Sh, name: string, wtype: int): string; runbuiltin: fn(ctxt: ref Context, sh: Sh, cmd: list of ref Listnode, last: int): string; runsbuiltin: fn(ctxt: ref Context, sh: Sh, cmd: list of ref Listnode): list of ref Listnode; getself: fn(): Shellbuiltin; }; .ps +1 .vs +1 .EE .SH DESCRIPTION .I Sh is a command-line interpreter and a scripting language; it also presents a module interface to allow Limbo modules to access its functionality at a lower level. The .B Sh module can be used in several different ways. At the simplest level, it can be run as a command-line program; for details of this, see .IR sh (1). The simplest access at the Limbo level is through the .B system function, which given a .I draw .B Context (see .IR draw-context (2)) and a string executes the .I sh command contained in .I s and returns its result. It catches any exceptions raised by the command. Almost as simple is .BR exec , which runs .I argv as a command, taking the first word as the command to be executed (it can be a braced block) and giving the rest as arguments, catching any exceptions raised. .PP Although program arguments are passed to external programs as lists of strings, at the .B Sh module level, an argument list is held as a .BR "list of ref Listnode" . A .B Listnode holds either a simple string, or a braced block that has been parsed by the shell. Sometimes it can hold both; in this case the string and the block both represent the same thing. .B Parse converts from a string to a .B Cmd (a braced block). It returns a tuple .RI ( cmd ,\ error ) where .I cmd holds the parsed block, and .I error is non-empty if an error has occurred doing so. .B Cmd2string performs the opposite conversion; it returns a string that when parsed will yield the same command block it was passed. The utility functions .B List2stringlist and .B stringlist2list convert from and to a .B list of ref Listnode to or from a .B list of string respectively. .PP A .B Context holds all the state information needed by a currently running .I sh process; this adt holds current values of environment variables and a list of currently loaded modules and builtin commands. It is specific to the process within which it was created. If it is desired to run .I sh commands in a newly spawned process, a new .B Context must be created, or a copy of an existing Context made (making sure to synchronise access until the copy has been made). .TP 10 .BI Context.new( drawcontext ) .B New creates a new context. .I Drawcontext represents the current graphics context within which .I sh commands will be run (see .IR draw-context (2)). .TP .IB ctxt .get(\fPname\fP) .B Get retrieves the value of environment variable .I name from .IR ctxt . It is retrieved from the innermost scope in which a value for .I name has been set. .TP .IB ctxt .set(\fPname\fP,\ \fPvalue\fP) .B Set sets the value of environment variable .I name in .IR ctxt to .IR value . It is set in the innermost scope in which a value for .I name has been set, or the outermost level if it has not been set. .TP .IB ctxt .setlocal(\fPname\fP,\ \fPvalue\fP) Similar to .B set() except that the value is set in the innermost scope that has been pushed. .TP .IB ctxt .envlist() .B Envlist retrieves the list of all the environment variables currently in scope, and their values. It returns a list of .RI ( name ,\ value ) tuples, where .I name is the name of the variable and .I value is its value. .TP .IB ctxt .push() .B Push creates a new innermost environment variable scope. .TP .IB ctxt .pop() .B Pop discards the current innermost scope, losing the values of all variables that have been defined there. It is an error to .B pop a context that has not been pushed. Care must be taken to ensure that a .B push is always matched by a .BR pop. In particular, exceptions should be caught, the context popped, and the exception re-raised. .TP .IB ctxt .copy(\fPcopyenv\fP) The shell's .B Context is associated with a particular process; .B copy returns a copy of .I ctxt associated with the current process. If .I copyenv is non-zero, the whole environment will be copied - this should be set if the new process is to run asynchronously - i.e. if there is a chance that there might be two processes accessing the context in parallel. It is an error to copy a context if not within a new process. .TP .IB ctxt .run(\fPargs\fP,\ \fPlast\fP) .B Run executes a .I sh command. .I Last should be non-zero if this is the last time that .B run will be called, so .I sh does not have to spawn a new process in order to hide file redirection side-effects. .TP .IB ctxt .addmodule(\fPname\fP,\ \fPmod\fP) .B Addmodule adds the .B Shellbuiltin module .I mod to its list of builtin modules. The module will be initialised as described in ``Builtin modules'', below. .TP .IB ctxt .addbuiltin(\fPname\fP,\ \fPmod\fP) .B Addbuiltin may be called by a module that has previously been loaded by .B addmodule or by the .B load .I sh command to add a new builtin command to the shell. Any subsequent invocation of .I name within .I ctxt will result in a call of .B runbuiltin() to .IR mod . Any attempt to redefine the command .RB `` builtin '' will be ignored. .TP .IB ctxt .removebuiltin(\fPname\fP,\ \fPmod\fP) .B Removebuiltin removes .I name from the list of builtin commands in .IR ctxt . If .I name had not previously been defined by .IR mod , or had subsequently been replaced, then this function does nothing. .TP .IB ctxt .addsbuiltin(\fPname\fP,\ \fPmod\fP) .B Addsbuiltin may be called by a module that has previously been loaded by .B addmodule or by the .B load .I sh command to add a new builtin substitution operator to the shell. Any subsequent invocation of .BI ${ name } within .I ctxt will result in a call of .B runsbuiltin() to .IR mod . .TP .IB ctxt .removesbuiltin(\fPname\fP,\ \fPmod\fP) .B Removesbuiltin removes .I name from the list of builtin substitution operators in .IR ctxt . If .I name had not previously been defined by .IR mod , or had subsequently been replaced, then this function does nothing. .TP .IB ctxt .fail(\fPename\fP,\ \fPmsg\fP) .B Fail prints .I msg to the standard error if message printing is currently enabled, and raises the exception .BI fail: ename\f1.\fP .TP .IB ctxt .options() .B Options returns a bitmask of the options currently enabled in .IR ctxt . The bits are defined by constants declared within .BR Context . They include: .RS .TP .IB ctxt .INTERACTIVE .I Sh is currently being run from an interactive command-line. .TP .IB ctxt .VERBOSE Message printing is currently enabled. .TP .IB ctxt .EXECPRINT Commands are printed to standard error as they are executed. .TP .IB ctxt .ERROREXIT An exception will be raised when the first simple command returns an error status. .PP Options are defined in the innermost scope of .I ctxt and will be lost when it is .BR pop ped. .RE .TP .IB ctxt .setoptions(\fPflags\fP,\ \fPon\fP) .B Setoptions sets the specified .I flags within .IR ctxt . .I Flags is a bitmask of options, as described in .BR options , above. If .I on is non-zero, the specified bits will be set; otherwise they will be reset. .B Setoptions returns the previously set options bitmask. .SS Builtin modules .B Shellbuiltin specifies the interface to a loadable .I sh builtin module. Any Limbo module .I mod adhering to this interface may be loaded into the shell. .TP 10 .IB mod ->initbuiltin(\fPctxt\fP,\ \fPsh\fP) .B Initbuiltin is called when .I sh loads .I mod either via the .B load command, or via the .B loadmodule() function. .I Ctxt is the context within which the builtin has been loaded, and .I sh is the .B Sh module itself. When .B initbuiltin is called, .I mod is expected to call .IB ctxt .addbuiltin and .IB ctxt .addsbuiltin to define any builtin commands and builtin substitution operators that it wants. If an error occurs on initialisation, .B initbuiltin should return a non-nil value; this will cause the load to fail. .TP .IB mod ->runbuiltin(\fPctxt\fP,\ \fPsh\fP,\ \fPcmd\fP,\ \fPlast\fP) .B Runbuiltin is invoked when .I sh executes a command that has previously been defined as a builtin command by .IR mod . .I Ctxt is the current execution context (which may not be the original context passed to .BR initbuiltin() ), .I sh is the running .B Sh module, and .I cmd is the command to be executed. .I Last is true if this is the last command to be executed in the current process; it can be passed to .IB ctxt .run() as appropriate. The name of the command can be found in .BR "(hd cmd).word" . .B Runbuiltin returns its exit status; by convention this is the exit status of the last command executed. A non-nil exit status is usually treated as false. By convention, if an invalid set of arguments are passed to a builtin command, a .B usage exception is raised by calling .IB ctxt .fail with .B "usage" and an explanatory usage message as arguments. .TP .IB mod ->runsbuiltin(\fPctxt\fP,\ \fPsh\fP,\ \fPcmd\fP) Similar to .BR runbuiltin , .B runsbuiltin is called when .I sh encounters a builtin substitution operator that has previously been defined by .IR mod . It returns the list of values that will be substituted in place of the operator. .TP .IB mod ->getself() .B Getself should return the .B Shellbuiltin module handle for .IR mod , usually obtained by invoking .BR "load $self" . N.B. it is important that the value returned by .B getself is the same as that passed to .B addbuiltin or .BR addsbuiltin . As the Limbo .B load operator returns a different value each time, the value to be returned by .B getself() should be initialised once, during the call to