| mk.1 - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| mk.1 (14216B) | |
| --- | |
| 1 .TH MK 1 | |
| 2 .SH NAME | |
| 3 mk \- maintain (make) related files | |
| 4 .SH SYNOPSIS | |
| 5 .B mk | |
| 6 [ | |
| 7 .B -f | |
| 8 .I mkfile | |
| 9 ] ... | |
| 10 [ | |
| 11 .I option ... | |
| 12 ] | |
| 13 [ | |
| 14 .I target ... | |
| 15 ] | |
| 16 .SH DESCRIPTION | |
| 17 .I Mk | |
| 18 uses the dependency rules specified in | |
| 19 .I mkfile | |
| 20 to control the update (usually by compilation) of | |
| 21 .I targets | |
| 22 (usually files) | |
| 23 from the source files upon which they depend. | |
| 24 The | |
| 25 .I mkfile | |
| 26 (default | |
| 27 .LR mkfile ) | |
| 28 contains a | |
| 29 .I rule | |
| 30 for each target that identifies the files and other | |
| 31 targets upon which it depends and an | |
| 32 .IR sh (1) | |
| 33 script, a | |
| 34 .IR recipe , | |
| 35 to update the target. | |
| 36 The script is run if the target does not exist | |
| 37 or if it is older than any of the files it depends on. | |
| 38 .I Mkfile | |
| 39 may also contain | |
| 40 .I meta-rules | |
| 41 that define actions for updating implicit targets. | |
| 42 If no | |
| 43 .I target | |
| 44 is specified, the target of the first rule (not meta-rule) in | |
| 45 .I mkfile | |
| 46 is updated. | |
| 47 .PP | |
| 48 The environment variable | |
| 49 .B $NPROC | |
| 50 determines how many targets may be updated simultaneously; | |
| 51 Some operating systems, e.g., Plan 9, set | |
| 52 .B $NPROC | |
| 53 automatically to the number of CPUs on the current machine. | |
| 54 .PP | |
| 55 Options are: | |
| 56 .TP \w'\fL-d[egp]\ 'u | |
| 57 .B -a | |
| 58 Assume all targets to be out of date. | |
| 59 Thus, everything is updated. | |
| 60 .PD 0 | |
| 61 .TP | |
| 62 .BR -d [ egp ] | |
| 63 Produce debugging output | |
| 64 .RB ( p | |
| 65 is for parsing, | |
| 66 .B g | |
| 67 for graph building, | |
| 68 .B e | |
| 69 for execution). | |
| 70 .TP | |
| 71 .B -e | |
| 72 Explain why each target is made. | |
| 73 .TP | |
| 74 .B -i | |
| 75 Force any missing intermediate targets to be made. | |
| 76 .TP | |
| 77 .B -k | |
| 78 Do as much work as possible in the face of errors. | |
| 79 .TP | |
| 80 .B -n | |
| 81 Print, but do not execute, the commands | |
| 82 needed to update the targets. | |
| 83 .TP | |
| 84 .B -s | |
| 85 Make the command line arguments sequentially rather than in parallel. | |
| 86 .TP | |
| 87 .B -t | |
| 88 Touch (update the modified date of) file targets, without | |
| 89 executing any recipes. | |
| 90 .TP | |
| 91 .BI -w target1 , target2,... | |
| 92 Pretend the modify time for each | |
| 93 .I target | |
| 94 is the current time; useful in conjunction with | |
| 95 .B -n | |
| 96 to learn what updates would be triggered by | |
| 97 modifying the | |
| 98 .IR targets . | |
| 99 .PD | |
| 100 .SS The \fLmkfile\fP | |
| 101 A | |
| 102 .I mkfile | |
| 103 consists of | |
| 104 .I assignments | |
| 105 (described under `Environment') and | |
| 106 .IR rules . | |
| 107 A rule contains | |
| 108 .I targets | |
| 109 and a | |
| 110 .IR tail . | |
| 111 A target is a literal string | |
| 112 and is normally a file name. | |
| 113 The tail contains zero or more | |
| 114 .I prerequisites | |
| 115 and an optional | |
| 116 .IR recipe , | |
| 117 which is an | |
| 118 .B shell | |
| 119 script. | |
| 120 Each line of the recipe must begin with white space. | |
| 121 A rule takes the form | |
| 122 .IP | |
| 123 .EX | |
| 124 target: prereq1 prereq2 | |
| 125 \f2recipe using\fP prereq1, prereq2 \f2to build\fP target | |
| 126 .EE | |
| 127 .PP | |
| 128 When the recipe is executed, | |
| 129 the first character on every line is elided. | |
| 130 .PP | |
| 131 After the colon on the target line, a rule may specify | |
| 132 .IR attributes , | |
| 133 described below. | |
| 134 .PP | |
| 135 A | |
| 136 .I meta-rule | |
| 137 has a target of the form | |
| 138 .IB A % B | |
| 139 where | |
| 140 .I A | |
| 141 and | |
| 142 .I B | |
| 143 are (possibly empty) strings. | |
| 144 A meta-rule acts as a rule for any potential target whose | |
| 145 name matches | |
| 146 .IB A % B | |
| 147 with | |
| 148 .B % | |
| 149 replaced by an arbitrary string, called the | |
| 150 .IR stem . | |
| 151 In interpreting a meta-rule, | |
| 152 the stem is substituted for all occurrences of | |
| 153 .B % | |
| 154 in the prerequisite names. | |
| 155 In the recipe of a meta-rule, the environment variable | |
| 156 .B $stem | |
| 157 contains the string matched by the | |
| 158 .BR % . | |
| 159 For example, a meta-rule to compile a C program using | |
| 160 .IR 9c (1) | |
| 161 might be: | |
| 162 .IP | |
| 163 .EX | |
| 164 %: %.c | |
| 165 9c -c $stem.c | |
| 166 9l -o $stem $stem.o | |
| 167 .EE | |
| 168 .PP | |
| 169 Meta-rules may contain an ampersand | |
| 170 .B & | |
| 171 rather than a percent sign | |
| 172 .BR % . | |
| 173 A | |
| 174 .B % | |
| 175 matches a maximal length string of any characters; | |
| 176 an | |
| 177 .B & | |
| 178 matches a maximal length string of any characters except period | |
| 179 or slash. | |
| 180 .PP | |
| 181 The text of the | |
| 182 .I mkfile | |
| 183 is processed as follows. | |
| 184 Lines beginning with | |
| 185 .B < | |
| 186 followed by a file name are replaced by the contents of the named | |
| 187 file. | |
| 188 Lines beginning with | |
| 189 .B "<|" | |
| 190 followed by a file name are replaced by the output | |
| 191 of the execution of the named | |
| 192 file. | |
| 193 Blank lines and comments, which run from unquoted | |
| 194 .B # | |
| 195 characters to the following newline, are deleted. | |
| 196 The character sequence backslash-newline is deleted, | |
| 197 so long lines in | |
| 198 .I mkfile | |
| 199 may be folded. | |
| 200 Non-recipe lines are processed by substituting for | |
| 201 .BI `{ command } | |
| 202 the output of the | |
| 203 .I command | |
| 204 when run by | |
| 205 .IR sh . | |
| 206 References to variables are replaced by the variables' values. | |
| 207 Special characters may be quoted using single quotes | |
| 208 .BR \&'' | |
| 209 as in | |
| 210 .IR sh (1). | |
| 211 .PP | |
| 212 Assignments and rules are distinguished by | |
| 213 the first unquoted occurrence of | |
| 214 .B : | |
| 215 (rule) | |
| 216 or | |
| 217 .B = | |
| 218 (assignment). | |
| 219 .PP | |
| 220 A later rule may modify or override an existing rule under the | |
| 221 following conditions: | |
| 222 .TP | |
| 223 \- | |
| 224 If the targets of the rules exactly match and one rule | |
| 225 contains only a prerequisite clause and no recipe, the | |
| 226 clause is added to the prerequisites of the other rule. | |
| 227 If either or both targets are virtual, the recipe is | |
| 228 always executed. | |
| 229 .TP | |
| 230 \- | |
| 231 If the targets of the rules match exactly and the | |
| 232 prerequisites do not match and both rules | |
| 233 contain recipes, | |
| 234 .I mk | |
| 235 reports an ``ambiguous recipe'' error. | |
| 236 .TP | |
| 237 \- | |
| 238 If the target and prerequisites of both rules match exactly, | |
| 239 the second rule overrides the first. | |
| 240 .SS Environment | |
| 241 Rules may make use of | |
| 242 shell | |
| 243 environment variables. | |
| 244 A legal reference of the form | |
| 245 .B $OBJ | |
| 246 or | |
| 247 .B ${name} | |
| 248 is expanded as in | |
| 249 .IR sh (1). | |
| 250 A reference of the form | |
| 251 .BI ${name: A % B = C\fL%\fID\fL}\fR, | |
| 252 where | |
| 253 .I A, B, C, D | |
| 254 are (possibly empty) strings, | |
| 255 has the value formed by expanding | |
| 256 .B $name | |
| 257 and substituting | |
| 258 .I C | |
| 259 for | |
| 260 .I A | |
| 261 and | |
| 262 .I D | |
| 263 for | |
| 264 .I B | |
| 265 in each word in | |
| 266 .B $name | |
| 267 that matches pattern | |
| 268 .IB A % B\f1. | |
| 269 .PP | |
| 270 Variables can be set by | |
| 271 assignments of the form | |
| 272 .I | |
| 273 var\fL=\fR[\fIattr\fL=\fR]\fIvalue\fR | |
| 274 .br | |
| 275 Blanks in the | |
| 276 .I value | |
| 277 break it into words. | |
| 278 Such variables are exported | |
| 279 to the environment of | |
| 280 recipes as they are executed, unless | |
| 281 .BR U , | |
| 282 the only legal attribute | |
| 283 .IR attr , | |
| 284 is present. | |
| 285 The initial value of a variable is | |
| 286 taken from (in increasing order of precedence) | |
| 287 the default values below, | |
| 288 .I mk's | |
| 289 environment, the | |
| 290 .IR mkfiles , | |
| 291 and any command line assignment as an argument to | |
| 292 .IR mk . | |
| 293 A variable assignment argument overrides the first (but not any subseque… | |
| 294 assignment to that variable. | |
| 295 .PP | |
| 296 The variable | |
| 297 .B MKFLAGS | |
| 298 contains all the option arguments (arguments starting with | |
| 299 .L - | |
| 300 or containing | |
| 301 .LR = ) | |
| 302 and | |
| 303 .B MKARGS | |
| 304 contains all the targets in the call to | |
| 305 .IR mk . | |
| 306 .PP | |
| 307 The variable | |
| 308 .B MKSHELL | |
| 309 contains the shell command line | |
| 310 .I mk | |
| 311 uses to run recipes. | |
| 312 If the first word of the command ends in | |
| 313 .B rc | |
| 314 or | |
| 315 .BR rcsh , | |
| 316 .I mk | |
| 317 uses | |
| 318 .IR rc (1)'s | |
| 319 quoting rules; otherwise it uses | |
| 320 .IR sh (1)'s. | |
| 321 The | |
| 322 .B MKSHELL | |
| 323 variable is consulted when the mkfile is read, not when it is executed, | |
| 324 so that different shells can be used within a single mkfile: | |
| 325 .IP | |
| 326 .EX | |
| 327 MKSHELL=$PLAN9/bin/rc | |
| 328 use-rc:V: | |
| 329 for(i in a b c) echo $i | |
| 330 | |
| 331 MKSHELL=sh | |
| 332 use-sh:V: | |
| 333 for i in a b c; do echo $i; done | |
| 334 .EE | |
| 335 .LP | |
| 336 Mkfiles included via | |
| 337 .B < | |
| 338 or | |
| 339 .B <| | |
| 340 .RI ( q.v. ) | |
| 341 see their own private copy of | |
| 342 .BR MKSHELL , | |
| 343 which always starts set to | |
| 344 .B sh . | |
| 345 .PP | |
| 346 Dynamic information may be included in the mkfile by using a line of the… | |
| 347 .IP | |
| 348 \fR<|\fIcommand\fR \fIargs\fR | |
| 349 .LP | |
| 350 This runs the command | |
| 351 .I command | |
| 352 with the given arguments | |
| 353 .I args | |
| 354 and pipes its standard output to | |
| 355 .I mk | |
| 356 to be included as part of the mkfile. For instance, the Inferno kernels | |
| 357 use this technique | |
| 358 to run a shell command with an awk script and a configuration | |
| 359 file as arguments in order for | |
| 360 the | |
| 361 .I awk | |
| 362 script to process the file and output a set of variables and their value… | |
| 363 .SS Execution | |
| 364 .PP | |
| 365 During execution, | |
| 366 .I mk | |
| 367 determines which targets must be updated, and in what order, | |
| 368 to build the | |
| 369 .I names | |
| 370 specified on the command line. | |
| 371 It then runs the associated recipes. | |
| 372 .PP | |
| 373 A target is considered up to date if it has no prerequisites or | |
| 374 if all its prerequisites are up to date and it is newer | |
| 375 than all its prerequisites. | |
| 376 Once the recipe for a target has executed, the target is | |
| 377 considered up to date. | |
| 378 .PP | |
| 379 The date stamp | |
| 380 used to determine if a target is up to date is computed | |
| 381 differently for different types of targets. | |
| 382 If a target is | |
| 383 .I virtual | |
| 384 (the target of a rule with the | |
| 385 .B V | |
| 386 attribute), | |
| 387 its date stamp is initially zero; when the target is | |
| 388 updated the date stamp is set to | |
| 389 the most recent date stamp of its prerequisites. | |
| 390 Otherwise, if a target does not exist as a file, | |
| 391 its date stamp is set to the most recent date stamp of its prerequisites, | |
| 392 or zero if it has no prerequisites. | |
| 393 Otherwise, the target is the name of a file and | |
| 394 the target's date stamp is always that file's modification date. | |
| 395 The date stamp is computed when the target is needed in | |
| 396 the execution of a rule; it is not a static value. | |
| 397 .PP | |
| 398 Nonexistent targets that have prerequisites | |
| 399 and are themselves prerequisites are treated specially. | |
| 400 Such a target | |
| 401 .I t | |
| 402 is given the date stamp of its most recent prerequisite | |
| 403 and if this causes all the targets which have | |
| 404 .I t | |
| 405 as a prerequisite to be up to date, | |
| 406 .I t | |
| 407 is considered up to date. | |
| 408 Otherwise, | |
| 409 .I t | |
| 410 is made in the normal fashion. | |
| 411 The | |
| 412 .B -i | |
| 413 flag overrides this special treatment. | |
| 414 .PP | |
| 415 Files may be made in any order that respects | |
| 416 the preceding restrictions. | |
| 417 .PP | |
| 418 A recipe is executed by supplying the recipe as standard input to | |
| 419 the command | |
| 420 .BR /bin/sh . | |
| 421 (Note that unlike | |
| 422 .IR make , | |
| 423 .I mk | |
| 424 feeds the entire recipe to the shell rather than running each line | |
| 425 of the recipe separately.) | |
| 426 The environment is augmented by the following variables: | |
| 427 .TP 14 | |
| 428 .B $alltarget | |
| 429 all the targets of this rule. | |
| 430 .TP | |
| 431 .B $newprereq | |
| 432 the prerequisites that caused this rule to execute. | |
| 433 .TP | |
| 434 .B $newmember | |
| 435 the prerequisites that are members of an aggregate | |
| 436 that caused this rule to execute. | |
| 437 When the prerequisites of a rule are members of an | |
| 438 aggregate, | |
| 439 .B $newprereq | |
| 440 contains the name of the aggregate and out of date | |
| 441 members, while | |
| 442 .B $newmember | |
| 443 contains only the name of the members. | |
| 444 .TP | |
| 445 .B $nproc | |
| 446 the process slot for this recipe. | |
| 447 It satisfies | |
| 448 .RB 0≤ $nproc < $NPROC . | |
| 449 .TP | |
| 450 .B $pid | |
| 451 the process id for the | |
| 452 .I mk | |
| 453 executing the recipe. | |
| 454 .TP | |
| 455 .B $prereq | |
| 456 all the prerequisites for this rule. | |
| 457 .TP | |
| 458 .B $stem | |
| 459 if this is a meta-rule, | |
| 460 .B $stem | |
| 461 is the string that matched | |
| 462 .B % | |
| 463 or | |
| 464 .BR & . | |
| 465 Otherwise, it is empty. | |
| 466 For regular expression meta-rules (see below), the variables | |
| 467 .LR stem0 ", ...," | |
| 468 .L stem9 | |
| 469 are set to the corresponding subexpressions. | |
| 470 .TP | |
| 471 .B $target | |
| 472 the targets for this rule that need to be remade. | |
| 473 .PP | |
| 474 These variables are available only during the execution of a recipe, | |
| 475 not while evaluating the | |
| 476 .IR mkfile . | |
| 477 .PP | |
| 478 Unless the rule has the | |
| 479 .B Q | |
| 480 attribute, | |
| 481 the recipe is printed prior to execution | |
| 482 with recognizable environment variables expanded. | |
| 483 Commands returning error status | |
| 484 cause | |
| 485 .I mk | |
| 486 to terminate. | |
| 487 .PP | |
| 488 Recipes and backquoted | |
| 489 .B rc | |
| 490 commands in places such as assignments | |
| 491 execute in a copy of | |
| 492 .I mk's | |
| 493 environment; changes they make to | |
| 494 environment variables are not visible from | |
| 495 .IR mk . | |
| 496 .PP | |
| 497 Variable substitution in a rule is done when | |
| 498 the rule is read; variable substitution in the recipe is done | |
| 499 when the recipe is executed. For example: | |
| 500 .IP | |
| 501 .EX | |
| 502 bar=a.c | |
| 503 foo: $bar | |
| 504 $CC -o foo $bar | |
| 505 bar=b.c | |
| 506 .EE | |
| 507 .PP | |
| 508 will compile | |
| 509 .B b.c | |
| 510 into | |
| 511 .BR foo , | |
| 512 if | |
| 513 .B a.c | |
| 514 is newer than | |
| 515 .BR foo . | |
| 516 .SS Aggregates | |
| 517 Names of the form | |
| 518 .IR a ( b ) | |
| 519 refer to member | |
| 520 .I b | |
| 521 of the aggregate | |
| 522 .IR a . | |
| 523 Currently, the only aggregates supported are | |
| 524 .I 9ar | |
| 525 (see | |
| 526 .IR 9c (1)) | |
| 527 archives. | |
| 528 .SS Attributes | |
| 529 The colon separating the target from the prerequisites | |
| 530 may be | |
| 531 immediately followed by | |
| 532 .I attributes | |
| 533 and another colon. | |
| 534 The attributes are: | |
| 535 .TP | |
| 536 .B D | |
| 537 If the recipe exits with a non-null status, the target is deleted. | |
| 538 .TP | |
| 539 .B E | |
| 540 Continue execution if the recipe draws errors. | |
| 541 .TP | |
| 542 .B N | |
| 543 If there is no recipe, the target has its time updated. | |
| 544 .TP | |
| 545 .B n | |
| 546 The rule is a meta-rule that cannot be a target of a virtual rule. | |
| 547 Only files match the pattern in the target. | |
| 548 .TP | |
| 549 .B P | |
| 550 The characters after the | |
| 551 .B P | |
| 552 until the terminating | |
| 553 .B : | |
| 554 are taken as a program name. | |
| 555 It will be invoked as | |
| 556 .B "sh -c prog 'arg1' 'arg2'" | |
| 557 and should return a zero exit status | |
| 558 if and only if arg1 is up to date with respect to arg2. | |
| 559 Date stamps are still propagated in the normal way. | |
| 560 .TP | |
| 561 .B Q | |
| 562 The recipe is not printed prior to execution. | |
| 563 .TP | |
| 564 .B R | |
| 565 The rule is a meta-rule using regular expressions. | |
| 566 In the rule, | |
| 567 .B % | |
| 568 has no special meaning. | |
| 569 The target is interpreted as a regular expression as defined in | |
| 570 .IR regexp (7). | |
| 571 The prerequisites may contain references | |
| 572 to subexpressions in form | |
| 573 .BI \e n\f1, | |
| 574 as in the substitute command of | |
| 575 .IR sed (1). | |
| 576 .TP | |
| 577 .B U | |
| 578 The targets are considered to have been updated | |
| 579 even if the recipe did not do so. | |
| 580 .TP | |
| 581 .B V | |
| 582 The targets of this rule are marked as virtual. | |
| 583 They are distinct from files of the same name. | |
| 584 .PD | |
| 585 .SH EXAMPLES | |
| 586 A simple mkfile to compile a program: | |
| 587 .IP | |
| 588 .EX | |
| 589 .ta 8n +8n +8n +8n +8n +8n +8n | |
| 590 </$objtype/mkfile | |
| 591 | |
| 592 prog: a.$O b.$O c.$O | |
| 593 $LD $LDFLAGS -o $target $prereq | |
| 594 | |
| 595 %.$O: %.c | |
| 596 $CC $CFLAGS $stem.c | |
| 597 .EE | |
| 598 .PP | |
| 599 Override flag settings in the mkfile: | |
| 600 .IP | |
| 601 .EX | |
| 602 % mk target 'CFLAGS=-S -w' | |
| 603 .EE | |
| 604 .PP | |
| 605 Maintain a library: | |
| 606 .IP | |
| 607 .EX | |
| 608 libc.a(%.$O):N: %.$O | |
| 609 libc.a: libc.a(abs.$O) libc.a(access.$O) libc.a(alarm.$O) ... | |
| 610 ar r libc.a $newmember | |
| 611 .EE | |
| 612 .PP | |
| 613 String expression variables to derive names from a master list: | |
| 614 .IP | |
| 615 .EX | |
| 616 NAMES=alloc arc bquote builtins expand main match mk var word | |
| 617 OBJ=${NAMES:%=%.$O} | |
| 618 .EE | |
| 619 .PP | |
| 620 Regular expression meta-rules: | |
| 621 .IP | |
| 622 .EX | |
| 623 ([^/]*)/(.*)\e.$O:R: \e1/\e2.c | |
| 624 cd $stem1; $CC $CFLAGS $stem2.c | |
| 625 .EE | |
| 626 .PP | |
| 627 A correct way to deal with | |
| 628 .IR yacc (1) | |
| 629 grammars. | |
| 630 The file | |
| 631 .B lex.c | |
| 632 includes the file | |
| 633 .B x.tab.h | |
| 634 rather than | |
| 635 .B y.tab.h | |
| 636 in order to reflect changes in content, not just modification time. | |
| 637 .IP | |
| 638 .EX | |
| 639 lex.$O: x.tab.h | |
| 640 x.tab.h: y.tab.h | |
| 641 cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h | |
| 642 y.tab.c y.tab.h: gram.y | |
| 643 $YACC -d gram.y | |
| 644 .EE | |
| 645 .PP | |
| 646 The above example could also use the | |
| 647 .B P | |
| 648 attribute for the | |
| 649 .B x.tab.h | |
| 650 rule: | |
| 651 .IP | |
| 652 .EX | |
| 653 x.tab.h:Pcmp -s: y.tab.h | |
| 654 cp y.tab.h x.tab.h | |
| 655 .EE | |
| 656 .SH SOURCE | |
| 657 .B \*9/src/cmd/mk | |
| 658 .SH SEE ALSO | |
| 659 .IR sh (1), | |
| 660 .IR regexp (7) | |
| 661 .PP | |
| 662 A. Hume, | |
| 663 ``Mk: a Successor to Make'' | |
| 664 (Tenth Edition Research Unix Manuals). | |
| 665 .PP | |
| 666 Andrew G. Hume and Bob Flandrena, | |
| 667 ``Maintaining Files on Plan 9 with Mk''. | |
| 668 DOCPREFIX/doc/mk.pdf | |
| 669 .SH HISTORY | |
| 670 Andrew Hume wrote | |
| 671 .I mk | |
| 672 for Tenth Edition Research Unix. | |
| 673 It was later ported to Plan 9. | |
| 674 This software is a port of the Plan 9 version back to Unix. | |
| 675 .SH BUGS | |
| 676 Identical recipes for regular expression meta-rules only have one target. | |
| 677 .PP | |
| 678 Seemingly appropriate input like | |
| 679 .B CFLAGS=-DHZ=60 | |
| 680 is parsed as an erroneous attribute; correct it by inserting | |
| 681 a space after the first | |
| 682 .LR = . | |
| 683 .PP | |
| 684 The recipes printed by | |
| 685 .I mk | |
| 686 before being passed to | |
| 687 the shell | |
| 688 for execution are sometimes erroneously expanded | |
| 689 for printing. Don't trust what's printed; rely | |
| 690 on what the shell | |
| 691 does. |