home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / perl / part05 < prev    next >
Encoding:
Internet Message Format  |  1988-01-30  |  48.6 KB

  1. Subject:  v13i005:  Perl, a "replacement" for awk and sed, Part05/10
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
  7. Posting-number: Volume 13, Issue 5
  8. Archive-name: perl/part05
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13.  
  14. # Make a new directory for the perl sources, cd to it, and run kits 1
  15. # thru 10 through sh.  When all 10 kits have been run, read README.
  16.  
  17. echo "This is perl 1.0 kit 5 (of 10).  If kit 5 is complete, the line"
  18. echo '"'"End of kit 5 (of 10)"'" will echo at the end.'
  19. echo ""
  20. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  21. mkdir t 2>/dev/null
  22. echo Extracting perl.man.1
  23. sed >perl.man.1 <<'!STUFFY!FUNK!' -e 's/X//'
  24. X.rn '' }`
  25. X''' $Header: perl.man.1,v 1.0 87/12/18 16:18:16 root Exp $
  26. X''' 
  27. X''' $Log:    perl.man.1,v $
  28. X''' Revision 1.0  87/12/18  16:18:16  root
  29. X''' Initial revision
  30. X''' 
  31. X''' 
  32. X.de Sh
  33. X.br
  34. X.ne 5
  35. X.PP
  36. X\fB\\$1\fR
  37. X.PP
  38. X..
  39. X.de Sp
  40. X.if t .sp .5v
  41. X.if n .sp
  42. X..
  43. X.de Ip
  44. X.br
  45. X.ie \\n.$>=3 .ne \\$3
  46. X.el .ne 3
  47. X.IP "\\$1" \\$2
  48. X..
  49. X'''
  50. X'''     Set up \*(-- to give an unbreakable dash;
  51. X'''     string Tr holds user defined translation string.
  52. X'''     Bell System Logo is used as a dummy character.
  53. X'''
  54. X.tr \(bs-|\(bv\*(Tr
  55. X.ie n \{\
  56. X.ds -- \(bs-
  57. X.if (\n(.H=4u)&(1m=24u) .ds -- \(bs\h'-12u'\(bs\h'-12u'-\" diablo 10 pitch
  58. X.if (\n(.H=4u)&(1m=20u) .ds -- \(bs\h'-12u'\(bs\h'-8u'-\" diablo 12 pitch
  59. X.ds L" ""
  60. X.ds R" ""
  61. X.ds L' '
  62. X.ds R' '
  63. X'br\}
  64. X.el\{\
  65. X.ds -- \(em\|
  66. X.tr \*(Tr
  67. X.ds L" ``
  68. X.ds R" ''
  69. X.ds L' `
  70. X.ds R' '
  71. X'br\}
  72. X.TH PERL 1 LOCAL
  73. X.SH NAME
  74. Xperl - Practical Extraction and Report Language
  75. X.SH SYNOPSIS
  76. X.B perl [options] filename args
  77. X.SH DESCRIPTION
  78. X.I Perl
  79. Xis a interpreted language optimized for scanning arbitrary text files,
  80. Xextracting information from those text files, and printing reports based
  81. Xon that information.
  82. XIt's also a good language for many system management tasks.
  83. XThe language is intended to be practical (easy to use, efficient, complete)
  84. Xrather than beautiful (tiny, elegant, minimal).
  85. XIt combines (in the author's opinion, anyway) some of the best features of C,
  86. X\fIsed\fR, \fIawk\fR, and \fIsh\fR,
  87. Xso people familiar with those languages should have little difficulty with it.
  88. X(Language historians will also note some vestiges of \fIcsh\fR, Pascal, and
  89. Xeven BASIC-PLUS.)
  90. XExpression syntax corresponds quite closely to C expression syntax.
  91. XIf you have a problem that would ordinarily use \fIsed\fR
  92. Xor \fIawk\fR or \fIsh\fR, but it
  93. Xexceeds their capabilities or must run a little faster,
  94. Xand you don't want to write the silly thing in C, then
  95. X.I perl
  96. Xmay be for you.
  97. XThere are also translators to turn your sed and awk scripts into perl scripts.
  98. XOK, enough hype.
  99. X.PP
  100. XUpon startup,
  101. X.I perl
  102. Xlooks for your script in one of the following places:
  103. X.Ip 1. 4 2
  104. XSpecified line by line via
  105. X.B \-e
  106. Xswitches on the command line.
  107. X.Ip 2. 4 2
  108. XContained in the file specified by the first filename on the command line.
  109. X(Note that systems supporting the #! notation invoke interpreters this way.)
  110. X.Ip 3. 4 2
  111. XPassed in via standard input.
  112. X.PP
  113. XAfter locating your script,
  114. X.I perl
  115. Xcompiles it to an internal form.
  116. XIf the script is syntactically correct, it is executed.
  117. X.Sh "Options"
  118. XNote: on first reading this section won't make much sense to you.  It's here
  119. Xat the front for easy reference.
  120. X.PP
  121. XA single-character option may be combined with the following option, if any.
  122. XThis is particularly useful when invoking a script using the #! construct which
  123. Xonly allows one argument.  Example:
  124. X.nf
  125. X
  126. X.ne 2
  127. X    #!/bin/perl -spi.bak    # same as -s -p -i.bak
  128. X    .\|.\|.
  129. X
  130. X.fi
  131. XOptions include:
  132. X.TP 5
  133. X.B \-D<number>
  134. Xsets debugging flags.
  135. XTo watch how it executes your script, use
  136. X.B \-D14.
  137. X(This only works if debugging is compiled into your
  138. X.IR perl .)
  139. X.TP 5
  140. X.B \-e commandline
  141. Xmay be used to enter one line of script.
  142. XMultiple
  143. X.B \-e
  144. Xcommands may be given to build up a multi-line script.
  145. XIf
  146. X.B \-e
  147. Xis given,
  148. X.I perl
  149. Xwill not look for a script filename in the argument list.
  150. X.TP 5
  151. X.B \-i<extension>
  152. Xspecifies that files processed by the <> construct are to be edited
  153. Xin-place.
  154. XIt does this by renaming the input file, opening the output file by the
  155. Xsame name, and selecting that output file as the default for print statements.
  156. XThe extension, if supplied, is added to the name of the
  157. Xold file to make a backup copy.
  158. XIf no extension is supplied, no backup is made.
  159. XSaying \*(L"perl -p -i.bak -e "s/foo/bar/;" ... \*(R" is the same as using
  160. Xthe script:
  161. X.nf
  162. X
  163. X.ne 2
  164. X    #!/bin/perl -pi.bak
  165. X    s/foo/bar/;
  166. X
  167. Xwhich is equivalent to
  168. X
  169. X.ne 14
  170. X    #!/bin/perl
  171. X    while (<>) {
  172. X        if ($ARGV ne $oldargv) {
  173. X            rename($ARGV,$ARGV . '.bak');
  174. X            open(ARGVOUT,">$ARGV");
  175. X            select(ARGVOUT);
  176. X            $oldargv = $ARGV;
  177. X        }
  178. X        s/foo/bar/;
  179. X    }
  180. X    continue {
  181. X        print;    # this prints to original filename
  182. X    }
  183. X    select(stdout);
  184. X
  185. X.fi
  186. Xexcept that the \-i form doesn't need to compare $ARGV to $oldargv to know when
  187. Xthe filename has changed.
  188. XIt does, however, use ARGVOUT for the selected filehandle.
  189. XNote that stdout is restored as the default output filehandle after the loop.
  190. X.TP 5
  191. X.B \-I<directory>
  192. Xmay be used in conjunction with
  193. X.B \-P
  194. Xto tell the C preprocessor where to look for include files.
  195. XBy default /usr/include and /usr/lib/perl are searched.
  196. X.TP 5
  197. X.B \-n
  198. Xcauses
  199. X.I perl
  200. Xto assume the following loop around your script, which makes it iterate
  201. Xover filename arguments somewhat like \*(L"sed -n\*(R" or \fIawk\fR:
  202. X.nf
  203. X
  204. X.ne 3
  205. X    while (<>) {
  206. X        ...        # your script goes here
  207. X    }
  208. X
  209. X.fi
  210. XNote that the lines are not printed by default.
  211. XSee
  212. X.B \-p
  213. Xto have lines printed.
  214. X.TP 5
  215. X.B \-p
  216. Xcauses
  217. X.I perl
  218. Xto assume the following loop around your script, which makes it iterate
  219. Xover filename arguments somewhat like \fIsed\fR:
  220. X.nf
  221. X
  222. X.ne 5
  223. X    while (<>) {
  224. X        ...        # your script goes here
  225. X    } continue {
  226. X        print;
  227. X    }
  228. X
  229. X.fi
  230. XNote that the lines are printed automatically.
  231. XTo suppress printing use the
  232. X.B \-n
  233. Xswitch.
  234. X.TP 5
  235. X.B \-P
  236. Xcauses your script to be run through the C preprocessor before
  237. Xcompilation by
  238. X.I perl.
  239. X(Since both comments and cpp directives begin with the # character,
  240. Xyou should avoid starting comments with any words recognized
  241. Xby the C preprocessor such as \*(L"if\*(R", \*(L"else\*(R" or \*(L"define\*(R".)
  242. X.TP 5
  243. X.B \-s
  244. Xenables some rudimentary switch parsing for switches on the command line
  245. Xafter the script name but before any filename arguments.
  246. XAny switch found there will set the corresponding variable in the
  247. X.I perl
  248. Xscript.
  249. XThe following script prints \*(L"true\*(R" if and only if the script is
  250. Xinvoked with a -x switch.
  251. X.nf
  252. X
  253. X.ne 2
  254. X    #!/bin/perl -s
  255. X    if ($x) { print "true\en"; }
  256. X
  257. X.fi
  258. X.Sh "Data Types and Objects"
  259. X.PP
  260. XPerl has about two and a half data types: strings, arrays of strings, and
  261. Xassociative arrays.
  262. XStrings and arrays of strings are first class objects, for the most part,
  263. Xin the sense that they can be used as a whole as values in an expression.
  264. XAssociative arrays can only be accessed on an association by association basis;
  265. Xthey don't have a value as a whole (at least not yet).
  266. X.PP
  267. XStrings are interpreted numerically as appropriate.
  268. XA string is interpreted as TRUE in the boolean sense if it is not the null
  269. Xstring or 0.
  270. XBooleans returned by operators are 1 for true and '0' or '' (the null
  271. Xstring) for false.
  272. X.PP
  273. XReferences to string variables always begin with \*(L'$\*(R', even when referring
  274. Xto a string that is part of an array.
  275. XThus:
  276. X.nf
  277. X
  278. X.ne 3
  279. X    $days    \h'|2i'# a simple string variable
  280. X    $days[28]    \h'|2i'# 29th element of array @days
  281. X    $days{'Feb'}\h'|2i'# one value from an associative array
  282. X
  283. Xbut entire arrays are denoted by \*(L'@\*(R':
  284. X
  285. X    @days    \h'|2i'# ($days[0], $days[1],\|.\|.\|. $days[n])
  286. X
  287. X.fi
  288. X.PP
  289. XAny of these four constructs may be assigned to (in compiler lingo, may serve
  290. Xas an lvalue).
  291. X(Additionally, you may find the length of array @days by evaluating
  292. X\*(L"$#days\*(R", as in
  293. X.IR csh .
  294. X[Actually, it's not the length of the array, it's the subscript of the last element, since there is (ordinarily) a 0th element.])
  295. X.PP
  296. XEvery data type has its own namespace.
  297. XYou can, without fear of conflict, use the same name for a string variable,
  298. Xan array, an associative array, a filehandle, a subroutine name, and/or
  299. Xa label.
  300. XSince variable and array references always start with \*(L'$\*(R'
  301. Xor \*(L'@\*(R', the \*(L"reserved\*(R" words aren't in fact reserved
  302. Xwith respect to variable names.
  303. X(They ARE reserved with respect to labels and filehandles, however, which
  304. Xdon't have an initial special character.)
  305. XCase IS significant\*(--\*(L"FOO\*(R", \*(L"Foo\*(R" and \*(L"foo\*(R" are all
  306. Xdifferent names.
  307. XNames which start with a letter may also contain digits and underscores.
  308. XNames which do not start with a letter are limited to one character,
  309. Xe.g. \*(L"$%\*(R" or \*(L"$$\*(R".
  310. X(Many one character names have a predefined significance to
  311. X.I perl.
  312. XMore later.)
  313. X.PP
  314. XString literals are delimited by either single or double quotes.
  315. XThey work much like shell quotes:
  316. Xdouble-quoted string literals are subject to backslash and variable
  317. Xsubstitution; single-quoted strings are not.
  318. XThe usual backslash rules apply for making characters such as newline, tab, etc.
  319. XYou can also embed newlines directly in your strings, i.e. they can end on
  320. Xa different line than they begin.
  321. XThis is nice, but if you forget your trailing quote, the error will not be
  322. Xreported until perl finds another line containing the quote character, which
  323. Xmay be much further on in the script.
  324. XVariable substitution inside strings is limited (currently) to simple string variables.
  325. XThe following code segment prints out \*(L"The price is $100.\*(R"
  326. X.nf
  327. X
  328. X.ne 2
  329. X    $Price = '$100';\h'|3.5i'# not interpreted
  330. X    print "The price is $Price.\e\|n";\h'|3.5i'# interpreted
  331. X
  332. X.fi
  333. X.PP
  334. XArray literals are denoted by separating individual values by commas, and
  335. Xenclosing the list in parentheses.
  336. XIn a context not requiring an array value, the value of the array literal
  337. Xis the value of the final element, as in the C comma operator.
  338. XFor example,
  339. X.nf
  340. X
  341. X    @foo = ('cc', '\-E', $bar);
  342. X
  343. Xassigns the entire array value to array foo, but
  344. X
  345. X    $foo = ('cc', '\-E', $bar);
  346. X
  347. X.fi
  348. Xassigns the value of variable bar to variable foo.
  349. XArray lists may be assigned to if and only if each element of the list
  350. Xis an lvalue:
  351. X.nf
  352. X
  353. X    ($a, $b, $c) = (1, 2, 3);
  354. X
  355. X    ($map{'red'}, $map{'blue'}, $map{'green'}) = (0x00f, 0x0f0, 0xf00);
  356. X
  357. X.fi
  358. X.PP
  359. XNumeric literals are specified in any of the usual floating point or
  360. Xinteger formats.
  361. X.PP
  362. XThere are several other pseudo-literals that you should know about.
  363. XIf a string is enclosed by backticks (grave accents), it is interpreted as
  364. Xa command, and the output of that command is the value of the pseudo-literal,
  365. Xjust like in any of the standard shells.
  366. XThe command is executed each time the pseudo-literal is evaluated.
  367. XUnlike in \f2csh\f1, no interpretation is done on the
  368. Xdata\*(--newlines remain newlines.
  369. X.PP
  370. XEvaluating a filehandle in angle brackets yields the next line
  371. Xfrom that file (newline included, so it's never false until EOF).
  372. XOrdinarily you must assign that value to a variable,
  373. Xbut there is one situation where in which an automatic assignment happens.
  374. XIf (and only if) the input symbol is the only thing inside the conditional of a
  375. X.I while
  376. Xloop, the value is
  377. Xautomatically assigned to the variable \*(L"$_\*(R".
  378. X(This may seem like an odd thing to you, but you'll use the construct
  379. Xin almost every
  380. X.I perl
  381. Xscript you write.)
  382. XAnyway, the following lines are equivalent to each other:
  383. X.nf
  384. X
  385. X.ne 3
  386. X    while ($_ = <stdin>) {
  387. X    while (<stdin>) {
  388. X    for (\|;\|<stdin>;\|) {
  389. X
  390. X.fi
  391. XThe filehandles
  392. X.IR stdin ,
  393. X.I stdout
  394. Xand
  395. X.I stderr
  396. Xare predefined.
  397. XAdditional filehandles may be created with the
  398. X.I open
  399. Xfunction.
  400. X.PP
  401. XThe null filehandle <> is special and can be used to emulate the behavior of
  402. X\fIsed\fR and \fIawk\fR.
  403. XInput from <> comes either from standard input, or from each file listed on
  404. Xthe command line.
  405. XHere's how it works: the first time <> is evaluated, the ARGV array is checked,
  406. Xand if it is null, $ARGV[0] is set to '-', which when opened gives you standard
  407. Xinput.
  408. XThe ARGV array is then processed as a list of filenames.
  409. XThe loop
  410. X.nf
  411. X
  412. X.ne 3
  413. X    while (<>) {
  414. X        .\|.\|.            # code for each line
  415. X    }
  416. X
  417. X.ne 10
  418. Xis equivalent to
  419. X
  420. X    unshift(@ARGV, '\-') \|if \|$#ARGV < $[;
  421. X    while ($ARGV = shift) {
  422. X        open(ARGV, $ARGV);
  423. X        while (<ARGV>) {
  424. X            .\|.\|.        # code for each line
  425. X        }
  426. X    }
  427. X
  428. X.fi
  429. Xexcept that it isn't as cumbersome to say.
  430. XIt really does shift array ARGV and put the current filename into
  431. Xvariable ARGV.
  432. XIt also uses filehandle ARGV internally.
  433. XYou can modify @ARGV before the first <> as long as you leave the first
  434. Xfilename at the beginning of the array.
  435. X.PP
  436. XIf you want to set @ARGV to you own list of files, go right ahead.
  437. XIf you want to pass switches into your script, you can
  438. Xput a loop on the front like this:
  439. X.nf
  440. X
  441. X.ne 10
  442. X    while ($_ = $ARGV[0], /\|^\-/\|) {
  443. X        shift;
  444. X        last if /\|^\-\|\-$\|/\|;
  445. X        /\|^\-D\|(.*\|)/ \|&& \|($debug = $1);
  446. X        /\|^\-v\|/ \|&& \|$verbose++;
  447. X        .\|.\|.        # other switches
  448. X    }
  449. X    while (<>) {
  450. X        .\|.\|.        # code for each line
  451. X    }
  452. X
  453. X.fi
  454. XThe <> symbol will return FALSE only once.
  455. XIf you call it again after this it will assume you are processing another
  456. X@ARGV list, and if you haven't set @ARGV, will input from stdin.
  457. X.Sh "Syntax"
  458. X.PP
  459. XA
  460. X.I perl
  461. Xscript consists of a sequence of declarations and commands.
  462. XThe only things that need to be declared in
  463. X.I perl
  464. Xare report formats and subroutines.
  465. XSee the sections below for more information on those declarations.
  466. XAll objects are assumed to start with a null or 0 value.
  467. XThe sequence of commands is executed just once, unlike in
  468. X.I sed
  469. Xand
  470. X.I awk
  471. Xscripts, where the sequence of commands is executed for each input line.
  472. XWhile this means that you must explicitly loop over the lines of your input file
  473. X(or files), it also means you have much more control over which files and which
  474. Xlines you look at.
  475. X(Actually, I'm lying\*(--it is possible to do an implicit loop with either the
  476. X.B \-n
  477. Xor
  478. X.B \-p
  479. Xswitch.)
  480. X.PP
  481. XA declaration can be put anywhere a command can, but has no effect on the
  482. Xexecution of the primary sequence of commands.
  483. XTypically all the declarations are put at the beginning or the end of the script.
  484. X.PP
  485. X.I Perl
  486. Xis, for the most part, a free-form language.
  487. X(The only exception to this is format declarations, for fairly obvious reasons.)
  488. XComments are indicated by the # character, and extend to the end of the line.
  489. XIf you attempt to use /* */ C comments, it will be interpreted either as
  490. Xdivision or pattern matching, depending on the context.
  491. XSo don't do that.
  492. X.Sh "Compound statements"
  493. XIn
  494. X.IR perl ,
  495. Xa sequence of commands may be treated as one command by enclosing it
  496. Xin curly brackets.
  497. XWe will call this a BLOCK.
  498. X.PP
  499. XThe following compound commands may be used to control flow:
  500. X.nf
  501. X
  502. X.ne 4
  503. X    if (EXPR) BLOCK
  504. X    if (EXPR) BLOCK else BLOCK
  505. X    if (EXPR) BLOCK elsif (EXPR) BLOCK ... else BLOCK
  506. X    LABEL while (EXPR) BLOCK
  507. X    LABEL while (EXPR) BLOCK continue BLOCK
  508. X    LABEL for (EXPR; EXPR; EXPR) BLOCK
  509. X    LABEL BLOCK continue BLOCK
  510. X
  511. X.fi
  512. X(Note that, unlike C and Pascal, these are defined in terms of BLOCKs, not
  513. Xstatements.
  514. XThis means that the curly brackets are \fIrequired\fR\*(--no dangling statements allowed.
  515. XIf you want to write conditionals without curly brackets there are several
  516. Xother ways to do it.
  517. XThe following all do the same thing:
  518. X.nf
  519. X
  520. X.ne 5
  521. X    if (!open(foo)) { die "Can't open $foo"; }
  522. X    die "Can't open $foo" unless open(foo);
  523. X    open(foo) || die "Can't open $foo";    # foo or bust!
  524. X    open(foo) ? die "Can't open $foo" : 'hi mom';
  525. X
  526. X.fi
  527. Xthough the last one is a bit exotic.)
  528. X.PP
  529. XThe
  530. X.I if
  531. Xstatement is straightforward.
  532. XSince BLOCKs are always bounded by curly brackets, there is never any
  533. Xambiguity about which
  534. X.I if
  535. Xan
  536. X.I else
  537. Xgoes with.
  538. XIf you use
  539. X.I unless
  540. Xin place of
  541. X.IR if ,
  542. Xthe sense of the test is reversed.
  543. X.PP
  544. XThe
  545. X.I while
  546. Xstatement executes the block as long as the expression is true
  547. X(does not evaluate to the null string or 0).
  548. XThe LABEL is optional, and if present, consists of an identifier followed by
  549. Xa colon.
  550. XThe LABEL identifies the loop for the loop control statements
  551. X.IR next ,
  552. X.I last
  553. Xand
  554. X.I redo
  555. X(see below).
  556. XIf there is a
  557. X.I continue
  558. XBLOCK, it is always executed just before
  559. Xthe conditional is about to be evaluated again, similarly to the third part
  560. Xof a
  561. X.I for
  562. Xloop in C.
  563. XThus it can be used to increment a loop variable, even when the loop has
  564. Xbeen continued via the
  565. X.I next
  566. Xstatement (similar to the C \*(L"continue\*(R" statement).
  567. X.PP
  568. XIf the word
  569. X.I while
  570. Xis replaced by the word
  571. X.IR until ,
  572. Xthe sense of the test is reversed, but the conditional is still tested before
  573. Xthe first iteration.
  574. X.PP
  575. XIn either the
  576. X.I if
  577. Xor the
  578. X.I while
  579. Xstatement, you may replace \*(L"(EXPR)\*(R" with a BLOCK, and the conditional
  580. Xis true if the value of the last command in that block is true.
  581. X.PP
  582. XThe
  583. X.I for
  584. Xloop works exactly like the corresponding
  585. X.I while
  586. Xloop:
  587. X.nf
  588. X
  589. X.ne 12
  590. X    for ($i = 1; $i < 10; $i++) {
  591. X        .\|.\|.
  592. X    }
  593. X
  594. Xis the same as
  595. X
  596. X    $i = 1;
  597. X    while ($i < 10) {
  598. X        .\|.\|.
  599. X    } continue {
  600. X        $i++;
  601. X    }
  602. X.fi
  603. X.PP
  604. XThe BLOCK by itself (labeled or not) is equivalent to a loop that executes
  605. Xonce.
  606. XThus you can use any of the loop control statements in it to leave or
  607. Xrestart the block.
  608. XThe
  609. X.I continue
  610. Xblock is optional.
  611. XThis construct is particularly nice for doing case structures.
  612. X.nf
  613. X
  614. X.ne 6
  615. X    foo: {
  616. X        if (/abc/) { $abc = 1; last foo; }
  617. X        if (/def/) { $def = 1; last foo; }
  618. X        if (/xyz/) { $xyz = 1; last foo; }
  619. X        $nothing = 1;
  620. X    }
  621. X
  622. X.fi
  623. X.Sh "Simple statements"
  624. XThe only kind of simple statement is an expression evaluated for its side
  625. Xeffects.
  626. XEvery expression (simple statement) must be terminated with a semicolon.
  627. XNote that this is like C, but unlike Pascal (and
  628. X.IR awk ).
  629. X.PP
  630. XAny simple statement may optionally be followed by a
  631. Xsingle modifier, just before the terminating semicolon.
  632. XThe possible modifiers are:
  633. X.nf
  634. X
  635. X.ne 4
  636. X    if EXPR
  637. X    unless EXPR
  638. X    while EXPR
  639. X    until EXPR
  640. X
  641. X.fi
  642. XThe
  643. X.I if
  644. Xand
  645. X.I unless
  646. Xmodifiers have the expected semantics.
  647. XThe
  648. X.I while
  649. Xand
  650. X.I unless
  651. Xmodifiers also have the expected semantics (conditional evaluated first),
  652. Xexcept when applied to a do-BLOCK command,
  653. Xin which case the block executes once before the conditional is evaluated.
  654. XThis is so that you can write loops like:
  655. X.nf
  656. X
  657. X.ne 4
  658. X    do {
  659. X        $_ = <stdin>;
  660. X        .\|.\|.
  661. X    } until $_ \|eq \|".\|\e\|n";
  662. X
  663. X.fi
  664. X(See the
  665. X.I do
  666. Xoperator below.  Note also that the loop control commands described later will
  667. XNOT work in this construct, since loop modifiers don't take loop labels.
  668. XSorry.)
  669. X.Sh "Expressions"
  670. XSince
  671. X.I perl
  672. Xexpressions work almost exactly like C expressions, only the differences
  673. Xwill be mentioned here.
  674. X.PP
  675. XHere's what
  676. X.I perl
  677. Xhas that C doesn't:
  678. X.Ip (\|) 8 3
  679. XThe null list, used to initialize an array to null.
  680. X.Ip . 8
  681. XConcatenation of two strings.
  682. X.Ip .= 8
  683. XThe corresponding assignment operator.
  684. X.Ip eq 8
  685. XString equality (== is numeric equality).
  686. XFor a mnemonic just think of \*(L"eq\*(R" as a string.
  687. X(If you are used to the
  688. X.I awk
  689. Xbehavior of using == for either string or numeric equality
  690. Xbased on the current form of the comparands, beware!
  691. XYou must be explicit here.)
  692. X.Ip ne 8
  693. XString inequality (!= is numeric inequality).
  694. X.Ip lt 8
  695. XString less than.
  696. X.Ip gt 8
  697. XString greater than.
  698. X.Ip le 8
  699. XString less than or equal.
  700. X.Ip ge 8
  701. XString greater than or equal.
  702. X.Ip =~ 8 2
  703. XCertain operations search or modify the string \*(L"$_\*(R" by default.
  704. XThis operator makes that kind of operation work on some other string.
  705. XThe right argument is a search pattern, substitution, or translation.
  706. XThe left argument is what is supposed to be searched, substituted, or
  707. Xtranslated instead of the default \*(L"$_\*(R".
  708. XThe return value indicates the success of the operation.
  709. X(If the right argument is an expression other than a search pattern,
  710. Xsubstitution, or translation, it is interpreted as a search pattern
  711. Xat run time.
  712. XThis is less efficient than an explicit search, since the pattern must
  713. Xbe compiled every time the expression is evaluated.)
  714. XThe precedence of this operator is lower than unary minus and autoincrement/decrement, but higher than everything else.
  715. X.Ip !~ 8
  716. XJust like =~ except the return value is negated.
  717. X.Ip x 8
  718. XThe repetition operator.
  719. XReturns a string consisting of the left operand repeated the
  720. Xnumber of times specified by the right operand.
  721. X.nf
  722. X
  723. X    print '-' x 80;        # print row of dashes
  724. X    print '-' x80;        # illegal, x80 is identifier
  725. X
  726. X    print "\et" x ($tab/8), ' ' x ($tab%8);    # tab over
  727. X
  728. X.fi
  729. X.Ip x= 8
  730. XThe corresponding assignment operator.
  731. X.Ip .. 8
  732. XThe range operator, which is bistable.
  733. XIt is false as long as its left argument is false.
  734. XOnce the left argument is true, it stays true until the right argument is true,
  735. XAFTER which it becomes false again.
  736. X(It doesn't become false till the next time it's evaluated.
  737. XIt can become false on the same evaluation it became true, but it still returns
  738. Xtrue once.)
  739. XThe .. operator is primarily intended for doing line number ranges after
  740. Xthe fashion of \fIsed\fR or \fIawk\fR.
  741. XThe precedence is a little lower than || and &&.
  742. XThe value returned is either the null string for false, or a sequence number
  743. X(beginning with 1) for true.
  744. XThe sequence number is reset for each range encountered.
  745. XThe final sequence number in a range has the string 'E0' appended to it, which
  746. Xdoesn't affect its numeric value, but gives you something to search for if you
  747. Xwant to exclude the endpoint.
  748. XYou can exclude the beginning point by waiting for the sequence number to be
  749. Xgreater than 1.
  750. XIf either argument to .. is static, that argument is implicitly compared to
  751. Xthe $. variable, the current line number.
  752. XExamples:
  753. X.nf
  754. X
  755. X.ne 5
  756. X    if (101 .. 200) { print; }    # print 2nd hundred lines
  757. X
  758. X    next line if (1 .. /^$/);    # skip header lines
  759. X
  760. X    s/^/> / if (/^$/ .. eof());    # quote body
  761. X
  762. X.fi
  763. X.PP
  764. XHere is what C has that
  765. X.I perl
  766. Xdoesn't:
  767. X.Ip "unary &" 12
  768. XAddress-of operator.
  769. X.Ip "unary *" 12
  770. XDereference-address operator.
  771. X.PP
  772. XLike C,
  773. X.I perl
  774. Xdoes a certain amount of expression evaluation at compile time, whenever
  775. Xit determines that all of the arguments to an operator are static and have
  776. Xno side effects.
  777. XIn particular, string concatenation happens at compile time between literals that don't do variable substitution.
  778. XBackslash interpretation also happens at compile time.
  779. XYou can say
  780. X.nf
  781. X
  782. X.ne 2
  783. X    'Now is the time for all' . "\|\e\|n" .
  784. X    'good men to come to.'
  785. X
  786. X.fi
  787. Xand this all reduces to one string internally.
  788. X.PP
  789. XAlong with the literals and variables mentioned earlier,
  790. Xthe following operations can serve as terms in an expression:
  791. X.Ip "/PATTERN/" 8 4
  792. XSearches a string for a pattern, and returns true (1) or false ('').
  793. XIf no string is specified via the =~ or !~ operator,
  794. Xthe $_ string is searched.
  795. X(The string specified with =~ need not be an lvalue\*(--it may be the result of an expression evaluation, but remember the =~ binds rather tightly.)
  796. XSee also the section on regular expressions.
  797. X.Sp
  798. XIf you prepend an `m' you can use any pair of characters as delimiters.
  799. XThis is particularly useful for matching Unix path names that contain `/'.
  800. X.Sp
  801. XExamples:
  802. X.nf
  803. X
  804. X.ne 4
  805. X    open(tty, '/dev/tty');
  806. X    <tty> \|=~ \|/\|^[Yy]\|/ \|&& \|do foo(\|);    # do foo if desired
  807. X
  808. X    if (/Version: \|*\|([0-9.]*\|)\|/\|) { $version = $1; }
  809. X
  810. X    next if m#^/usr/spool/uucp#;
  811. X
  812. X.fi
  813. X.Ip "?PATTERN?" 8 4
  814. XThis is just like the /pattern/ search, except that it matches only once between
  815. Xcalls to the
  816. X.I reset
  817. Xoperator.
  818. XThis is a useful optimization when you only want to see the first occurence of
  819. Xsomething in each of a set of files, for instance.
  820. X.Ip "chdir EXPR" 8 2
  821. XChanges the working director to EXPR, if possible.
  822. XReturns 1 upon success, 0 otherwise.
  823. XSee example under die().
  824. X.Ip "chmod LIST" 8 2
  825. XChanges the permissions of a list of files.
  826. XThe first element of the list must be the numerical mode.
  827. XLIST may be an array, in which case you may wish to use the unshift()
  828. Xcommand to put the mode on the front of the array.
  829. XReturns the number of files successfully changed.
  830. XNote: in order to use the value you must put the whole thing in parentheses.
  831. X.nf
  832. X
  833. X    $cnt = (chmod 0755,'foo','bar');
  834. X
  835. X.fi
  836. X.Ip "chop(VARIABLE)" 8 5
  837. X.Ip "chop" 8
  838. XChops off the last character of a string and returns it.
  839. XIt's used primarily to remove the newline from the end of an input record,
  840. Xbut is much more efficient than s/\en// because it neither scans nor copies
  841. Xthe string.
  842. XIf VARIABLE is omitted, chops $_.
  843. XExample:
  844. X.nf
  845. X
  846. X.ne 5
  847. X    while (<>) {
  848. X        chop;    # avoid \en on last field
  849. X        @array = split(/:/);
  850. X        .\|.\|.
  851. X    }
  852. X
  853. X.fi
  854. X.Ip "chown LIST" 8 2
  855. XChanges the owner (and group) of a list of files.
  856. XLIST may be an array.
  857. XThe first two elements of the list must be the NUMERICAL uid and gid, in that order.
  858. XReturns the number of files successfully changed.
  859. XNote: in order to use the value you must put the whole thing in parentheses.
  860. X.nf
  861. X
  862. X    $cnt = (chown $uid,$gid,'foo');
  863. X
  864. X.fi
  865. XHere's an example of looking up non-numeric uids:
  866. X.nf
  867. X
  868. X.ne 16
  869. X    print "User: ";
  870. X    $user = <stdin>;
  871. X    open(pass,'/etc/passwd') || die "Can't open passwd";
  872. X    while (<pass>) {
  873. X        ($login,$pass,$uid,$gid) = split(/:/);
  874. X        $uid{$login} = $uid;
  875. X        $gid{$login} = $gid;
  876. X    }
  877. X    @ary = ('foo','bar','bie','doll');
  878. X    if ($uid{$user} eq '') {
  879. X        die "$user not in passwd file";
  880. X    }
  881. X    else {
  882. X        unshift(@ary,$uid{$user},$gid{$user});
  883. X        chown @ary;
  884. X    }
  885. X
  886. X.fi
  887. X.Ip "close(FILEHANDLE)" 8 5
  888. X.Ip "close FILEHANDLE" 8
  889. XCloses the file or pipe associated with the file handle.
  890. XYou don't have to close FILEHANDLE if you are immediately going to
  891. Xdo another open on it, since open will close it for you.
  892. X(See
  893. X.IR open .)
  894. XHowever, an explicit close on an input file resets the line counter ($.), while
  895. Xthe implicit close done by
  896. X.I open
  897. Xdoes not.
  898. XAlso, closing a pipe will wait for the process executing on the pipe to complete,
  899. Xin case you want to look at the output of the pipe afterwards.
  900. XExample:
  901. X.nf
  902. X
  903. X.ne 4
  904. X    open(output,'|sort >foo');    # pipe to sort
  905. X    ...    # print stuff to output
  906. X    close(output);        # wait for sort to finish
  907. X    open(input,'foo');    # get sort's results
  908. X
  909. X.fi
  910. X.Ip "crypt(PLAINTEXT,SALT)" 8 6
  911. XEncrypts a string exactly like the crypt() function in the C library.
  912. XUseful for checking the password file for lousy passwords.
  913. XOnly the guys wearing white hats should do this.
  914. X.Ip "die EXPR" 8 6
  915. XPrints the value of EXPR to stderr and exits with a non-zero status.
  916. XEquivalent examples:
  917. X.nf
  918. X
  919. X.ne 3
  920. X    die "Can't cd to spool." unless chdir '/usr/spool/news';
  921. X
  922. X    (chdir '/usr/spool/news') || die "Can't cd to spool." 
  923. X
  924. X.fi
  925. XNote that the parens are necessary above due to precedence.
  926. XSee also
  927. X.IR exit .
  928. X.Ip "do BLOCK" 8 4
  929. XReturns the value of the last command in the sequence of commands indicated
  930. Xby BLOCK.
  931. XWhen modified by a loop modifier, executes the BLOCK once before testing the
  932. Xloop condition.
  933. X(On other statements the loop modifiers test the conditional first.)
  934. X.Ip "do SUBROUTINE (LIST)" 8 3
  935. XExecutes a SUBROUTINE declared by a
  936. X.I sub
  937. Xdeclaration, and returns the value
  938. Xof the last expression evaluated in SUBROUTINE.
  939. X(See the section on subroutines later on.)
  940. X.Ip "each(ASSOC_ARRAY)" 8 6
  941. XReturns a 2 element array consisting of the key and value for the next
  942. Xvalue of an associative array, so that you can iterate over it.
  943. XEntries are returned in an apparently random order.
  944. XWhen the array is entirely read, a null array is returned (which when
  945. Xassigned produces a FALSE (0) value).
  946. XThe next call to each() after that will start iterating again.
  947. XThe iterator can be reset only by reading all the elements from the array.
  948. XThe following prints out your environment like the printenv program, only
  949. Xin a different order:
  950. X.nf
  951. X
  952. X.ne 3
  953. X    while (($key,$value) = each(ENV)) {
  954. X        print "$key=$value\en";
  955. X    }
  956. X
  957. X.fi
  958. XSee also keys() and values().
  959. X.Ip "eof(FILEHANDLE)" 8 8
  960. X.Ip "eof" 8
  961. XReturns 1 if the next read on FILEHANDLE will return end of file, or if
  962. XFILEHANDLE is not open.
  963. XIf (FILEHANDLE) is omitted, the eof status is returned for the last file read.
  964. XThe null filehandle may be used to indicate the pseudo file formed of the
  965. Xfiles listed on the command line, i.e. eof() is reasonable to use inside
  966. Xa while (<>) loop.
  967. XExample:
  968. X.nf
  969. X
  970. X.ne 7
  971. X    # insert dashes just before last line
  972. X    while (<>) {
  973. X        if (eof()) {
  974. X            print "--------------\en";
  975. X        }
  976. X        print;
  977. X    }
  978. X
  979. X.fi
  980. X.Ip "exec LIST" 8 6
  981. XIf there is more than one argument in LIST,
  982. Xcalls execvp() with the arguments in LIST.
  983. XIf there is only one argument, the argument is checked for shell metacharacters.
  984. XIf there are any, the entire argument is passed to /bin/sh -c for parsing.
  985. XIf there are none, the argument is split into words and passed directly to
  986. Xexecvp(), which is more efficient.
  987. XNote: exec (and system) do not flush your output buffer, so you may need to
  988. Xset $| to avoid lost output.
  989. X.Ip "exit EXPR" 8 6
  990. XEvaluates EXPR and exits immediately with that value.
  991. XExample:
  992. X.nf
  993. X
  994. X.ne 2
  995. X    $ans = <stdin>;
  996. X    exit 0 \|if \|$ans \|=~ \|/\|^[Xx]\|/\|;
  997. X
  998. X.fi
  999. XSee also
  1000. X.IR die .
  1001. X.Ip "exp(EXPR)" 8 3
  1002. XReturns e to the power of EXPR.
  1003. X.Ip "fork" 8 4
  1004. XDoes a fork() call.
  1005. XReturns the child pid to the parent process and 0 to the child process.
  1006. XNote: unflushed buffers remain unflushed in both processes, which means
  1007. Xyou may need to set $| to avoid duplicate output.
  1008. X.Ip "gmtime(EXPR)" 8 4
  1009. XConverts a time as returned by the time function to a 9-element array with
  1010. Xthe time analyzed for the Greenwich timezone.
  1011. XTypically used as follows:
  1012. X.nf
  1013. X
  1014. X.ne 3
  1015. X    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
  1016. X       = gmtime(time);
  1017. X
  1018. X.fi
  1019. XAll array elements are numeric.
  1020. X''' End of part 1
  1021. !STUFFY!FUNK!
  1022. echo Extracting perl.y
  1023. sed >perl.y <<'!STUFFY!FUNK!' -e 's/X//'
  1024. X/* $Header: perl.y,v 1.0 87/12/18 15:48:59 root Exp $
  1025. X *
  1026. X * $Log:    perl.y,v $
  1027. X * Revision 1.0  87/12/18  15:48:59  root
  1028. X * Initial revision
  1029. X * 
  1030. X */
  1031. X
  1032. X%{
  1033. X#include "handy.h"
  1034. X#include "EXTERN.h"
  1035. X#include "search.h"
  1036. X#include "util.h"
  1037. X#include "INTERN.h"
  1038. X#include "perl.h"
  1039. Xchar *tokename[] = {
  1040. X"256",
  1041. X"word",
  1042. X"append","open","write","select","close","loopctl",
  1043. X"using","format","do","shift","push","pop","chop",
  1044. X"while","until","if","unless","else","elsif","continue","split","sprintf",
  1045. X"for", "eof", "tell", "seek", "stat",
  1046. X"function(no args)","function(1 arg)","function(2 args)","function(3 args)","array function",
  1047. X"join", "sub",
  1048. X"format lines",
  1049. X"register","array_length", "array",
  1050. X"s","pattern",
  1051. X"string","y",
  1052. X"print", "unary operation",
  1053. X"..",
  1054. X"||",
  1055. X"&&",
  1056. X"==","!=", "EQ", "NE",
  1057. X"<=",">=", "LT", "GT", "LE", "GE",
  1058. X"<<",">>",
  1059. X"=~","!~",
  1060. X"unary -",
  1061. X"++", "--",
  1062. X"???"
  1063. X};
  1064. X
  1065. X%}
  1066. X
  1067. X%start prog
  1068. X
  1069. X%union {
  1070. X    int    ival;
  1071. X    char *cval;
  1072. X    ARG *arg;
  1073. X    CMD *cmdval;
  1074. X    struct compcmd compval;
  1075. X    STAB *stabval;
  1076. X    FCMD *formval;
  1077. X}
  1078. X
  1079. X%token <cval> WORD
  1080. X%token <ival> APPEND OPEN WRITE SELECT CLOSE LOOPEX
  1081. X%token <ival> USING FORMAT DO SHIFT PUSH POP CHOP
  1082. X%token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE SPLIT SPRINTF
  1083. X%token <ival> FOR FEOF TELL SEEK STAT 
  1084. X%token <ival> FUNC0 FUNC1 FUNC2 FUNC3 STABFUN
  1085. X%token <ival> JOIN SUB
  1086. X%token <formval> FORMLIST
  1087. X%token <stabval> REG ARYLEN ARY
  1088. X%token <arg> SUBST PATTERN
  1089. X%token <arg> RSTRING TRANS
  1090. X
  1091. X%type <ival> prog decl format
  1092. X%type <stabval>
  1093. X%type <cmdval> block lineseq line loop cond sideff nexpr else
  1094. X%type <arg> expr sexpr term
  1095. X%type <arg> condmod loopmod cexpr
  1096. X%type <arg> texpr print
  1097. X%type <cval> label
  1098. X%type <compval> compblock
  1099. X
  1100. X%nonassoc <ival> PRINT
  1101. X%left ','
  1102. X%nonassoc <ival> UNIOP
  1103. X%right '='
  1104. X%right '?' ':'
  1105. X%nonassoc DOTDOT
  1106. X%left OROR
  1107. X%left ANDAND
  1108. X%left '|' '^'
  1109. X%left '&'
  1110. X%nonassoc EQ NE SEQ SNE
  1111. X%nonassoc '<' '>' LE GE SLT SGT SLE SGE
  1112. X%left LS RS
  1113. X%left '+' '-' '.'
  1114. X%left '*' '/' '%' 'x'
  1115. X%left MATCH NMATCH 
  1116. X%right '!' '~' UMINUS
  1117. X%nonassoc INC DEC
  1118. X%left '('
  1119. X
  1120. X%% /* RULES */
  1121. X
  1122. Xprog    :    lineseq
  1123. X            { main_root = block_head($1); }
  1124. X    ;
  1125. X
  1126. Xcompblock:    block CONTINUE block
  1127. X            { $$.comp_true = $1; $$.comp_alt = $3; }
  1128. X    |    block else
  1129. X            { $$.comp_true = $1; $$.comp_alt = $2; }
  1130. X    ;
  1131. X
  1132. Xelse    :    /* NULL */
  1133. X            { $$ = Nullcmd; }
  1134. X    |    ELSE block
  1135. X            { $$ = $2; }
  1136. X    |    ELSIF '(' expr ')' compblock
  1137. X            { $$ = make_ccmd(C_IF,$3,$5); }
  1138. X    ;
  1139. X
  1140. Xblock    :    '{' lineseq '}'
  1141. X            { $$ = block_head($2); }
  1142. X    ;
  1143. X
  1144. Xlineseq    :    /* NULL */
  1145. X            { $$ = Nullcmd; }
  1146. X    |    lineseq line
  1147. X            { $$ = append_line($1,$2); }
  1148. X    ;
  1149. X
  1150. Xline    :    decl
  1151. X            { $$ = Nullcmd; }
  1152. X    |    label cond
  1153. X            { $$ = add_label($1,$2); }
  1154. X    |    loop    /* loops add their own labels */
  1155. X    |    label ';'
  1156. X            { if ($1 != Nullch) {
  1157. X                  $$ = add_label(make_acmd(C_EXPR, Nullstab,
  1158. X                  Nullarg, Nullarg) );
  1159. X                } else
  1160. X                  $$ = Nullcmd; }
  1161. X    |    label sideff ';'
  1162. X            { $$ = add_label($1,$2); }
  1163. X    ;
  1164. X
  1165. Xsideff    :    expr
  1166. X            { $$ = make_acmd(C_EXPR, Nullstab, $1, Nullarg); }
  1167. X    |    expr condmod
  1168. X            { $$ = addcond(
  1169. X                   make_acmd(C_EXPR, Nullstab, Nullarg, $1), $2); }
  1170. X    |    expr loopmod
  1171. X            { $$ = addloop(
  1172. X                   make_acmd(C_EXPR, Nullstab, Nullarg, $1), $2); }
  1173. X    ;
  1174. X
  1175. Xcond    :    IF '(' expr ')' compblock
  1176. X            { $$ = make_ccmd(C_IF,$3,$5); }
  1177. X    |    UNLESS '(' expr ')' compblock
  1178. X            { $$ = invert(make_ccmd(C_IF,$3,$5)); }
  1179. X    |    IF block compblock
  1180. X            { $$ = make_ccmd(C_IF,cmd_to_arg($2),$3); }
  1181. X    |    UNLESS block compblock
  1182. X            { $$ = invert(make_ccmd(C_IF,cmd_to_arg($2),$3)); }
  1183. X    ;
  1184. X
  1185. Xloop    :    label WHILE '(' texpr ')' compblock
  1186. X            { $$ = wopt(add_label($1,
  1187. X                make_ccmd(C_WHILE,$4,$6) )); }
  1188. X    |    label UNTIL '(' expr ')' compblock
  1189. X            { $$ = wopt(add_label($1,
  1190. X                invert(make_ccmd(C_WHILE,$4,$6)) )); }
  1191. X    |    label WHILE block compblock
  1192. X            { $$ = wopt(add_label($1,
  1193. X                make_ccmd(C_WHILE, cmd_to_arg($3),$4) )); }
  1194. X    |    label UNTIL block compblock
  1195. X            { $$ = wopt(add_label($1,
  1196. X                invert(make_ccmd(C_WHILE, cmd_to_arg($3),$4)) )); }
  1197. X    |    label FOR '(' nexpr ';' texpr ';' nexpr ')' block
  1198. X            /* basically fake up an initialize-while lineseq */
  1199. X            {   yyval.compval.comp_true = $10;
  1200. X                yyval.compval.comp_alt = $8;
  1201. X                $$ = append_line($4,wopt(add_label($1,
  1202. X                make_ccmd(C_WHILE,$6,yyval.compval) ))); }
  1203. X    |    label compblock    /* a block is a loop that happens once */
  1204. X            { $$ = add_label($1,make_ccmd(C_BLOCK,Nullarg,$2)); }
  1205. X    ;
  1206. X
  1207. Xnexpr    :    /* NULL */
  1208. X            { $$ = Nullcmd; }
  1209. X    |    sideff
  1210. X    ;
  1211. X
  1212. Xtexpr    :    /* NULL means true */
  1213. X            {   scanstr("1"); $$ = yylval.arg; }
  1214. X    |    expr
  1215. X    ;
  1216. X
  1217. Xlabel    :    /* empty */
  1218. X            { $$ = Nullch; }
  1219. X    |    WORD ':'
  1220. X    ;
  1221. X
  1222. Xloopmod :    WHILE expr
  1223. X            { $$ = $2; }
  1224. X    |    UNTIL expr
  1225. X            { $$ = make_op(O_NOT,1,$2,Nullarg,Nullarg,0); }
  1226. X    ;
  1227. X
  1228. Xcondmod :    IF expr
  1229. X            { $$ = $2; }
  1230. X    |    UNLESS expr
  1231. X            { $$ = make_op(O_NOT,1,$2,Nullarg,Nullarg,0); }
  1232. X    ;
  1233. X
  1234. Xdecl    :    format
  1235. X            { $$ = 0; }
  1236. X    |    subrout
  1237. X            { $$ = 0; }
  1238. X    ;
  1239. X
  1240. Xformat    :    FORMAT WORD '=' FORMLIST '.' 
  1241. X            { stabent($2,TRUE)->stab_form = $4; safefree($2); }
  1242. X    |    FORMAT '=' FORMLIST '.'
  1243. X            { stabent("stdout",TRUE)->stab_form = $3; }
  1244. X    ;
  1245. X
  1246. Xsubrout    :    SUB WORD block
  1247. X            { stabent($2,TRUE)->stab_sub = $3; }
  1248. X    ;
  1249. X
  1250. Xexpr    :    print
  1251. X    |    cexpr
  1252. X    ;
  1253. X
  1254. Xcexpr    :    sexpr ',' cexpr
  1255. X            { $$ = make_op(O_COMMA, 2, $1, $3, Nullarg,0); }
  1256. X    |    sexpr
  1257. X    ;
  1258. X
  1259. Xsexpr    :    sexpr '=' sexpr
  1260. X            {   $1 = listish($1);
  1261. X                if ($1->arg_type == O_LIST)
  1262. X                $3 = listish($3);
  1263. X                $$ = l(make_op(O_ASSIGN, 2, $1, $3, Nullarg,1)); }
  1264. X    |    sexpr '*' '=' sexpr
  1265. X            { $$ = l(make_op(O_MULTIPLY, 2, $1, $4, Nullarg,0)); }
  1266. X    |    sexpr '/' '=' sexpr
  1267. X            { $$ = l(make_op(O_DIVIDE, 2, $1, $4, Nullarg,0)); }
  1268. X    |    sexpr '%' '=' sexpr
  1269. X            { $$ = l(make_op(O_MODULO, 2, $1, $4, Nullarg,0)); }
  1270. X    |    sexpr 'x' '=' sexpr
  1271. X            { $$ = l(make_op(O_REPEAT, 2, $1, $4, Nullarg,0)); }
  1272. X    |    sexpr '+' '=' sexpr
  1273. X            { $$ = l(make_op(O_ADD, 2, $1, $4, Nullarg,0)); }
  1274. X    |    sexpr '-' '=' sexpr
  1275. X            { $$ = l(make_op(O_SUBTRACT, 2, $1, $4, Nullarg,0)); }
  1276. X    |    sexpr LS '=' sexpr
  1277. X            { $$ = l(make_op(O_LEFT_SHIFT, 2, $1, $4, Nullarg,0)); }
  1278. X    |    sexpr RS '=' sexpr
  1279. X            { $$ = l(make_op(O_RIGHT_SHIFT, 2, $1, $4, Nullarg,0)); }
  1280. X    |    sexpr '&' '=' sexpr
  1281. X            { $$ = l(make_op(O_BIT_AND, 2, $1, $4, Nullarg,0)); }
  1282. X    |    sexpr '^' '=' sexpr
  1283. X            { $$ = l(make_op(O_XOR, 2, $1, $4, Nullarg,0)); }
  1284. X    |    sexpr '|' '=' sexpr
  1285. X            { $$ = l(make_op(O_BIT_OR, 2, $1, $4, Nullarg,0)); }
  1286. X    |    sexpr '.' '=' sexpr
  1287. X            { $$ = l(make_op(O_CONCAT, 2, $1, $4, Nullarg,0)); }
  1288. X
  1289. X
  1290. X    |    sexpr '*' sexpr
  1291. X            { $$ = make_op(O_MULTIPLY, 2, $1, $3, Nullarg,0); }
  1292. X    |    sexpr '/' sexpr
  1293. X            { $$ = make_op(O_DIVIDE, 2, $1, $3, Nullarg,0); }
  1294. X    |    sexpr '%' sexpr
  1295. X            { $$ = make_op(O_MODULO, 2, $1, $3, Nullarg,0); }
  1296. X    |    sexpr 'x' sexpr
  1297. X            { $$ = make_op(O_REPEAT, 2, $1, $3, Nullarg,0); }
  1298. X    |    sexpr '+' sexpr
  1299. X            { $$ = make_op(O_ADD, 2, $1, $3, Nullarg,0); }
  1300. X    |    sexpr '-' sexpr
  1301. X            { $$ = make_op(O_SUBTRACT, 2, $1, $3, Nullarg,0); }
  1302. X    |    sexpr LS sexpr
  1303. X            { $$ = make_op(O_LEFT_SHIFT, 2, $1, $3, Nullarg,0); }
  1304. X    |    sexpr RS sexpr
  1305. X            { $$ = make_op(O_RIGHT_SHIFT, 2, $1, $3, Nullarg,0); }
  1306. X    |    sexpr '<' sexpr
  1307. X            { $$ = make_op(O_LT, 2, $1, $3, Nullarg,0); }
  1308. X    |    sexpr '>' sexpr
  1309. X            { $$ = make_op(O_GT, 2, $1, $3, Nullarg,0); }
  1310. X    |    sexpr LE sexpr
  1311. X            { $$ = make_op(O_LE, 2, $1, $3, Nullarg,0); }
  1312. X    |    sexpr GE sexpr
  1313. X            { $$ = make_op(O_GE, 2, $1, $3, Nullarg,0); }
  1314. X    |    sexpr EQ sexpr
  1315. X            { $$ = make_op(O_EQ, 2, $1, $3, Nullarg,0); }
  1316. X    |    sexpr NE sexpr
  1317. X            { $$ = make_op(O_NE, 2, $1, $3, Nullarg,0); }
  1318. X    |    sexpr SLT sexpr
  1319. X            { $$ = make_op(O_SLT, 2, $1, $3, Nullarg,0); }
  1320. X    |    sexpr SGT sexpr
  1321. X            { $$ = make_op(O_SGT, 2, $1, $3, Nullarg,0); }
  1322. X    |    sexpr SLE sexpr
  1323. X            { $$ = make_op(O_SLE, 2, $1, $3, Nullarg,0); }
  1324. X    |    sexpr SGE sexpr
  1325. X            { $$ = make_op(O_SGE, 2, $1, $3, Nullarg,0); }
  1326. X    |    sexpr SEQ sexpr
  1327. X            { $$ = make_op(O_SEQ, 2, $1, $3, Nullarg,0); }
  1328. X    |    sexpr SNE sexpr
  1329. X            { $$ = make_op(O_SNE, 2, $1, $3, Nullarg,0); }
  1330. X    |    sexpr '&' sexpr
  1331. X            { $$ = make_op(O_BIT_AND, 2, $1, $3, Nullarg,0); }
  1332. X    |    sexpr '^' sexpr
  1333. X            { $$ = make_op(O_XOR, 2, $1, $3, Nullarg,0); }
  1334. X    |    sexpr '|' sexpr
  1335. X            { $$ = make_op(O_BIT_OR, 2, $1, $3, Nullarg,0); }
  1336. X    |    sexpr DOTDOT sexpr
  1337. X            { $$ = make_op(O_FLIP, 4,
  1338. X                flipflip($1),
  1339. X                flipflip($3),
  1340. X                Nullarg,0);}
  1341. X    |    sexpr ANDAND sexpr
  1342. X            { $$ = make_op(O_AND, 2, $1, $3, Nullarg,0); }
  1343. X    |    sexpr OROR sexpr
  1344. X            { $$ = make_op(O_OR, 2, $1, $3, Nullarg,0); }
  1345. X    |    sexpr '?' sexpr ':' sexpr
  1346. X            { $$ = make_op(O_COND_EXPR, 3, $1, $3, $5,0); }
  1347. X    |    sexpr '.' sexpr
  1348. X            { $$ = make_op(O_CONCAT, 2, $1, $3, Nullarg,0); }
  1349. X    |    sexpr MATCH sexpr
  1350. X            { $$ = mod_match(O_MATCH, $1, $3); }
  1351. X    |    sexpr NMATCH sexpr
  1352. X            { $$ = mod_match(O_NMATCH, $1, $3); }
  1353. X    |    term INC
  1354. X            { $$ = addflags(1, AF_POST|AF_UP,
  1355. X                l(make_op(O_ITEM,1,$1,Nullarg,Nullarg,0))); }
  1356. X    |    term DEC
  1357. X            { $$ = addflags(1, AF_POST,
  1358. X                l(make_op(O_ITEM,1,$1,Nullarg,Nullarg,0))); }
  1359. X    |    INC term
  1360. X            { $$ = addflags(1, AF_PRE|AF_UP,
  1361. X                l(make_op(O_ITEM,1,$2,Nullarg,Nullarg,0))); }
  1362. X    |    DEC term
  1363. X            { $$ = addflags(1, AF_PRE,
  1364. X                l(make_op(O_ITEM,1,$2,Nullarg,Nullarg,0))); }
  1365. X    |    term
  1366. X            { $$ = $1; }
  1367. X    ;
  1368. X
  1369. Xterm    :    '-' term %prec UMINUS
  1370. X            { $$ = make_op(O_NEGATE, 1, $2, Nullarg, Nullarg,0); }
  1371. X    |    '!' term
  1372. X            { $$ = make_op(O_NOT, 1, $2, Nullarg, Nullarg,0); }
  1373. X    |    '~' term
  1374. X            { $$ = make_op(O_COMPLEMENT, 1, $2, Nullarg, Nullarg,0);}
  1375. X    |    '(' expr ')'
  1376. X            { $$ = make_list(hide_ary($2)); }
  1377. X    |    '(' ')'
  1378. X            { $$ = make_list(Nullarg); }
  1379. X    |    DO block    %prec '('
  1380. X            { $$ = cmd_to_arg($2); }
  1381. X    |    REG    %prec '('
  1382. X            { $$ = stab_to_arg(A_STAB,$1); }
  1383. X    |    REG '[' expr ']'    %prec '('
  1384. X            { $$ = make_op(O_ARRAY, 2,
  1385. X                $3, stab_to_arg(A_STAB,aadd($1)), Nullarg,0); }
  1386. X    |    ARY     %prec '('
  1387. X            { $$ = make_op(O_ARRAY, 1,
  1388. X                stab_to_arg(A_STAB,$1),
  1389. X                Nullarg, Nullarg, 1); }
  1390. X    |    REG '{' expr '}'    %prec '('
  1391. X            { $$ = make_op(O_HASH, 2,
  1392. X                $3, stab_to_arg(A_STAB,hadd($1)), Nullarg,0); }
  1393. X    |    ARYLEN    %prec '('
  1394. X            { $$ = stab_to_arg(A_ARYLEN,$1); }
  1395. X    |    RSTRING    %prec '('
  1396. X            { $$ = $1; }
  1397. X    |    PATTERN    %prec '('
  1398. X            { $$ = $1; }
  1399. X    |    SUBST    %prec '('
  1400. X            { $$ = $1; }
  1401. X    |    TRANS    %prec '('
  1402. X            { $$ = $1; }
  1403. X    |    DO WORD '(' expr ')'
  1404. X            { $$ = make_op(O_SUBR, 2,
  1405. X                make_list($4),
  1406. X                stab_to_arg(A_STAB,stabent($2,TRUE)),
  1407. X                Nullarg,1); }
  1408. X    |    DO WORD '(' ')'
  1409. X            { $$ = make_op(O_SUBR, 2,
  1410. X                make_list(Nullarg),
  1411. X                stab_to_arg(A_STAB,stabent($2,TRUE)),
  1412. X                Nullarg,1); }
  1413. X    |    LOOPEX
  1414. X            { $$ = make_op($1,0,Nullarg,Nullarg,Nullarg,0); }
  1415. X    |    LOOPEX WORD
  1416. X            { $$ = make_op($1,1,cval_to_arg($2),
  1417. X                Nullarg,Nullarg,0); }
  1418. X    |    UNIOP
  1419. X            { $$ = make_op($1,1,Nullarg,Nullarg,Nullarg,0); }
  1420. X    |    UNIOP sexpr
  1421. X            { $$ = make_op($1,1,$2,Nullarg,Nullarg,0); }
  1422. X    |    WRITE
  1423. X            { $$ = make_op(O_WRITE, 0,
  1424. X                Nullarg, Nullarg, Nullarg,0); }
  1425. X    |    WRITE '(' ')'
  1426. X            { $$ = make_op(O_WRITE, 0,
  1427. X                Nullarg, Nullarg, Nullarg,0); }
  1428. X    |    WRITE '(' WORD ')'
  1429. X            { $$ = l(make_op(O_WRITE, 1,
  1430. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1431. X                Nullarg, Nullarg,0)); safefree($3); }
  1432. X    |    WRITE '(' expr ')'
  1433. X            { $$ = make_op(O_WRITE, 1, $3, Nullarg, Nullarg,0); }
  1434. X    |    SELECT '(' WORD ')'
  1435. X            { $$ = l(make_op(O_SELECT, 1,
  1436. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1437. X                Nullarg, Nullarg,0)); safefree($3); }
  1438. X    |    SELECT '(' expr ')'
  1439. X            { $$ = make_op(O_SELECT, 1, $3, Nullarg, Nullarg,0); }
  1440. X    |    OPEN WORD    %prec '('
  1441. X            { $$ = make_op(O_OPEN, 2,
  1442. X                stab_to_arg(A_STAB,stabent($2,TRUE)),
  1443. X                stab_to_arg(A_STAB,stabent($2,TRUE)),
  1444. X                Nullarg,0); }
  1445. X    |    OPEN '(' WORD ')'
  1446. X            { $$ = make_op(O_OPEN, 2,
  1447. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1448. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1449. X                Nullarg,0); }
  1450. X    |    OPEN '(' WORD ',' expr ')'
  1451. X            { $$ = make_op(O_OPEN, 2,
  1452. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1453. X                $5, Nullarg,0); }
  1454. X    |    CLOSE '(' WORD ')'
  1455. X            { $$ = make_op(O_CLOSE, 1,
  1456. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1457. X                Nullarg, Nullarg,0); }
  1458. X    |    CLOSE WORD    %prec '('
  1459. X            { $$ = make_op(O_CLOSE, 1,
  1460. X                stab_to_arg(A_STAB,stabent($2,TRUE)),
  1461. X                Nullarg, Nullarg,0); }
  1462. X    |    FEOF '(' WORD ')'
  1463. X            { $$ = make_op(O_EOF, 1,
  1464. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1465. X                Nullarg, Nullarg,0); }
  1466. X    |    FEOF '(' ')'
  1467. X            { $$ = make_op(O_EOF, 0,
  1468. X                stab_to_arg(A_STAB,stabent("ARGV",TRUE)),
  1469. X                Nullarg, Nullarg,0); }
  1470. X    |    FEOF
  1471. X            { $$ = make_op(O_EOF, 0,
  1472. X                Nullarg, Nullarg, Nullarg,0); }
  1473. X    |    TELL '(' WORD ')'
  1474. X            { $$ = make_op(O_TELL, 1,
  1475. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1476. X                Nullarg, Nullarg,0); }
  1477. X    |    TELL
  1478. X            { $$ = make_op(O_TELL, 0,
  1479. X                Nullarg, Nullarg, Nullarg,0); }
  1480. X    |    SEEK '(' WORD ',' sexpr ',' expr ')'
  1481. X            { $$ = make_op(O_SEEK, 3,
  1482. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1483. X                $5, $7,1); }
  1484. X    |    PUSH '(' WORD ',' expr ')'
  1485. X            { $$ = make_op($1, 2,
  1486. X                make_list($5),
  1487. X                stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
  1488. X                Nullarg,1); }
  1489. X    |    PUSH '(' ARY ',' expr ')'
  1490. X            { $$ = make_op($1, 2,
  1491. X                make_list($5),
  1492. X                stab_to_arg(A_STAB,$3),
  1493. X                Nullarg,1); }
  1494. X    |    POP WORD    %prec '('
  1495. X            { $$ = make_op(O_POP, 1,
  1496. X                stab_to_arg(A_STAB,aadd(stabent($2,TRUE))),
  1497. X                Nullarg, Nullarg,0); }
  1498. X    |    POP '(' WORD ')'
  1499. X            { $$ = make_op(O_POP, 1,
  1500. X                stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
  1501. X                Nullarg, Nullarg,0); }
  1502. X    |    POP ARY    %prec '('
  1503. X            { $$ = make_op(O_POP, 1,
  1504. X                stab_to_arg(A_STAB,$2),
  1505. X                Nullarg,
  1506. X                Nullarg,
  1507. X                0); }
  1508. X    |    POP '(' ARY ')'
  1509. X            { $$ = make_op(O_POP, 1,
  1510. X                stab_to_arg(A_STAB,$3),
  1511. X                Nullarg,
  1512. X                Nullarg,
  1513. X                0); }
  1514. X    |    SHIFT WORD    %prec '('
  1515. X            { $$ = make_op(O_SHIFT, 1,
  1516. X                stab_to_arg(A_STAB,aadd(stabent($2,TRUE))),
  1517. X                Nullarg, Nullarg,0); }
  1518. X    |    SHIFT '(' WORD ')'
  1519. X            { $$ = make_op(O_SHIFT, 1,
  1520. X                stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
  1521. X                Nullarg, Nullarg,0); }
  1522. X    |    SHIFT ARY    %prec '('
  1523. X            { $$ = make_op(O_SHIFT, 1,
  1524. X                stab_to_arg(A_STAB,$2), Nullarg, Nullarg,0); }
  1525. X    |    SHIFT '(' ARY ')'
  1526. X            { $$ = make_op(O_SHIFT, 1,
  1527. X                stab_to_arg(A_STAB,$3), Nullarg, Nullarg,0); }
  1528. X    |    SHIFT    %prec '('
  1529. X            { $$ = make_op(O_SHIFT, 1,
  1530. X                stab_to_arg(A_STAB,aadd(stabent("ARGV",TRUE))),
  1531. X                Nullarg, Nullarg,0); }
  1532. X    |    SPLIT    %prec '('
  1533. X            { scanpat("/[ \t\n]+/");
  1534. X                $$ = make_split(defstab,yylval.arg); }
  1535. X    |    SPLIT '(' WORD ')'
  1536. X            { scanpat("/[ \t\n]+/");
  1537. X                $$ = make_split(stabent($3,TRUE),yylval.arg); }
  1538. X    |    SPLIT '(' WORD ',' PATTERN ')'
  1539. X            { $$ = make_split(stabent($3,TRUE),$5); }
  1540. X    |    SPLIT '(' WORD ',' PATTERN ',' sexpr ')'
  1541. X            { $$ = mod_match(O_MATCH,
  1542. X                $7,
  1543. X                make_split(stabent($3,TRUE),$5) ); }
  1544. X    |    SPLIT '(' sexpr ',' sexpr ')'
  1545. X            { $$ = mod_match(O_MATCH, $5, make_split(defstab,$3) ); }
  1546. X    |    SPLIT '(' sexpr ')'
  1547. X            { $$ = mod_match(O_MATCH,
  1548. X                stab_to_arg(A_STAB,defstab),
  1549. X                make_split(defstab,$3) ); }
  1550. X    |    JOIN '(' WORD ',' expr ')'
  1551. X            { $$ = make_op(O_JOIN, 2,
  1552. X                $5,
  1553. X                stab_to_arg(A_STAB,aadd(stabent($3,TRUE))),
  1554. X                Nullarg,0); }
  1555. X    |    JOIN '(' sexpr ',' expr ')'
  1556. X            { $$ = make_op(O_JOIN, 2,
  1557. X                $3,
  1558. X                make_list($5),
  1559. X                Nullarg,2); }
  1560. X    |    SPRINTF '(' expr ')'
  1561. X            { $$ = make_op(O_SPRINTF, 1,
  1562. X                make_list($3),
  1563. X                Nullarg,
  1564. X                Nullarg,1); }
  1565. X    |    STAT '(' WORD ')'
  1566. X            { $$ = l(make_op(O_STAT, 1,
  1567. X                stab_to_arg(A_STAB,stabent($3,TRUE)),
  1568. X                Nullarg, Nullarg,0)); }
  1569. X    |    STAT '(' expr ')'
  1570. X            { $$ = make_op(O_STAT, 1, $3, Nullarg, Nullarg,0); }
  1571. X    |    CHOP
  1572. X            { $$ = l(make_op(O_CHOP, 1,
  1573. X                stab_to_arg(A_STAB,defstab),
  1574. X                Nullarg, Nullarg,0)); }
  1575. X    |    CHOP '(' expr ')'
  1576. X            { $$ = l(make_op(O_CHOP, 1, $3, Nullarg, Nullarg,0)); }
  1577. X    |    FUNC0
  1578. X            { $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg,0); }
  1579. X    |    FUNC1 '(' expr ')'
  1580. X            { $$ = make_op($1, 1, $3, Nullarg, Nullarg,0); }
  1581. X    |    FUNC2 '(' sexpr ',' expr ')'
  1582. X            { $$ = make_op($1, 2, $3, $5, Nullarg, 0); }
  1583. X    |    FUNC3 '(' sexpr ',' sexpr ',' expr ')'
  1584. X            { $$ = make_op($1, 3, $3, $5, $7, 0); }
  1585. X    |    STABFUN '(' WORD ')'
  1586. X            { $$ = make_op($1, 1,
  1587. X                stab_to_arg(A_STAB,hadd(stabent($3,TRUE))),
  1588. X                Nullarg,
  1589. X                Nullarg, 0); }
  1590. X    ;
  1591. X
  1592. Xprint    :    PRINT
  1593. X            { $$ = make_op($1,2,
  1594. X                stab_to_arg(A_STAB,defstab),
  1595. X                stab_to_arg(A_STAB,Nullstab),
  1596. X                Nullarg,0); }
  1597. X    |    PRINT expr
  1598. X            { $$ = make_op($1,2,make_list($2),
  1599. X                stab_to_arg(A_STAB,Nullstab),
  1600. X                Nullarg,1); }
  1601. X    |    PRINT WORD
  1602. X            { $$ = make_op($1,2,
  1603. X                stab_to_arg(A_STAB,defstab),
  1604. X                stab_to_arg(A_STAB,stabent($2,TRUE)),
  1605. X                Nullarg,1); }
  1606. X    |    PRINT WORD expr
  1607. X            { $$ = make_op($1,2,make_list($3),
  1608. X                stab_to_arg(A_STAB,stabent($2,TRUE)),
  1609. X                Nullarg,1); }
  1610. X    ;
  1611. X
  1612. X%% /* PROGRAM */
  1613. X#include "perly.c"
  1614. !STUFFY!FUNK!
  1615. echo Extracting t/io.fs
  1616. sed >t/io.fs <<'!STUFFY!FUNK!' -e 's/X//'
  1617. X#!./perl
  1618. X
  1619. X# $Header: io.fs,v 1.0 87/12/18 13:12:48 root Exp $
  1620. X
  1621. Xprint "1..18\n";
  1622. X
  1623. Xchdir '/tmp';
  1624. X`/bin/rm -rf a b c x`;
  1625. X
  1626. Xumask(022);
  1627. X
  1628. Xif (umask(0) == 022) {print "ok 1\n";} else {print "not ok 1\n";}
  1629. Xopen(fh,'>x') || die "Can't create x";
  1630. Xclose(fh);
  1631. Xopen(fh,'>a') || die "Can't create a";
  1632. Xclose(fh);
  1633. X
  1634. Xif (link('a','b')) {print "ok 2\n";} else {print "not ok 2\n";}
  1635. X
  1636. Xif (link('b','c')) {print "ok 3\n";} else {print "not ok 3\n";}
  1637. X
  1638. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1639. X    $blksize,$blocks) = stat('c');
  1640. X
  1641. Xif ($nlink == 3) {print "ok 4\n";} else {print "not ok 4\n";}
  1642. Xif (($mode & 0777) == 0666) {print "ok 5\n";} else {print "not ok 5\n";}
  1643. X
  1644. Xif ((chmod 0777,'a') == 1) {print "ok 6\n";} else {print "not ok 6\n";}
  1645. X
  1646. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1647. X    $blksize,$blocks) = stat('c');
  1648. Xif (($mode & 0777) == 0777) {print "ok 7\n";} else {print "not ok 7\n";}
  1649. X
  1650. Xif ((chmod 0700,'c','x') == 2) {print "ok 8\n";} else {print "not ok 8\n";}
  1651. X
  1652. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1653. X    $blksize,$blocks) = stat('c');
  1654. Xif (($mode & 0777) == 0700) {print "ok 9\n";} else {print "not ok 9\n";}
  1655. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1656. X    $blksize,$blocks) = stat('x');
  1657. Xif (($mode & 0777) == 0700) {print "ok 10\n";} else {print "not ok 10\n";}
  1658. X
  1659. Xif ((unlink 'b','x') == 2) {print "ok 11\n";} else {print "not ok 11\n";}
  1660. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1661. X    $blksize,$blocks) = stat('b');
  1662. Xif ($ino == 0) {print "ok 12\n";} else {print "not ok 12\n";}
  1663. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1664. X    $blksize,$blocks) = stat('x');
  1665. Xif ($ino == 0) {print "ok 13\n";} else {print "not ok 13\n";}
  1666. X
  1667. Xif (rename('a','b')) {print "ok 14\n";} else {print "not ok 14\n";}
  1668. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1669. X    $blksize,$blocks) = stat('a');
  1670. Xif ($ino == 0) {print "ok 15\n";} else {print "not ok 15\n";}
  1671. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1672. X    $blksize,$blocks) = stat('b');
  1673. Xif ($ino) {print "ok 16\n";} else {print "not ok 16\n";}
  1674. X
  1675. Xif ((unlink 'b') == 1) {print "ok 17\n";} else {print "not ok 17\n";}
  1676. X($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
  1677. X    $blksize,$blocks) = stat('b');
  1678. Xif ($ino == 0) {print "ok 18\n";} else {print "not ok 18\n";}
  1679. Xunlink 'c';
  1680. !STUFFY!FUNK!
  1681. echo ""
  1682. echo "End of kit 5 (of 10)"
  1683. cat /dev/null >kit5isdone
  1684. config=true
  1685. for iskit in 1 2 3 4 5 6 7 8 9 10; do
  1686.     if test -f kit${iskit}isdone; then
  1687.     echo "You have run kit ${iskit}."
  1688.     else
  1689.     echo "You still need to run kit ${iskit}."
  1690.     config=false
  1691.     fi
  1692. done
  1693. case $config in
  1694.     true)
  1695.     echo "You have run all your kits.  Please read README and then type Configure."
  1696.     chmod 755 Configure
  1697.     ;;
  1698. esac
  1699. : Someone might mail this, so...
  1700. exit
  1701.