1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
|
.TH MASH 1
.SH NAME
mash \- programmable shell
.SH SYNOPSIS
.B mash
[
.B -denx
][
.BI -c command
] [
.I file
[
.I arg ...
]]
.SH DESCRIPTION
.I Mash
is an older alternative to the original Inferno shell
(now
.IR tiny (1)).
.I Mash
is a programmable shell that also allows the definition of simple dependency
rules, resembling those of Unix
.IR make .
It executes commands read from standard input
or a file or, with the
.B -c
flag, from
.IR mash 's
argument list. Its syntax and
semantics are similar to that of Plan 9's
.IR rc .
.SS Invocation
If
.I mash
is started with no arguments it reads commands from standard
input. Otherwise its first non-flag argument is the name of a file from
which to read commands (but see
.B -c
below). Subsequent arguments
become the initial value of
.BR $args .
Mash accepts the following
command-line flags.
.PD 0
.TF "-c string"
.TP
.BI -c " string"
Commands are read from string.
.TP
.B -d
Dump parsed commands before execution.
.TP
.B -e
Fail if a top level command does.
.TP
.B -n
Parse but do not execute.
.TP
.B -x
Print each simple command before executing it.
.PD
.PP
If invoked without arguments
.I mash
first runs the commands found in
.BR /lib/mashinit .
.SS "Command Lines"
Each command is terminated with an ampersand or a semicolon (& or ;).
When reading from
.B /dev/cons
a newline
not escaped with a backslash (\\) is treated as a semicolon.
.I Mash
does not
wait for a command followed by
.B &
to finish executing before starting the
following command.
.PP
A number-sign (#) and any following characters up to (but not including) the next newline are
ignored, except in quotation marks.
.SS "Simple Commands"
A simple command is a sequence of words interspersed with I/O
redirections. If the first word is the name of a
.I mash
function or of one of
.IR mash 's
built-in commands, it is executed by
.IR mash .
Otherwise, if the name
starts with a slash
.RB ( / ),
it must be the path name of a Dis
file to be loaded
and executed. Names containing no initial slash are searched for in the
current directory and then in
.BR /dis .
The
.B .dis
extension need not be
supplied.
.PP
The keywords are
.EX
case else fn for hd if in len rescue tl while
.EE
.SS Words and Variables
A number of constructions may be used where
.IR mash 's
syntax requires a
word to appear. In many cases a construction's value will be a list of
strings rather than a single string.
.PP
The simplest kind of word is the unquoted word: a sequence of one or
more characters none of which is a blank, tab, newline, or any of the
following:
.EX
# : ; ! ~ @ & | ^ $ = " ` ' { } ( ) < >
.EE
An unquoted word that contains any of the characters
.BR * ,\ ?
or
.B [
is a pattern
for matching against file names. The character
.B *
matches any sequence of
characters,
.B ?
matches any single character, and
.B [
.I class
.B ]
matches any
character in the class. The class may also contain pairs of characters
separated by
.BR \- ,
standing for all characters lexically between the two. The
character
.B /
must appear explicitly in a pattern. A pattern is replaced by a
list of words, one for each path name matched, except that a pattern
matching no names is not replaced by the empty list, but rather stands for
itself. Pattern matching is done after all other operations. Thus,
.EX
x=/tmp; echo $x^/*.c;
.EE
matches
.BR /tmp/*.c ,
rather than matching
.B /*.c
and then prefixing
.BR /tmp .
.PP
A quoted word is a sequence of characters surrounded by single quotes
.RB ( ' ).
A single quote is escaped with a backslash.
.PP
Each of the following is a word.
.PD 0
.HP
.BI $ identifier
.br
The identifier after the
.B $
is the name of a variable whose value is
substituted. Variable values are lists of strings. It is an error if the
named variable has never been assigned a value.
.HP
.BI $ number
.br
See the description of rules for the
.IR mash-make (1)
builtin.
.HP
.B $"\c
.I identifier
.br
The value is a single string containing the components of the named
variable separated by spaces.
.HP
.BI `{ commands }
.br
.I mash
executes the commands and reads the standard output, splitting
it into a list of words, using the whitespace characters (space, tab,
newline and carriage return) as separators.
.HP
.B
"{\c
.IB commands }
.br
.I mash
executes the commands and reads the standard output, splitting
it into a list of words, using the whitespace characters (space, tab,
newline and carriage return) as separators.
.HP
.BI <{ commands }
.HP
.BI >{ commands }
.br
The commands are executed asynchronously with their standard
output or standard input connected to a pipe. The value of the word
is the name of a file referring to the other end of the pipe. This
allows the construction of non-linear pipelines. For example, the
following runs two commands
.B old
and
.B new
and uses
.B cmp
to compare their outputs
.EX
cmp <{old} <{new};
.EE
.TP
.BI ( expr )
.I mash
evaluates
.I expr
as an expression. The value is a (possibly null) list of words.
Expressions are described in detail below.
.HP
.IB word ^ word
.br
The
.B ^
operator concatenates its two operands. If either operand is a
singleton, the concatenation is distributive. Otherwise the lists are
concatenated pairwise.
.PD
.SS Free Carets
In most circumstances,
.I mash
will insert the
.B ^
operator automatically
between words that are not separated by white space. Whenever one of
.B $
.BR ' or
.B `
(dollar, single quote or back quote)
follows a quoted or unquoted word or an unquoted word follows a
quoted word with no intervening blanks or tabs, a
.B ^
is inserted between
the two. If an unquoted word immediately follows a
.B $
and contains a
character other than an alphanumeric, or underscore, a
.B ^
is inserted before
the first such character. Thus
.IP
.B limbo -$flags $stem.b
.LP
is equivalent to
.IP
.B limbo -^$flags $stem^.b
.SS I/O Redirections
The sequence
.BI > file
redirects the standard output file (file descriptor 1,
normally
.BR /dev/cons )
to the named
.IR file ;
.BI >> file
appends standard
output to the file. The standard input file (file descriptor 0, also normally
.BR /dev/cons )
may be redirected from a file by the sequence
.BR <file .
The
sequence
.B <>file
opens the file for read/write and associates both file
descriptor 0 and 1 with it.
.SH Compound Commands
A pair of commands separated by a pipe operator
.RB ( | )
is a command. The
standard output of the left command is sent through a pipe to the
standard input of the right command.
.PP
Each of the following is a command.
.PD 0
.HP
.B if (
.I expr
.B )
.I command1
.HP
.B if (
.I expr
.B )
.I command1
.B else
.I command2
.br
The
.I expr
is evaluated and if the result is not null, then
.I command1
is executed. In the second form
.I command2
is executed if
the result is null.
.HP
.B for (
.I name
.B in
.I list
.BI ) command
.br
The
.I command
is executed once for each word in
.I list
with that
word assigned to
.IR name .
.HP
.B while (
.I expr
.B )
.I command
.br
The
.I expr
is evaluated repeatedly until its value is null. Each time it
evaluates to non-null, the command is executed.
.HP
.B case
.I expr
.B {
.I pattern-list
.B =>
.I command ...
.B }
.br
.HP
.B case
.I expr-list
.B {
.I pattern
.B =>
.I command ...
.B }
.br
In the first form of the command the
.I expr
is matched against a series of lists of regular expressions (See
.IR regex (2)).
The command associated with the matching expression is executed.
In the second form the
.I command
associated with the first pattern to match one of the words in
.I expr-list
is executed. An
.I expr-list
will never match a
.IR pattern-list .
.HP
.BI { commands }
.HP
.BI @{ commands }
.br
Braces serve to alter the grouping of commands implied by operator
priorities. The body is a sequence of commands separated by
.B &
or
.BR ; .
The second form is executed with a new scope. Either form can be
followed by redirections.
.HP
.BI fn name { list }
.HP
.BI fn name
.br
The first form defines a function with the given
.IR name .
Subsequently,
whenever a command whose first word is
.I name
is encountered, the
current value of the remainder of the command's word list will be
assigned to the local variable
.BR args ,
in a new scope, and
.I mash
will execute the list. The second form removes
.IR name 's
function definition.
.HP
.IB name = list
.HP
.IB name := list
.br
The first form is an assignment to a variable. If the name is currently
defined as a local variable its value will be updated. Otherwise a
global variable with the given name will be defined or updated. The
second form is an explicit definition or update of a local variable.
.HP
.IB list : list
.HP
.IB list : list { commands }
.HP
.IB word :~ word { commands }
.br
These forms define dependencies and rules for the
.I make
loadable
builtin. The first form defines a simple dependency, the second a
dependency with an explicit rule. The third form defines an implicit
rule where the left-hand word is a file pattern, the right-hand word is
the prerequisite. The right-hand word and the commands can
contain references to the characters matched by the
.B *
meta-character
in the pattern
.RB ( $1
evaluates to the characters matched by the first
.BR * ,
.B $2
the second and so on;
.B $0
is the entire match).
.PD
.SS Expressions
Expressions evaluate to possibly null lists of strings. A word is an
expression. An expression may take one of the following forms
.PD 0
.HP
.BI ( " expr " )
.br
Parentheses are used for grouping.
.HP
.BI hd " expr"
.HP
.BI tl " expr"
.HP
.BI len " expr"
.HP
.BI ! " expr"
.br
.I hd
is the first element of a list,
.I tl
the remainder.
.I len
is the length of
a list. Both evaluate to the null list if their operand is a null list.
.B !
is the not operator and evaluates to true for a null list or to a null list
otherwise.
.HP
.IB expr " ^ " expr
.HP
.IB expr " :: " expr
.HP
.IB expr " == " expr
.HP
.IB expr " != " expr
.HP
.IB expr " ~ " expr
.br
.B ^
is concatenation (as defined above),
.B ::
is list concatenation,
.B ==
and
.B !=
are the equality operators evaluating to true or the null list,
depending on the equality or inequality of the two operands.
.B ~
is the match operator, true if a singleton string matches one of a list of
regular expressions, or one of a list of strings matches a regular
expression. (If neither operand is a singleton it evaluates to the null
list.)
.B ^
has the highest precedence, followed by
.B ::
followed by the
other three. All associate to the left except
.BR :: .
.SS Built-in Commands
.I Mash
supports loadable modules of builtins. The
.I Mashbuiltin
module definition and description is in
.BR mash.m .
One such module,
.IR builtins ,
is loaded before
.I mash
begins parsing. This module defines the following commands
.PD 0
.HP
.B env
.br
Print global and local variables. Global variables are displayed using a
.IB name = value
format, and local variables using a
.IB name := value
format.
.HP
.B eval
.br
Concatenate arguments and use as mash input.
.HP
.B exit
.br
Cause
.I mash
to raise an
.B "exit"
exception.
.HP
.B load
.I file
.br
Load a builtin module. The
.I file
must be a module with type
.BR Mashbuiltin .
The argument
.I file
is assumed to contain a path to the loadable module. If no such module
is found then the string
.B /dis/lib/mash/
is prepended to
.I file
and the load is retried.
.HP
.B prompt
.HP
.BI prompt text
.HP
.BI prompt "text contin"
.br
When called with no arguments causes the current value of the
.I mash
prompt to be printed to standard output. The default value is
.BR mash% .
The second form sets a new prompt. The final form sets a new prompt
and additionally a continuation string. Initially the continuation
string is set to a single tab character.
.I Mash
uses the continuation string in place of the prompt string to indicate that
the preceding line has been continued by escaping with a final backslash
.RB ( \e )
character.
.HP
.BI quote args...
.br
Print arguments quoted as input for
.IR mash .
.HP
.BI "run -" [ denx "] file [arg...]"
.br
Interpret a file as input to
.IR mash .
.HP
.BI time "cmd [arg...]"
.br
Time the execution of a command. The total execution time is reported
in seconds and on standard error when the command completes.
.HP
.BI whatis name
.br
Print variable, function or builtin. The object given by
.I name
is described on standard output in a format that reflects its type.
.PP
The
.I make
loadable builtin provides `make` functionality.
The
.I tk
loadable builtin provides control over some of the visual elements of a
.I mash
window.
.SS Adding Builtins
New builtins can be added to
.I mash
by creating a
.I Dis
module that can be loaded with a
.B Mashbuiltin
module interface (defined in mash.m).
The new module is loaded with the builtin
.B load
command which calls its
.B mashinit
function to initialise it with an argument containing the
.B load
command line. The function should use this call to register the set of builtins
that the module will provide using the
.B Env.defbuiltin
function. Thereafter, each time one of the registered builtins is invoked
the module's
.B mashcmd
function is called passing as an argument a list containing the invoked
builtin name and its arguments. See the examples in
.BR mash/builtins.b ,
.BR mash/make.b ", and"
.BR mash/tk.b .
.SH FILES
.B /lib/mashinit
.br
.B /dis/lib/mash
.SH SOURCE
.B /appl/cmd/mash
.SH SEE ALSO
.IR mash-tk (1),
.IR mash-make (1),
.IR regex (2)
.PP
Tom Duff,
``Rc \- The Plan 9 Shell'', in the
.I "Plan 9 Programmer's Manual", Second Edition,
Volume 2.
|