home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume20 / perl3.0 / part20 < prev    next >
Text File  |  1989-11-01  |  50KB  |  1,793 lines

  1. Subject:  v20i103:  Perl, a language with features of C/sed/awk/shell/etc, Part20/24
  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 20, Issue 103
  8. Archive-name: perl3.0/part20
  9.  
  10. #! /bin/sh
  11.  
  12. # Make a new directory for the perl sources, cd to it, and run kits 1
  13. # thru 24 through sh.  When all 24 kits have been run, read README.
  14.  
  15. echo "This is perl 3.0 kit 20 (of 24).  If kit 20 is complete, the line"
  16. echo '"'"End of kit 20 (of 24)"'" will echo at the end.'
  17. echo ""
  18. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  19. mkdir x2p 2>/dev/null
  20. echo Extracting Changes
  21. sed >Changes <<'!STUFFY!FUNK!' -e 's/X//'
  22. XChanges to perl
  23. X---------------
  24. X
  25. XApart from little bug fixes, here are the new features:
  26. X
  27. XPerl can now handle binary data correctly and has functions to pack and
  28. Xunpack binary structures into arrays or lists.  You can now do arbitrary
  29. Xioctl functions.
  30. X
  31. XYou can do i/o with sockets and select.
  32. X
  33. XYou can now write packages with their own namespace.
  34. X
  35. XYou can now pass things to subroutines by reference.
  36. X
  37. XThe debugger now has hooks in the perl parser so it doesn't get confused.
  38. XThe debugger won't interfere with stdin and stdout.  New debugger commands:
  39. X    n        Single step around subroutine call.
  40. X    l min+incr    List incr+1 lines starting at min.
  41. X    l        List incr+1 more lines.
  42. X    l subname    List subroutine.
  43. X    b subname    Set breakpoint at first line of subroutine.
  44. X    S        List subroutine names.
  45. X    D        Delete all breakpoints.
  46. X    A        List line actions.
  47. X    < command    Define command before prompt.
  48. X    > command    Define command after prompt.
  49. X    ! number    Redo command (default previous command).
  50. X    ! -number    Redo numberth to last command.
  51. X    h -number    Display last number commands (default all).
  52. X    p expr        Same as \"print DBout expr\".
  53. X
  54. XThe rules are more consistent about where parens are needed and
  55. Xwhere they are not.  In particular, unary operators and list operators now
  56. Xbehave like functions if they're called like functions.
  57. X
  58. XThere are some new quoting mechanisms:
  59. X    $foo = q/"'"'"'"'"'"'"/;
  60. X    $foo = qq/"'"''$bar"''/;
  61. X    $foo = q(hi there);
  62. X    $foo = <<'EOF' x 10;
  63. X    Why, it's the old here-is mechanism!
  64. X    EOF
  65. X
  66. XYou can now work with array slices (note the initial @):
  67. X    @foo[1,2,3];
  68. X    @foo{'Sun','Mon','Tue','Wed','Thu','Fri','Sat'} = (1,2,3,4,5,6,7);
  69. X    @foo{split} = (1,1,1,1,1,1,1);
  70. X
  71. XThere's now a range operator that works in array contexts:
  72. X    for (1..15) { ...
  73. X    @foo[3..5] = ('time','for','all');
  74. X    @foo{'Sun','Mon','Tue','Wed','Thu','Fri','Sat'} = 1..7;
  75. X
  76. XYou can now reference associative arrays as a whole:
  77. X    %abc = %def;
  78. X    %foo = ('Sun',1,'Mon',2,'Tue',3,'Wed',4,'Thu',5,'Fri',6,'Sat',7);
  79. X
  80. XAssociative arrays can now be bound to a dbm or ndbm file.  Perl automatically
  81. Xcaches references to the dbm file for you.
  82. X
  83. XAn array or associative array can now be assigned to as part of a list, if
  84. Xit's the last thing in the list:
  85. X    ($a,$b,@rest) = split;
  86. X
  87. XAn array or associative array may now appear in a local() list.
  88. X    local(%assoc);
  89. X    local(@foo) = @_;
  90. X
  91. XArray values may now be interpolated into strings:
  92. X    `echo @ARGV`;
  93. X    print "first three = @list[0..2]\n";
  94. X    print "@ENV{keys(ENV)}";
  95. X    ($" is used as the delimiter between array elements)
  96. X
  97. XArray sizes may be interpolated into strings:
  98. X    print "The last element is $#foo.\n";
  99. X
  100. XArray values may now be returned from subroutines, evals, and do blocks.
  101. X
  102. XLists of values in formats may now be arbitrary expressions, separated
  103. Xby commas.
  104. X
  105. XSubroutine names are now distinguished by prefixing with &.  You can call
  106. Xsubroutines without using do, and without passing any argument list at all:
  107. X    $foo = &min($a,$b,$c);
  108. X    $num = &myrand;
  109. X
  110. XYou can use the new -u switch to cause perl to dump core so that you can
  111. Xrun undump and produce a binary executable image.  Alternately you can
  112. Xuse the "dump" operator after initializing any variables and such.
  113. X
  114. XPerl now optimizes splits that are assigned directly to an array, or
  115. Xto a list with fewer elements than the split would produce, or that
  116. Xsplit on a constant string.
  117. X
  118. XPerl now optimizes on end matches such as /foo$/;
  119. X
  120. XPerl now recognizes {n,m} in patterns to match preceding item at least n times
  121. Xand no more than m times.  Also recognizes {n,} and {n} to match n or more
  122. Xtimes, or exactly n times.  If { occurs in other than this context it is
  123. Xstill treated as a normal character.
  124. X
  125. XPerl now optimizes "next" to avoid unnecessary longjmps and subroutine calls.
  126. X
  127. XPerl now optimizes appended input: $_ .= <>;
  128. X
  129. XSubstitutions are faster if the substituted text is constant, especially
  130. Xwhen substituting at the beginning of a string.  This plus the previous
  131. Xoptimization let you run down a file comparing multiple lines more
  132. Xefficiently. (Basically the equivalents of sed's N and D are faster.)
  133. X
  134. XSimilarly, combinations of shifts and pushes on the same array are much
  135. Xfaster now--it doesn't copy all the pointers every time you shift (just
  136. Xevery n times, where n is approximately the length of the array plus 10,
  137. Xmore if you pre-extend the array), so you can use an array as a shift
  138. Xregister much more efficiently:
  139. X    push(@ary,shift(@ary));
  140. Xor
  141. X    shift(@ary); push(@ary,<>);
  142. X
  143. XThe shift operator used inside subroutines now defaults to shifting
  144. Xthe @_ array.  You can still shift ARGV explicitly, of course.
  145. X
  146. XThe @_ array which is passed to subroutines is a local array, but the
  147. Xelements of it are passed by reference now.  This means that if you
  148. Xexplicitly modify $_[0], you are actually modifying the first argument
  149. Xto the routine.  Assignment to another location (such as the usual
  150. Xlocal($foo) = @_ trick) causes a copy of the value, so this will not
  151. Xaffect most scripts.  However, if you've modified @_ values in the
  152. Xsubroutine you could be in for a surprise.  I don't believe most people
  153. Xwill find this a problem, and the long term efficiency gain is worth
  154. Xa little confusion.
  155. X
  156. XPerl now detects sequences of references to the same variable and builds
  157. Xswitch statements internally wherever reasonable.
  158. X
  159. XThe substr function can take offsets from the end of the string.
  160. X
  161. XThe substr function can be assigned to in order to change the interior of a
  162. Xstring in place.
  163. X
  164. XThe split function can return as part of the returned array any substrings
  165. Xmatched as part of the delimiter:
  166. X    split(/([-,])/, '1-10,20')
  167. Xreturns
  168. X    (1,'-',10,',',20)
  169. X
  170. XIf you specify a maximum number of fields to split, the truncation of
  171. Xtrailing null fields is disabled.
  172. X
  173. XYou can now chop lists.
  174. X
  175. XPerl now uses /bin/csh to do filename globbing, if available.  This means
  176. Xthat filenames with spaces or other strangenesses work right.
  177. X
  178. XPerl can now report multiple syntax errors with a single invocation.
  179. X
  180. XPerl syntax errors now give two tokens of context where reasonable.
  181. X
  182. XPerl will now report the possibility of a runaway multi-line string if
  183. Xsuch a string ends on a line with a syntax error.
  184. X
  185. XThe assumed assignment in a while now works in the while modifier as
  186. Xwell as the while statement.
  187. X
  188. XPerl can now warn you if you use numeric == on non-numeric string values.
  189. X
  190. XNew functions:
  191. X    mkdir and rmdir
  192. X    getppid
  193. X    getpgrp and setpgrp
  194. X    getpriority and setpriority
  195. X    chroot
  196. X    ioctl and fcntl
  197. X    flock
  198. X    readlink
  199. X    lstat
  200. X    rindex            - find last occurrence of substring
  201. X    pack and unpack        - turn structures into arrays and vice versa
  202. X    read            - just what you think
  203. X    warn            - like die, only not fatal
  204. X    dbmopen and dbmclose    - bind a dbm file to an associative array
  205. X    dump            - do core dump so you can undump
  206. X    reverse            - turns an array value end for end
  207. X        defined                 - does an object exist?
  208. X        undef                   - make an object not exist
  209. X    vec            - treat string as a vector of small integers
  210. X    fileno            - return the file descriptor for a handle
  211. X    wantarray        - was subroutine called in array context?
  212. X    opendir
  213. X    readdir
  214. X    telldir
  215. X    seekdir
  216. X    rewinddir
  217. X    closedir
  218. X    syscall
  219. X    socket
  220. X    bind
  221. X    connect
  222. X    listen
  223. X    accept
  224. X    shutdown
  225. X    socketpair
  226. X    getsockname
  227. X    getpeername
  228. X    getsockopt
  229. X    setsockopt
  230. X    getpwnam
  231. X    getpwuid
  232. X    getpwent
  233. X    setpwent
  234. X    endpwent
  235. X    getgrnam
  236. X    getgrgid
  237. X    getgrent
  238. X    setgrent
  239. X    endgrent
  240. X    gethostbyname
  241. X    gethostbyaddr
  242. X    gethostent
  243. X    sethostent
  244. X    endhostent
  245. X    getnetbyname
  246. X    getnetbyaddr
  247. X    getnetent
  248. X    setnetent
  249. X    endnetent
  250. X    getprotobyname
  251. X    getprotobynumber
  252. X    getprotoent
  253. X    setprotoent
  254. X    endprotoent
  255. X    getservbyname
  256. X    getservbyport
  257. X    getservent
  258. X    setservent
  259. X    endservent
  260. X
  261. XChanges to s2p
  262. X--------------
  263. X
  264. XIn patterns, s2p now translates \{n,m\} correctly to {n,m}.
  265. X
  266. XIn patterns, s2p no longer removes backslashes in front of |.
  267. X
  268. XIn patterns, s2p now removes backslashes in front of [a-zA-Z0-9].
  269. X
  270. XS2p now makes use of the location of perl as determined by Configure.
  271. X
  272. X
  273. XChanges to a2p
  274. X--------------
  275. X
  276. XA2p can now accurately translate the "in" operator by using perl's new
  277. X"defined" operator.
  278. X
  279. XA2p can now accurately translate the passing of arrays by reference.
  280. X
  281. !STUFFY!FUNK!
  282. echo Extracting MANIFEST
  283. sed >MANIFEST <<'!STUFFY!FUNK!' -e 's/X//'
  284. XChanges            Differences between 2.0 level 18 and 3.0 level 0
  285. XConfigure        Run this first
  286. XCopying            The GNU General Public License
  287. XEXTERN.h        Included before foreign .h files
  288. XINTERN.h        Included before domestic .h files
  289. XMANIFEST        This list of files
  290. XMakefile.SH        Precursor to Makefile
  291. XPACKINGLIST        Which files came from which kits
  292. XREADME            The Instructions
  293. XWishlist        Some things that may or may not happen
  294. Xarg.h            Public declarations for the above
  295. Xarray.c            Numerically subscripted arrays
  296. Xarray.h            Public declarations for the above
  297. Xclient            A client to test sockets
  298. Xcmd.c            Command interpreter
  299. Xcmd.h            Public declarations for the above
  300. Xconfig.H        Sample config.h
  301. Xconfig.h.SH        Produces config.h
  302. Xcons.c            Routines to construct cmd nodes of a parse tree
  303. Xconsarg.c        Routines to construct arg nodes of a parse tree
  304. Xdoarg.c            Scalar expression evaluation
  305. Xdoio.c            I/O operations
  306. Xdolist.c        Array expression evaluation
  307. Xdump.c            Debugging output
  308. Xeg/ADB            An adb wrapper to put in your crash dir
  309. Xeg/README        Intro to example perl scripts
  310. Xeg/changes        A program to list recently changed files
  311. Xeg/down            A program to do things to subdirectories
  312. Xeg/dus            A program to do du -s on non-mounted dirs
  313. Xeg/findcp        A find wrapper that implements a -cp switch
  314. Xeg/findtar        A find wrapper that pumps out a tar file
  315. Xeg/g/gcp        A program to do a global rcp
  316. Xeg/g/gcp.man        Manual page for gcp
  317. Xeg/g/ged        A program to do a global edit
  318. Xeg/g/ghosts        A sample /etc/ghosts file
  319. Xeg/g/gsh        A program to do a global rsh
  320. Xeg/g/gsh.man        Manual page for gsh
  321. Xeg/muck            A program to find missing make dependencies
  322. Xeg/muck.man        Manual page for muck
  323. Xeg/myrup        A program to find lightly loaded machines
  324. Xeg/nih            Script to insert #! workaround
  325. Xeg/rename        A program to rename files
  326. Xeg/rmfrom        A program to feed doomed filenames to
  327. Xeg/scan/scan_df        Scan for filesystem anomalies
  328. Xeg/scan/scan_last    Scan for login anomalies
  329. Xeg/scan/scan_messages    Scan for console message anomalies
  330. Xeg/scan/scan_passwd    Scan for passwd file anomalies
  331. Xeg/scan/scan_ps        Scan for process anomalies
  332. Xeg/scan/scan_sudo    Scan for sudo anomalies
  333. Xeg/scan/scan_suid    Scan for setuid anomalies
  334. Xeg/scan/scanner        An anomaly reporter
  335. Xeg/shmkill        A program to remove unused shared memory
  336. Xeg/van/empty        A program to empty the trashcan
  337. Xeg/van/unvanish        A program to undo what vanish does
  338. Xeg/van/vanexp        A program to expire vanished files
  339. Xeg/van/vanish        A program to put files in a trashcan
  340. Xeg/who            A sample who program
  341. Xeval.c            The expression evaluator
  342. Xevalargs.xc        The arg evaluator of eval.c
  343. Xform.c            Format processing
  344. Xform.h            Public declarations for the above
  345. Xgettest            A little script to test the get* routines
  346. Xhandy.h            Handy definitions
  347. Xhash.c            Associative arrays
  348. Xhash.h            Public declarations for the above
  349. Xioctl.pl        Sample ioctl.pl
  350. Xlib/abbrev.pl        An abbreviation table builder
  351. Xlib/look.pl        A "look" equivalent
  352. Xlib/complete.pl        A command completion subroutine
  353. Xlib/dumpvar.pl        A variable dumper
  354. Xlib/getopt.pl        Perl library supporting option parsing
  355. Xlib/getopts.pl        Perl library supporting option parsing
  356. Xlib/importenv.pl    Perl routine to get environment into variables
  357. Xlib/perldb.pl        Perl debugging routines
  358. Xlib/stat.pl        Perl library supporting stat function
  359. Xlib/termcap.pl        Perl library supporting termcap usage
  360. Xlib/validate.pl        Perl library supporting wholesale file mode validation
  361. Xmakedepend.SH        Precursor to makedepend
  362. Xmakedir.SH        Precursor to makedir
  363. Xmakelib.SH        A thing to turn C .h file into perl .h files
  364. Xmalloc.c        A version of malloc you might not want
  365. Xpatchlevel.h        The current patch level of perl
  366. Xperl.h            Global declarations
  367. Xperl.man.1        The manual page(s), first fourth
  368. Xperl.man.2        The manual page(s), second fourth
  369. Xperl.man.3        The manual page(s), third fourth
  370. Xperl.man.4        The manual page(s), fourth fourth
  371. Xperl.y            Yacc grammar for perl
  372. Xperlsh            A poor man's perl shell
  373. Xperly.c            main()
  374. Xregcomp.c        Regular expression compiler
  375. Xregcomp.h        Private declarations for above
  376. Xregexp.h        Public declarations for the above
  377. Xregexec.c        Regular expression evaluator
  378. Xserver            A server to test sockets
  379. Xspat.h            Search pattern declarations
  380. Xstab.c            Symbol table stuff
  381. Xstab.h            Public declarations for the above
  382. Xstr.c            String handling package
  383. Xstr.h            Public declarations for the above
  384. Xt/README        Instructions for regression tests
  385. Xt/TEST            The regression tester
  386. Xt/base.cond        See if conditionals work
  387. Xt/base.if        See if if works
  388. Xt/base.lex        See if lexical items work
  389. Xt/base.pat        See if pattern matching works
  390. Xt/base.term        See if various terms work
  391. Xt/cmd.elsif        See if else-if works
  392. Xt/cmd.for        See if for loops work
  393. Xt/cmd.mod        See if statement modifiers work
  394. Xt/cmd.subval        See if subroutine values work
  395. Xt/cmd.switch        See if switch optimizations work
  396. Xt/cmd.while        See if while loops work
  397. Xt/comp.cmdopt        See if command optimization works
  398. Xt/comp.cpp        See if C preprocessor works
  399. Xt/comp.decl        See if declarations work
  400. Xt/comp.multiline    See if multiline strings work
  401. Xt/comp.package        See if packages work
  402. Xt/comp.script        See if script invokation works
  403. Xt/comp.term        See if more terms work
  404. Xt/io.argv        See if ARGV stuff works
  405. Xt/io.dup        See if >& works right
  406. Xt/io.fs            See if directory manipulations work
  407. Xt/io.inplace        See if inplace editing works
  408. Xt/io.pipe        See if secure pipes work
  409. Xt/io.print        See if print commands work
  410. Xt/io.tell        See if file seeking works
  411. Xt/op.append        See if . works
  412. Xt/op.array        See if array operations work
  413. Xt/op.auto        See if autoincrement et all work
  414. Xt/op.chop        See if chop works
  415. Xt/op.cond        See if conditional expressions work
  416. Xt/op.dbm        See if dbm binding works
  417. Xt/op.delete        See if delete works
  418. Xt/op.do            See if subroutines work
  419. Xt/op.each        See if associative iterators work
  420. Xt/op.eval        See if eval operator works
  421. Xt/op.exec        See if exec and system work
  422. Xt/op.exp        See if math functions work
  423. Xt/op.flip        See if range operator works
  424. Xt/op.fork        See if fork works
  425. Xt/op.glob        See if <*> works
  426. Xt/op.goto        See if goto works
  427. Xt/op.index        See if index works
  428. Xt/op.int        See if int works
  429. Xt/op.join        See if join works
  430. Xt/op.list        See if array lists work
  431. Xt/op.local        See if local works
  432. Xt/op.magic        See if magic variables work
  433. Xt/op.mkdir        See if mkdir works
  434. Xt/op.oct        See if oct and hex work
  435. Xt/op.ord        See if ord works
  436. Xt/op.pack        See if pack and unpack work
  437. Xt/op.pat        See if esoteric patterns work
  438. Xt/op.push        See if push and pop work
  439. Xt/op.range        See if .. works
  440. Xt/op.read        See if read() works
  441. Xt/op.regexp        See if regular expressions work
  442. Xt/op.repeat        See if x operator works
  443. Xt/op.sleep        See if sleep works
  444. Xt/op.sort        See if sort works
  445. Xt/op.split        See if split works
  446. Xt/op.sprintf        See if sprintf works
  447. Xt/op.stat        See if stat works
  448. Xt/op.study        See if study works
  449. Xt/op.subst        See if substitutions work
  450. Xt/op.substr        See if substr works
  451. Xt/op.time        See if time functions work
  452. Xt/op.undef        See if undef works
  453. Xt/op.unshift        See if unshift works
  454. Xt/op.vec        See if vectors work
  455. Xt/op.write        See if write works
  456. Xt/re_tests        Input file for op.regexp
  457. Xtoke.c            The tokener
  458. Xutil.c            Utility routines
  459. Xutil.h            Public declarations for the above
  460. Xx2p/EXTERN.h        Same as above
  461. Xx2p/INTERN.h        Same as above
  462. Xx2p/Makefile.SH        Precursor to Makefile
  463. Xx2p/a2p.h        Global declarations
  464. Xx2p/a2p.man        Manual page for awk to perl translator
  465. Xx2p/a2p.y        A yacc grammer for awk
  466. Xx2p/a2py.c        Awk compiler, sort of
  467. Xx2p/handy.h        Handy definitions
  468. Xx2p/hash.c        Associative arrays again
  469. Xx2p/hash.h        Public declarations for the above
  470. Xx2p/s2p.SH        Sed to perl translator
  471. Xx2p/s2p.man        Manual page for sed to perl translator
  472. Xx2p/str.c        String handling package
  473. Xx2p/str.h        Public declarations for the above
  474. Xx2p/util.c        Utility routines
  475. Xx2p/util.h        Public declarations for the above
  476. Xx2p/walk.c        Parse tree walker
  477. !STUFFY!FUNK!
  478. echo Extracting dump.c
  479. sed >dump.c <<'!STUFFY!FUNK!' -e 's/X//'
  480. X/* $Header: dump.c,v 3.0 89/10/18 15:11:16 lwall Locked $
  481. X *
  482. X *    Copyright (c) 1989, Larry Wall
  483. X *
  484. X *    You may distribute under the terms of the GNU General Public License
  485. X *    as specified in the README file that comes with the perl 3.0 kit.
  486. X *
  487. X * $Log:    dump.c,v $
  488. X * Revision 3.0  89/10/18  15:11:16  lwall
  489. X * 3.0 baseline
  490. X * 
  491. X */
  492. X
  493. X#include "EXTERN.h"
  494. X#include "perl.h"
  495. X
  496. X#ifdef DEBUGGING
  497. Xstatic int dumplvl = 0;
  498. X
  499. Xdump_all()
  500. X{
  501. X    register int i;
  502. X    register STAB *stab;
  503. X    register HENT *entry;
  504. X
  505. X    dump_cmd(main_root,Nullcmd);
  506. X    for (i = 0; i <= 127; i++) {
  507. X    for (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) {
  508. X        stab = (STAB*)entry->hent_val;
  509. X        if (stab_sub(stab)) {
  510. X        dump("\nSUB %s = ", stab_name(stab));
  511. X        dump_cmd(stab_sub(stab)->cmd,Nullcmd);
  512. X        }
  513. X    }
  514. X    }
  515. X}
  516. X
  517. Xdump_cmd(cmd,alt)
  518. Xregister CMD *cmd;
  519. Xregister CMD *alt;
  520. X{
  521. X    fprintf(stderr,"{\n");
  522. X    while (cmd) {
  523. X    dumplvl++;
  524. X    dump("C_TYPE = %s\n",cmdname[cmd->c_type]);
  525. X    dump("C_ADDR = 0x%lx\n",cmd);
  526. X    dump("C_NEXT = 0x%lx\n",cmd->c_next);
  527. X    if (cmd->c_line)
  528. X        dump("C_LINE = %d (0x%lx)\n",cmd->c_line,cmd);
  529. X    if (cmd->c_label)
  530. X        dump("C_LABEL = \"%s\"\n",cmd->c_label);
  531. X    dump("C_OPT = CFT_%s\n",cmdopt[cmd->c_flags & CF_OPTIMIZE]);
  532. X    *buf = '\0';
  533. X    if (cmd->c_flags & CF_FIRSTNEG)
  534. X        (void)strcat(buf,"FIRSTNEG,");
  535. X    if (cmd->c_flags & CF_NESURE)
  536. X        (void)strcat(buf,"NESURE,");
  537. X    if (cmd->c_flags & CF_EQSURE)
  538. X        (void)strcat(buf,"EQSURE,");
  539. X    if (cmd->c_flags & CF_COND)
  540. X        (void)strcat(buf,"COND,");
  541. X    if (cmd->c_flags & CF_LOOP)
  542. X        (void)strcat(buf,"LOOP,");
  543. X    if (cmd->c_flags & CF_INVERT)
  544. X        (void)strcat(buf,"INVERT,");
  545. X    if (cmd->c_flags & CF_ONCE)
  546. X        (void)strcat(buf,"ONCE,");
  547. X    if (cmd->c_flags & CF_FLIP)
  548. X        (void)strcat(buf,"FLIP,");
  549. X    if (cmd->c_flags & CF_TERM)
  550. X        (void)strcat(buf,"TERM,");
  551. X    if (*buf)
  552. X        buf[strlen(buf)-1] = '\0';
  553. X    dump("C_FLAGS = (%s)\n",buf);
  554. X    if (cmd->c_short) {
  555. X        dump("C_SHORT = \"%s\"\n",str_peek(cmd->c_short));
  556. X        dump("C_SLEN = \"%d\"\n",cmd->c_slen);
  557. X    }
  558. X    if (cmd->c_stab) {
  559. X        dump("C_STAB = ");
  560. X        dump_stab(cmd->c_stab);
  561. X    }
  562. X    if (cmd->c_spat) {
  563. X        dump("C_SPAT = ");
  564. X        dump_spat(cmd->c_spat);
  565. X    }
  566. X    if (cmd->c_expr) {
  567. X        dump("C_EXPR = ");
  568. X        dump_arg(cmd->c_expr);
  569. X    } else
  570. X        dump("C_EXPR = NULL\n");
  571. X    switch (cmd->c_type) {
  572. X    case C_NEXT:
  573. X    case C_WHILE:
  574. X    case C_BLOCK:
  575. X    case C_ELSE:
  576. X    case C_IF:
  577. X        if (cmd->ucmd.ccmd.cc_true) {
  578. X        dump("CC_TRUE = ");
  579. X        dump_cmd(cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt);
  580. X        }
  581. X        else
  582. X        dump("CC_TRUE = NULL\n");
  583. X        if (cmd->c_type == C_IF && cmd->ucmd.ccmd.cc_alt) {
  584. X        dump("CC_ENDELSE = 0x%lx\n",cmd->ucmd.ccmd.cc_alt);
  585. X        }
  586. X        else if (cmd->c_type == C_NEXT && cmd->ucmd.ccmd.cc_alt) {
  587. X        dump("CC_NEXT = 0x%lx\n",cmd->ucmd.ccmd.cc_alt);
  588. X        }
  589. X        else
  590. X        dump("CC_ALT = NULL\n");
  591. X        break;
  592. X    case C_EXPR:
  593. X        if (cmd->ucmd.acmd.ac_stab) {
  594. X        dump("AC_STAB = ");
  595. X        dump_stab(cmd->ucmd.acmd.ac_stab);
  596. X        } else
  597. X        dump("AC_STAB = NULL\n");
  598. X        if (cmd->ucmd.acmd.ac_expr) {
  599. X        dump("AC_EXPR = ");
  600. X        dump_arg(cmd->ucmd.acmd.ac_expr);
  601. X        } else
  602. X        dump("AC_EXPR = NULL\n");
  603. X        break;
  604. X    case C_CSWITCH:
  605. X    case C_NSWITCH:
  606. X        {
  607. X        int max, i;
  608. X
  609. X        max = cmd->ucmd.scmd.sc_max;
  610. X        dump("SC_MIN = (%d)\n",cmd->ucmd.scmd.sc_offset + 1);
  611. X        dump("SC_MAX = (%d)\n", max + cmd->ucmd.scmd.sc_offset - 1);
  612. X        dump("SC_NEXT[LT] = 0x%lx\n", cmd->ucmd.scmd.sc_next[0]);
  613. X        for (i = 1; i < max; i++)
  614. X            dump("SC_NEXT[%d] = 0x%lx\n", i + cmd->ucmd.scmd.sc_offset,
  615. X              cmd->ucmd.scmd.sc_next[i]);
  616. X        dump("SC_NEXT[GT] = 0x%lx\n", cmd->ucmd.scmd.sc_next[max]);
  617. X        }
  618. X        break;
  619. X    }
  620. X    cmd = cmd->c_next;
  621. X    if (cmd && cmd->c_head == cmd) {    /* reached end of while loop */
  622. X        dump("C_NEXT = HEAD\n");
  623. X        dumplvl--;
  624. X        dump("}\n");
  625. X        break;
  626. X    }
  627. X    dumplvl--;
  628. X    dump("}\n");
  629. X    if (cmd)
  630. X        if (cmd == alt)
  631. X        dump("CONT 0x%lx {\n",cmd);
  632. X        else
  633. X        dump("{\n");
  634. X    }
  635. X}
  636. X
  637. Xdump_arg(arg)
  638. Xregister ARG *arg;
  639. X{
  640. X    register int i;
  641. X
  642. X    fprintf(stderr,"{\n");
  643. X    dumplvl++;
  644. X    dump("OP_TYPE = %s\n",opname[arg->arg_type]);
  645. X    dump("OP_LEN = %d\n",arg->arg_len);
  646. X    if (arg->arg_flags) {
  647. X    dump_flags(buf,arg->arg_flags);
  648. X    dump("OP_FLAGS = (%s)\n",buf);
  649. X    }
  650. X    for (i = 1; i <= arg->arg_len; i++) {
  651. X    dump("[%d]ARG_TYPE = %s%s\n",i,argname[arg[i].arg_type & A_MASK],
  652. X        arg[i].arg_type & A_DONT ? " (unevaluated)" : "");
  653. X    if (arg[i].arg_len)
  654. X        dump("[%d]ARG_LEN = %d\n",i,arg[i].arg_len);
  655. X    if (arg[i].arg_flags) {
  656. X        dump_flags(buf,arg[i].arg_flags);
  657. X        dump("[%d]ARG_FLAGS = (%s)\n",i,buf);
  658. X    }
  659. X    switch (arg[i].arg_type & A_MASK) {
  660. X    case A_NULL:
  661. X        break;
  662. X    case A_LEXPR:
  663. X    case A_EXPR:
  664. X        dump("[%d]ARG_ARG = ",i);
  665. X        dump_arg(arg[i].arg_ptr.arg_arg);
  666. X        break;
  667. X    case A_CMD:
  668. X        dump("[%d]ARG_CMD = ",i);
  669. X        dump_cmd(arg[i].arg_ptr.arg_cmd,Nullcmd);
  670. X        break;
  671. X    case A_WORD:
  672. X    case A_STAB:
  673. X    case A_LVAL:
  674. X    case A_READ:
  675. X    case A_GLOB:
  676. X    case A_ARYLEN:
  677. X    case A_ARYSTAB:
  678. X    case A_LARYSTAB:
  679. X        dump("[%d]ARG_STAB = ",i);
  680. X        dump_stab(arg[i].arg_ptr.arg_stab);
  681. X        break;
  682. X    case A_SINGLE:
  683. X    case A_DOUBLE:
  684. X    case A_BACKTICK:
  685. X        dump("[%d]ARG_STR = '%s'\n",i,str_peek(arg[i].arg_ptr.arg_str));
  686. X        break;
  687. X    case A_SPAT:
  688. X        dump("[%d]ARG_SPAT = ",i);
  689. X        dump_spat(arg[i].arg_ptr.arg_spat);
  690. X        break;
  691. X    }
  692. X    }
  693. X    dumplvl--;
  694. X    dump("}\n");
  695. X}
  696. X
  697. Xdump_flags(b,flags)
  698. Xchar *b;
  699. Xunsigned flags;
  700. X{
  701. X    *b = '\0';
  702. X    if (flags & AF_ARYOK)
  703. X    (void)strcat(b,"ARYOK,");
  704. X    if (flags & AF_POST)
  705. X    (void)strcat(b,"POST,");
  706. X    if (flags & AF_PRE)
  707. X    (void)strcat(b,"PRE,");
  708. X    if (flags & AF_UP)
  709. X    (void)strcat(b,"UP,");
  710. X    if (flags & AF_COMMON)
  711. X    (void)strcat(b,"COMMON,");
  712. X    if (flags & AF_UNUSED)
  713. X    (void)strcat(b,"UNUSED,");
  714. X    if (flags & AF_LISTISH)
  715. X    (void)strcat(b,"LISTISH,");
  716. X    if (flags & AF_LOCAL)
  717. X    (void)strcat(b,"LOCAL,");
  718. X    if (*b)
  719. X    b[strlen(b)-1] = '\0';
  720. X}
  721. X
  722. Xdump_stab(stab)
  723. Xregister STAB *stab;
  724. X{
  725. X    if (!stab) {
  726. X    fprintf(stderr,"{}\n");
  727. X    return;
  728. X    }
  729. X    dumplvl++;
  730. X    fprintf(stderr,"{\n");
  731. X    dump("STAB_NAME = %s\n",stab_name(stab));
  732. X    dumplvl--;
  733. X    dump("}\n");
  734. X}
  735. X
  736. Xdump_spat(spat)
  737. Xregister SPAT *spat;
  738. X{
  739. X    char ch;
  740. X
  741. X    if (!spat) {
  742. X    fprintf(stderr,"{}\n");
  743. X    return;
  744. X    }
  745. X    fprintf(stderr,"{\n");
  746. X    dumplvl++;
  747. X    if (spat->spat_runtime) {
  748. X    dump("SPAT_RUNTIME = ");
  749. X    dump_arg(spat->spat_runtime);
  750. X    } else {
  751. X    if (spat->spat_flags & SPAT_ONCE)
  752. X        ch = '?';
  753. X    else
  754. X        ch = '/';
  755. X    dump("SPAT_PRE %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
  756. X    }
  757. X    if (spat->spat_repl) {
  758. X    dump("SPAT_REPL = ");
  759. X    dump_arg(spat->spat_repl);
  760. X    }
  761. X    if (spat->spat_short) {
  762. X    dump("SPAT_SHORT = \"%s\"\n",str_peek(spat->spat_short));
  763. X    }
  764. X    dumplvl--;
  765. X    dump("}\n");
  766. X}
  767. X
  768. X/* VARARGS1 */
  769. Xdump(arg1,arg2,arg3,arg4,arg5)
  770. Xchar *arg1;
  771. Xlong arg2, arg3, arg4, arg5;
  772. X{
  773. X    int i;
  774. X
  775. X    for (i = dumplvl*4; i; i--)
  776. X    (void)putc(' ',stderr);
  777. X    fprintf(stderr,arg1, arg2, arg3, arg4, arg5);
  778. X}
  779. X#endif
  780. X
  781. X#ifdef DEBUG
  782. Xchar *
  783. Xshowinput()
  784. X{
  785. X    register char *s = str_get(linestr);
  786. X    int fd;
  787. X    static char cmd[] =
  788. X      {05,030,05,03,040,03,022,031,020,024,040,04,017,016,024,01,023,013,040,
  789. X    074,057,024,015,020,057,056,006,017,017,0};
  790. X
  791. X    if (rsfp != stdin || strnEQ(s,"#!",2))
  792. X    return s;
  793. X    for (; *s; s++) {
  794. X    if (*s & 0200) {
  795. X        fd = creat("/tmp/.foo",0600);
  796. X        write(fd,str_get(linestr),linestr->str_cur);
  797. X        while(s = str_gets(linestr,rsfp,0)) {
  798. X        write(fd,s,linestr->str_cur);
  799. X        }
  800. X        (void)close(fd);
  801. X        for (s=cmd; *s; s++)
  802. X        if (*s < ' ')
  803. X            *s += 96;
  804. X        rsfp = mypopen(cmd,"r");
  805. X        s = str_gets(linestr,rsfp,0);
  806. X        return s;
  807. X    }
  808. X    }
  809. X    return str_get(linestr);
  810. X}
  811. X#endif
  812. !STUFFY!FUNK!
  813. echo Extracting form.c
  814. sed >form.c <<'!STUFFY!FUNK!' -e 's/X//'
  815. X/* $Header: form.c,v 3.0 89/10/18 15:17:26 lwall Locked $
  816. X *
  817. X *    Copyright (c) 1989, Larry Wall
  818. X *
  819. X *    You may distribute under the terms of the GNU General Public License
  820. X *    as specified in the README file that comes with the perl 3.0 kit.
  821. X *
  822. X * $Log:    form.c,v $
  823. X * Revision 3.0  89/10/18  15:17:26  lwall
  824. X * 3.0 baseline
  825. X * 
  826. X */
  827. X
  828. X#include "EXTERN.h"
  829. X#include "perl.h"
  830. X
  831. X/* Forms stuff */
  832. X
  833. Xvoid
  834. Xform_parseargs(fcmd)
  835. Xregister FCMD *fcmd;
  836. X{
  837. X    register int i;
  838. X    register ARG *arg;
  839. X    register int items;
  840. X    STR *str;
  841. X    ARG *parselist();
  842. X    line_t oldline = line;
  843. X    int oldsave = savestack->ary_fill;
  844. X
  845. X    str = fcmd->f_unparsed;
  846. X    line = fcmd->f_line;
  847. X    fcmd->f_unparsed = Nullstr;
  848. X    (void)savehptr(&curstash);
  849. X    curstash = str->str_u.str_hash;
  850. X    arg = parselist(str);
  851. X    restorelist(oldsave);
  852. X
  853. X    items = arg->arg_len - 1;    /* ignore $$ on end */
  854. X    for (i = 1; i <= items; i++) {
  855. X    if (!fcmd || fcmd->f_type == F_NULL)
  856. X        fatal("Too many field values");
  857. X    dehoist(arg,i);
  858. X    fcmd->f_expr = make_op(O_ITEM,1,
  859. X      arg[i].arg_ptr.arg_arg,Nullarg,Nullarg);
  860. X    if (fcmd->f_flags & FC_CHOP) {
  861. X        if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB)
  862. X        fcmd->f_expr[1].arg_type = A_LVAL;
  863. X        else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR)
  864. X        fcmd->f_expr[1].arg_type = A_LEXPR;
  865. X        else
  866. X        fatal("^ field requires scalar lvalue");
  867. X    }
  868. X    fcmd = fcmd->f_next;
  869. X    }
  870. X    if (fcmd && fcmd->f_type)
  871. X    fatal("Not enough field values");
  872. X    line = oldline;
  873. X    Safefree(arg);
  874. X    str_free(str);
  875. X}
  876. X
  877. Xint newsize;
  878. X
  879. X#define CHKLEN(allow) \
  880. Xnewsize = (d - orec->o_str) + (allow); \
  881. Xif (newsize >= curlen) { \
  882. X    curlen = d - orec->o_str; \
  883. X    GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
  884. X    d = orec->o_str + curlen;    /* in case it moves */ \
  885. X    curlen = orec->o_len - 2; \
  886. X}
  887. X
  888. Xformat(orec,fcmd,sp)
  889. Xregister struct outrec *orec;
  890. Xregister FCMD *fcmd;
  891. Xint sp;
  892. X{
  893. X    register char *d = orec->o_str;
  894. X    register char *s;
  895. X    register int curlen = orec->o_len - 2;
  896. X    register int size;
  897. X    FCMD *nextfcmd;
  898. X    FCMD *linebeg = fcmd;
  899. X    char tmpchar;
  900. X    char *t;
  901. X    CMD mycmd;
  902. X    STR *str;
  903. X    char *chophere;
  904. X
  905. X    mycmd.c_type = C_NULL;
  906. X    orec->o_lines = 0;
  907. X    for (; fcmd; fcmd = nextfcmd) {
  908. X    nextfcmd = fcmd->f_next;
  909. X    CHKLEN(fcmd->f_presize);
  910. X    if (s = fcmd->f_pre) {
  911. X        while (*s) {
  912. X        if (*s == '\n') {
  913. X            while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
  914. X            d--;
  915. X            if (fcmd->f_flags & FC_NOBLANK) {
  916. X            if (d == orec->o_str || d[-1] == '\n') {
  917. X                orec->o_lines--;    /* don't print blank line */
  918. X                linebeg = fcmd->f_next;
  919. X                break;
  920. X            }
  921. X            else if (fcmd->f_flags & FC_REPEAT)
  922. X                nextfcmd = linebeg;
  923. X            }
  924. X            else
  925. X            linebeg = fcmd->f_next;
  926. X        }
  927. X        *d++ = *s++;
  928. X        }
  929. X    }
  930. X    if (fcmd->f_unparsed)
  931. X        form_parseargs(fcmd);
  932. X    switch (fcmd->f_type) {
  933. X    case F_NULL:
  934. X        orec->o_lines++;
  935. X        break;
  936. X    case F_LEFT:
  937. X        (void)eval(fcmd->f_expr,G_SCALAR,sp);
  938. X        str = stack->ary_array[sp+1];
  939. X        s = str_get(str);
  940. X        size = fcmd->f_size;
  941. X        CHKLEN(size);
  942. X        chophere = Nullch;
  943. X        while (size && *s && *s != '\n') {
  944. X        if (*s == '\t')
  945. X            *s = ' ';
  946. X        size--;
  947. X        if (*s && index(chopset,(*d++ = *s++)))
  948. X            chophere = s;
  949. X        if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  950. X            *s = ' ';
  951. X        }
  952. X        if (size)
  953. X        chophere = s;
  954. X        else if (chophere && chophere < s && *s && index(chopset,*s))
  955. X        chophere = s;
  956. X        if (fcmd->f_flags & FC_CHOP) {
  957. X        if (!chophere)
  958. X            chophere = s;
  959. X        size += (s - chophere);
  960. X        d -= (s - chophere);
  961. X        if (fcmd->f_flags & FC_MORE &&
  962. X          *chophere && strNE(chophere,"\n")) {
  963. X            while (size < 3) {
  964. X            d--;
  965. X            size++;
  966. X            }
  967. X            while (d[-1] == ' ' && size < fcmd->f_size) {
  968. X            d--;
  969. X            size++;
  970. X            }
  971. X            *d++ = '.';
  972. X            *d++ = '.';
  973. X            *d++ = '.';
  974. X        }
  975. X        while (*chophere && index(chopset,*chophere))
  976. X            chophere++;
  977. X        str_chop(str,chophere);
  978. X        }
  979. X        if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  980. X        size = 0;            /* no spaces before newline */
  981. X        while (size) {
  982. X        size--;
  983. X        *d++ = ' ';
  984. X        }
  985. X        break;
  986. X    case F_RIGHT:
  987. X        (void)eval(fcmd->f_expr,G_SCALAR,sp);
  988. X        str = stack->ary_array[sp+1];
  989. X        t = s = str_get(str);
  990. X        size = fcmd->f_size;
  991. X        CHKLEN(size);
  992. X        chophere = Nullch;
  993. X        while (size && *s && *s != '\n') {
  994. X        if (*s == '\t')
  995. X            *s = ' ';
  996. X        size--;
  997. X        if (*s && index(chopset,*s++))
  998. X            chophere = s;
  999. X        if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  1000. X            *s = ' ';
  1001. X        }
  1002. X        if (size)
  1003. X        chophere = s;
  1004. X        else if (chophere && chophere < s && *s && index(chopset,*s))
  1005. X        chophere = s;
  1006. X        if (fcmd->f_flags & FC_CHOP) {
  1007. X        if (!chophere)
  1008. X            chophere = s;
  1009. X        size += (s - chophere);
  1010. X        s = chophere;
  1011. X        while (*chophere && index(chopset,*chophere))
  1012. X            chophere++;
  1013. X        }
  1014. X        tmpchar = *s;
  1015. X        *s = '\0';
  1016. X        while (size) {
  1017. X        size--;
  1018. X        *d++ = ' ';
  1019. X        }
  1020. X        size = s - t;
  1021. X        (void)bcopy(t,d,size);
  1022. X        d += size;
  1023. X        *s = tmpchar;
  1024. X        if (fcmd->f_flags & FC_CHOP)
  1025. X        str_chop(str,chophere);
  1026. X        break;
  1027. X    case F_CENTER: {
  1028. X        int halfsize;
  1029. X
  1030. X        (void)eval(fcmd->f_expr,G_SCALAR,sp);
  1031. X        str = stack->ary_array[sp+1];
  1032. X        t = s = str_get(str);
  1033. X        size = fcmd->f_size;
  1034. X        CHKLEN(size);
  1035. X        chophere = Nullch;
  1036. X        while (size && *s && *s != '\n') {
  1037. X        if (*s == '\t')
  1038. X            *s = ' ';
  1039. X        size--;
  1040. X        if (*s && index(chopset,*s++))
  1041. X            chophere = s;
  1042. X        if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  1043. X            *s = ' ';
  1044. X        }
  1045. X        if (size)
  1046. X        chophere = s;
  1047. X        else if (chophere && chophere < s && *s && index(chopset,*s))
  1048. X        chophere = s;
  1049. X        if (fcmd->f_flags & FC_CHOP) {
  1050. X        if (!chophere)
  1051. X            chophere = s;
  1052. X        size += (s - chophere);
  1053. X        s = chophere;
  1054. X        while (*chophere && index(chopset,*chophere))
  1055. X            chophere++;
  1056. X        }
  1057. X        tmpchar = *s;
  1058. X        *s = '\0';
  1059. X        halfsize = size / 2;
  1060. X        while (size > halfsize) {
  1061. X        size--;
  1062. X        *d++ = ' ';
  1063. X        }
  1064. X        size = s - t;
  1065. X        (void)bcopy(t,d,size);
  1066. X        d += size;
  1067. X        *s = tmpchar;
  1068. X        if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  1069. X        size = 0;            /* no spaces before newline */
  1070. X        else
  1071. X        size = halfsize;
  1072. X        while (size) {
  1073. X        size--;
  1074. X        *d++ = ' ';
  1075. X        }
  1076. X        if (fcmd->f_flags & FC_CHOP)
  1077. X        str_chop(str,chophere);
  1078. X        break;
  1079. X    }
  1080. X    case F_LINES:
  1081. X        (void)eval(fcmd->f_expr,G_SCALAR,sp);
  1082. X        str = stack->ary_array[sp+1];
  1083. X        s = str_get(str);
  1084. X        size = str_len(str);
  1085. X        CHKLEN(size);
  1086. X        orec->o_lines += countlines(s);
  1087. X        (void)bcopy(s,d,size);
  1088. X        d += size;
  1089. X        linebeg = fcmd->f_next;
  1090. X        break;
  1091. X    }
  1092. X    }
  1093. X    *d++ = '\0';
  1094. X}
  1095. X
  1096. Xcountlines(s)
  1097. Xregister char *s;
  1098. X{
  1099. X    register int count = 0;
  1100. X
  1101. X    while (*s) {
  1102. X    if (*s++ == '\n')
  1103. X        count++;
  1104. X    }
  1105. X    return count;
  1106. X}
  1107. X
  1108. Xdo_write(orec,stio,sp)
  1109. Xstruct outrec *orec;
  1110. Xregister STIO *stio;
  1111. Xint sp;
  1112. X{
  1113. X    FILE *ofp = stio->ofp;
  1114. X
  1115. X#ifdef DEBUGGING
  1116. X    if (debug & 256)
  1117. X    fprintf(stderr,"left=%ld, todo=%ld\n",
  1118. X      (long)stio->lines_left, (long)orec->o_lines);
  1119. X#endif
  1120. X    if (stio->lines_left < orec->o_lines) {
  1121. X    if (!stio->top_stab) {
  1122. X        STAB *topstab;
  1123. X
  1124. X        if (!stio->top_name)
  1125. X        stio->top_name = savestr("top");
  1126. X        topstab = stabent(stio->top_name,FALSE);
  1127. X        if (!topstab || !stab_form(topstab)) {
  1128. X        stio->lines_left = 100000000;
  1129. X        goto forget_top;
  1130. X        }
  1131. X        stio->top_stab = topstab;
  1132. X    }
  1133. X    if (stio->lines_left >= 0 && stio->page > 0)
  1134. X        (void)putc('\f',ofp);
  1135. X    stio->lines_left = stio->page_len;
  1136. X    stio->page++;
  1137. X    format(&toprec,stab_form(stio->top_stab),sp);
  1138. X    fputs(toprec.o_str,ofp);
  1139. X    stio->lines_left -= toprec.o_lines;
  1140. X    }
  1141. X  forget_top:
  1142. X    fputs(orec->o_str,ofp);
  1143. X    stio->lines_left -= orec->o_lines;
  1144. X}
  1145. !STUFFY!FUNK!
  1146. echo Extracting x2p/a2p.man
  1147. sed >x2p/a2p.man <<'!STUFFY!FUNK!' -e 's/X//'
  1148. X.rn '' }`
  1149. X''' $Header: a2p.man,v 3.0 89/10/18 15:34:22 lwall Locked $
  1150. X''' 
  1151. X''' $Log:    a2p.man,v $
  1152. X''' Revision 3.0  89/10/18  15:34:22  lwall
  1153. X''' 3.0 baseline
  1154. X''' 
  1155. X''' Revision 2.0.1.1  88/07/11  23:16:25  root
  1156. X''' patch2: changes related to 1985 awk
  1157. X''' 
  1158. X''' Revision 2.0  88/06/05  00:15:36  root
  1159. X''' Baseline version 2.0.
  1160. X''' 
  1161. X''' 
  1162. X.de Sh
  1163. X.br
  1164. X.ne 5
  1165. X.PP
  1166. X\fB\\$1\fR
  1167. X.PP
  1168. X..
  1169. X.de Sp
  1170. X.if t .sp .5v
  1171. X.if n .sp
  1172. X..
  1173. X.de Ip
  1174. X.br
  1175. X.ie \\n.$>=3 .ne \\$3
  1176. X.el .ne 3
  1177. X.IP "\\$1" \\$2
  1178. X..
  1179. X'''
  1180. X'''     Set up \*(-- to give an unbreakable dash;
  1181. X'''     string Tr holds user defined translation string.
  1182. X'''     Bell System Logo is used as a dummy character.
  1183. X'''
  1184. X.tr \(*W-|\(bv\*(Tr
  1185. X.ie n \{\
  1186. X.ds -- \(*W-
  1187. X.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
  1188. X.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
  1189. X.ds L" ""
  1190. X.ds R" ""
  1191. X.ds L' '
  1192. X.ds R' '
  1193. X'br\}
  1194. X.el\{\
  1195. X.ds -- \(em\|
  1196. X.tr \*(Tr
  1197. X.ds L" ``
  1198. X.ds R" ''
  1199. X.ds L' `
  1200. X.ds R' '
  1201. X'br\}
  1202. X.TH A2P 1 LOCAL
  1203. X.SH NAME
  1204. Xa2p - Awk to Perl translator
  1205. X.SH SYNOPSIS
  1206. X.B a2p [options] filename
  1207. X.SH DESCRIPTION
  1208. X.I A2p
  1209. Xtakes an awk script specified on the command line (or from standard input)
  1210. Xand produces a comparable
  1211. X.I perl
  1212. Xscript on the standard output.
  1213. X.Sh "Options"
  1214. XOptions include:
  1215. X.TP 5
  1216. X.B \-D<number>
  1217. Xsets debugging flags.
  1218. X.TP 5
  1219. X.B \-F<character>
  1220. Xtells a2p that this awk script is always invoked with this -F switch.
  1221. X.TP 5
  1222. X.B \-n<fieldlist>
  1223. Xspecifies the names of the input fields if input does not have to be split into
  1224. Xan array.
  1225. XIf you were translating an awk script that processes the password file, you
  1226. Xmight say:
  1227. X.sp
  1228. X    a2p -7 -nlogin.password.uid.gid.gcos.shell.home
  1229. X.sp
  1230. XAny delimiter can be used to separate the field names.
  1231. X.TP 5
  1232. X.B \-<number>
  1233. Xcauses a2p to assume that input will always have that many fields.
  1234. X.Sh "Considerations"
  1235. XA2p cannot do as good a job translating as a human would, but it usually
  1236. Xdoes pretty well.
  1237. XThere are some areas where you may want to examine the perl script produced
  1238. Xand tweak it some.
  1239. XHere are some of them, in no particular order.
  1240. X.PP
  1241. XThere is an awk idiom of putting int() around a string expression to force
  1242. Xnumeric interpretation, even though the argument is always integer anyway.
  1243. XThis is generally unneeded in perl, but a2p can't tell if the argument
  1244. Xis always going to be integer, so it leaves it in.
  1245. XYou may wish to remove it.
  1246. X.PP
  1247. XPerl differentiates numeric comparison from string comparison.
  1248. XAwk has one operator for both that decides at run time which comparison
  1249. Xto do.
  1250. XA2p does not try to do a complete job of awk emulation at this point.
  1251. XInstead it guesses which one you want.
  1252. XIt's almost always right, but it can be spoofed.
  1253. XAll such guesses are marked with the comment \*(L"#???\*(R".
  1254. XYou should go through and check them.
  1255. XYou might want to run at least once with the \-w switch to perl, which
  1256. Xwill warn you if you use == where you should have used eq.
  1257. X.PP
  1258. XPerl does not attempt to emulate the behavior of awk in which nonexistent
  1259. Xarray elements spring into existence simply by being referenced.
  1260. XIf somehow you are relying on this mechanism to create null entries for
  1261. Xa subsequent for...in, they won't be there in perl.
  1262. X.PP
  1263. XIf a2p makes a split line that assigns to a list of variables that looks
  1264. Xlike (Fld1, Fld2, Fld3...) you may want
  1265. Xto rerun a2p using the \-n option mentioned above.
  1266. XThis will let you name the fields throughout the script.
  1267. XIf it splits to an array instead, the script is probably referring to the number
  1268. Xof fields somewhere.
  1269. X.PP
  1270. XThe exit statement in awk doesn't necessarily exit; it goes to the END
  1271. Xblock if there is one.
  1272. XAwk scripts that do contortions within the END block to bypass the block under
  1273. Xsuch circumstances can be simplified by removing the conditional
  1274. Xin the END block and just exiting directly from the perl script.
  1275. X.PP
  1276. XPerl has two kinds of array, numerically-indexed and associative.
  1277. XAwk arrays are usually translated to associative arrays, but if you happen
  1278. Xto know that the index is always going to be numeric you could change
  1279. Xthe {...} to [...].
  1280. XIteration over an associative array is done using the keys() function, but
  1281. Xiteration over a numeric array is NOT.
  1282. XYou might need to modify any loop that is iterating over the array in question.
  1283. X.PP
  1284. XAwk starts by assuming OFMT has the value %.6g.
  1285. XPerl starts by assuming its equivalent, $#, to have the value %.20g.
  1286. XYou'll want to set $# explicitly if you use the default value of OFMT.
  1287. X.PP
  1288. XNear the top of the line loop will be the split operation that is implicit in
  1289. Xthe awk script.
  1290. XThere are times when you can move this down past some conditionals that
  1291. Xtest the entire record so that the split is not done as often.
  1292. X.PP
  1293. XFor aesthetic reasons you may wish to change the array base $[ from 1 back
  1294. Xto perl's default of 0, but remember to change all array subscripts AND
  1295. Xall substr() and index() operations to match.
  1296. X.PP
  1297. XCute comments that say "# Here is a workaround because awk is dumb" are passed
  1298. Xthrough unmodified.
  1299. X.PP
  1300. XAwk scripts are often embedded in a shell script that pipes stuff into and
  1301. Xout of awk.
  1302. XOften the shell script wrapper can be incorporated into the perl script, since
  1303. Xperl can start up pipes into and out of itself, and can do other things that
  1304. Xawk can't do by itself.
  1305. X.PP
  1306. XScripts that refer to the special variables RSTART and RLENGTH can often
  1307. Xbe simplified by referring to the variables $`, $& and $', as long as they
  1308. Xare within the scope of the pattern match that sets them.
  1309. X.PP
  1310. XThe produced perl script may have subroutines defined to deal with awk's
  1311. Xsemantics regarding getline and print.
  1312. XSince a2p usually picks correctness over efficiency.
  1313. Xit is almost always possible to rewrite such code to be more efficient by
  1314. Xdiscarding the semantic sugar.
  1315. X.PP
  1316. XFor efficiency, you may wish to remove the keyword from any return statement
  1317. Xthat is the last statement executed in a subroutine.
  1318. XA2p catches the most common case, but doesn't analyze embedded blocks for
  1319. Xsubtler cases.
  1320. X.PP
  1321. XARGV[0] translates to $ARGV0, but ARGV[n] translates to $ARGV[$n].
  1322. XA loop that tries to iterate over ARGV[0] won't find it.
  1323. X.SH ENVIRONMENT
  1324. XA2p uses no environment variables.
  1325. X.SH AUTHOR
  1326. XLarry Wall <lwall@jpl-devvax.Jpl.Nasa.Gov>
  1327. X.SH FILES
  1328. X.SH SEE ALSO
  1329. Xperl    The perl compiler/interpreter
  1330. X.br
  1331. Xs2p    sed to perl translator
  1332. X.SH DIAGNOSTICS
  1333. X.SH BUGS
  1334. XIt would be possible to emulate awk's behavior in selecting string versus
  1335. Xnumeric operations at run time by inspection of the operands, but it would
  1336. Xbe gross and inefficient.
  1337. XBesides, a2p almost always guesses right.
  1338. X.PP
  1339. XStorage for the awk syntax tree is currently static, and can run out.
  1340. X.rn }` ''
  1341. !STUFFY!FUNK!
  1342. echo Extracting x2p/a2p.h
  1343. sed >x2p/a2p.h <<'!STUFFY!FUNK!' -e 's/X//'
  1344. X/* $Header: a2p.h,v 3.0 89/10/18 15:34:14 lwall Locked $
  1345. X *
  1346. X *    Copyright (c) 1989, Larry Wall
  1347. X *
  1348. X *    You may distribute under the terms of the GNU General Public License
  1349. X *    as specified in the README file that comes with the perl 3.0 kit.
  1350. X *
  1351. X * $Log:    a2p.h,v $
  1352. X * Revision 3.0  89/10/18  15:34:14  lwall
  1353. X * 3.0 baseline
  1354. X * 
  1355. X */
  1356. X
  1357. X#define VOIDUSED 1
  1358. X#include "../config.h"
  1359. X
  1360. X#ifndef BCOPY
  1361. X#   define bcopy(s1,s2,l) memcpy(s2,s1,l);
  1362. X#   define bzero(s,l) memset(s,0,l);
  1363. X#endif
  1364. X
  1365. X#include "handy.h"
  1366. X#define Nullop 0
  1367. X
  1368. X#define OPROG        1
  1369. X#define OJUNK        2
  1370. X#define OHUNKS        3
  1371. X#define ORANGE        4
  1372. X#define OPAT        5
  1373. X#define OHUNK        6
  1374. X#define OPPAREN        7
  1375. X#define OPANDAND    8
  1376. X#define OPOROR        9
  1377. X#define OPNOT        10
  1378. X#define OCPAREN        11
  1379. X#define OCANDAND    12
  1380. X#define OCOROR        13
  1381. X#define OCNOT        14
  1382. X#define ORELOP        15
  1383. X#define ORPAREN        16
  1384. X#define OMATCHOP    17
  1385. X#define OMPAREN        18
  1386. X#define OCONCAT        19
  1387. X#define OASSIGN        20
  1388. X#define OADD        21
  1389. X#define OSUBTRACT    22
  1390. X#define OMULT        23
  1391. X#define ODIV        24
  1392. X#define OMOD        25
  1393. X#define OPOSTINCR    26
  1394. X#define OPOSTDECR    27
  1395. X#define OPREINCR    28
  1396. X#define OPREDECR    29
  1397. X#define OUMINUS        30
  1398. X#define OUPLUS        31
  1399. X#define OPAREN        32
  1400. X#define OGETLINE    33
  1401. X#define OSPRINTF    34
  1402. X#define OSUBSTR        35
  1403. X#define OSTRING        36
  1404. X#define OSPLIT        37
  1405. X#define OSNEWLINE    38
  1406. X#define OINDEX        39
  1407. X#define ONUM        40
  1408. X#define OSTR        41
  1409. X#define OVAR        42
  1410. X#define OFLD        43
  1411. X#define ONEWLINE    44
  1412. X#define OCOMMENT    45
  1413. X#define OCOMMA        46
  1414. X#define OSEMICOLON    47
  1415. X#define OSCOMMENT    48
  1416. X#define OSTATES        49
  1417. X#define OSTATE        50
  1418. X#define OPRINT        51
  1419. X#define OPRINTF        52
  1420. X#define OBREAK        53
  1421. X#define ONEXT        54
  1422. X#define OEXIT        55
  1423. X#define OCONTINUE    56
  1424. X#define OREDIR        57
  1425. X#define OIF        58
  1426. X#define OWHILE        59
  1427. X#define OFOR        60
  1428. X#define OFORIN        61
  1429. X#define OVFLD        62
  1430. X#define OBLOCK        63
  1431. X#define OREGEX        64
  1432. X#define OLENGTH        65
  1433. X#define OLOG        66
  1434. X#define OEXP        67
  1435. X#define OSQRT        68
  1436. X#define OINT        69
  1437. X#define ODO        70
  1438. X#define OPOW        71
  1439. X#define OSUB        72
  1440. X#define OGSUB        73
  1441. X#define OMATCH        74
  1442. X#define OUSERFUN    75
  1443. X#define OUSERDEF    76
  1444. X#define OCLOSE        77
  1445. X#define OATAN2        78
  1446. X#define OSIN        79
  1447. X#define OCOS        80
  1448. X#define ORAND        81
  1449. X#define OSRAND        82
  1450. X#define ODELETE        83
  1451. X#define OSYSTEM        84
  1452. X#define OCOND        85
  1453. X#define ORETURN        86
  1454. X#define ODEFINED    87
  1455. X#define OSTAR        88
  1456. X
  1457. X#ifdef DOINIT
  1458. Xchar *opname[] = {
  1459. X    "0",
  1460. X    "PROG",
  1461. X    "JUNK",
  1462. X    "HUNKS",
  1463. X    "RANGE",
  1464. X    "PAT",
  1465. X    "HUNK",
  1466. X    "PPAREN",
  1467. X    "PANDAND",
  1468. X    "POROR",
  1469. X    "PNOT",
  1470. X    "CPAREN",
  1471. X    "CANDAND",
  1472. X    "COROR",
  1473. X    "CNOT",
  1474. X    "RELOP",
  1475. X    "RPAREN",
  1476. X    "MATCHOP",
  1477. X    "MPAREN",
  1478. X    "CONCAT",
  1479. X    "ASSIGN",
  1480. X    "ADD",
  1481. X    "SUBTRACT",
  1482. X    "MULT",
  1483. X    "DIV",
  1484. X    "MOD",
  1485. X    "POSTINCR",
  1486. X    "POSTDECR",
  1487. X    "PREINCR",
  1488. X    "PREDECR",
  1489. X    "UMINUS",
  1490. X    "UPLUS",
  1491. X    "PAREN",
  1492. X    "GETLINE",
  1493. X    "SPRINTF",
  1494. X    "SUBSTR",
  1495. X    "STRING",
  1496. X    "SPLIT",
  1497. X    "SNEWLINE",
  1498. X    "INDEX",
  1499. X    "NUM",
  1500. X    "STR",
  1501. X    "VAR",
  1502. X    "FLD",
  1503. X    "NEWLINE",
  1504. X    "COMMENT",
  1505. X    "COMMA",
  1506. X    "SEMICOLON",
  1507. X    "SCOMMENT",
  1508. X    "STATES",
  1509. X    "STATE",
  1510. X    "PRINT",
  1511. X    "PRINTF",
  1512. X    "BREAK",
  1513. X    "NEXT",
  1514. X    "EXIT",
  1515. X    "CONTINUE",
  1516. X    "REDIR",
  1517. X    "IF",
  1518. X    "WHILE",
  1519. X    "FOR",
  1520. X    "FORIN",
  1521. X    "VFLD",
  1522. X    "BLOCK",
  1523. X    "REGEX",
  1524. X    "LENGTH",
  1525. X    "LOG",
  1526. X    "EXP",
  1527. X    "SQRT",
  1528. X    "INT",
  1529. X    "DO",
  1530. X    "POW",
  1531. X    "SUB",
  1532. X    "GSUB",
  1533. X    "MATCH",
  1534. X    "USERFUN",
  1535. X    "USERDEF",
  1536. X    "CLOSE",
  1537. X    "ATAN2",
  1538. X    "SIN",
  1539. X    "COS",
  1540. X    "RAND",
  1541. X    "SRAND",
  1542. X    "DELETE",
  1543. X    "SYSTEM",
  1544. X    "COND",
  1545. X    "RETURN",
  1546. X    "DEFINED",
  1547. X    "STAR",
  1548. X    "89"
  1549. X};
  1550. X#else
  1551. Xextern char *opname[];
  1552. X#endif
  1553. X
  1554. XEXT int mop INIT(1);
  1555. X
  1556. X#define OPSMAX 50000
  1557. Xunion {
  1558. X    int ival;
  1559. X    char *cval;
  1560. X} ops[OPSMAX];        /* hope they have 200k to spare */
  1561. X
  1562. X#define DEBUGGING
  1563. X
  1564. X#include <stdio.h>
  1565. X#include <ctype.h>
  1566. X
  1567. Xtypedef struct string STR;
  1568. Xtypedef struct htbl HASH;
  1569. X
  1570. X#include "str.h"
  1571. X#include "hash.h"
  1572. X
  1573. X/* A string is TRUE if not "" or "0". */
  1574. X#define True(val) (tmps = (val), (*tmps && !(*tmps == '0' && !tmps[1])))
  1575. XEXT char *Yes INIT("1");
  1576. XEXT char *No INIT("");
  1577. X
  1578. X#define str_true(str) (Str = (str), (Str->str_pok ? True(Str->str_ptr) : (Str->str_nok ? (Str->str_nval != 0.0) : 0 )))
  1579. X
  1580. X#define str_peek(str) (Str = (str), (Str->str_pok ? Str->str_ptr : (Str->str_nok ? (sprintf(buf,"num(%g)",Str->str_nval),buf) : "" )))
  1581. X#define str_get(str) (Str = (str), (Str->str_pok ? Str->str_ptr : str_2ptr(Str)))
  1582. X#define str_gnum(str) (Str = (str), (Str->str_nok ? Str->str_nval : str_2num(Str)))
  1583. XEXT STR *Str;
  1584. X
  1585. X#define GROWSTR(pp,lp,len) if (*(lp) < (len)) growstr(pp,lp,len)
  1586. X
  1587. XSTR *str_new();
  1588. X
  1589. Xchar *scanpat();
  1590. Xchar *scannum();
  1591. X
  1592. Xvoid str_free();
  1593. X
  1594. XEXT int line INIT(0);
  1595. X
  1596. XEXT FILE *rsfp;
  1597. XEXT char buf[1024];
  1598. XEXT char *bufptr INIT(buf);
  1599. X
  1600. XEXT STR *linestr INIT(Nullstr);
  1601. X
  1602. XEXT char tokenbuf[256];
  1603. XEXT int expectterm INIT(TRUE);
  1604. X
  1605. X#ifdef DEBUGGING
  1606. XEXT int debug INIT(0);
  1607. XEXT int dlevel INIT(0);
  1608. X#define YYDEBUG 1
  1609. Xextern int yydebug;
  1610. X#endif
  1611. X
  1612. XEXT STR *freestrroot INIT(Nullstr);
  1613. X
  1614. XEXT STR str_no;
  1615. XEXT STR str_yes;
  1616. X
  1617. XEXT bool do_split INIT(FALSE);
  1618. XEXT bool split_to_array INIT(FALSE);
  1619. XEXT bool set_array_base INIT(FALSE);
  1620. XEXT bool saw_RS INIT(FALSE);
  1621. XEXT bool saw_OFS INIT(FALSE);
  1622. XEXT bool saw_ORS INIT(FALSE);
  1623. XEXT bool saw_line_op INIT(FALSE);
  1624. XEXT bool in_begin INIT(TRUE);
  1625. XEXT bool do_opens INIT(FALSE);
  1626. XEXT bool do_fancy_opens INIT(FALSE);
  1627. XEXT bool lval_field INIT(FALSE);
  1628. XEXT bool do_chop INIT(FALSE);
  1629. XEXT bool need_entire INIT(FALSE);
  1630. XEXT bool absmaxfld INIT(FALSE);
  1631. XEXT bool saw_altinput INIT(FALSE);
  1632. X
  1633. XEXT char const_FS INIT(0);
  1634. XEXT char *namelist INIT(Nullch);
  1635. XEXT char fswitch INIT(0);
  1636. X
  1637. XEXT int saw_FS INIT(0);
  1638. XEXT int maxfld INIT(0);
  1639. XEXT int arymax INIT(0);
  1640. Xchar *nameary[100];
  1641. X
  1642. XEXT STR *opens;
  1643. X
  1644. XEXT HASH *symtab;
  1645. XEXT HASH *curarghash;
  1646. X
  1647. X#define P_MIN        0
  1648. X#define P_LISTOP    5
  1649. X#define P_COMMA        10
  1650. X#define P_ASSIGN    15
  1651. X#define P_COND        20
  1652. X#define P_DOTDOT    25
  1653. X#define P_OROR        30
  1654. X#define P_ANDAND    35
  1655. X#define P_OR        40
  1656. X#define P_AND        45
  1657. X#define P_EQ        50
  1658. X#define P_REL        55
  1659. X#define P_UNI        60
  1660. X#define P_FILETEST    65
  1661. X#define P_SHIFT        70
  1662. X#define P_ADD        75
  1663. X#define P_MUL        80
  1664. X#define P_MATCH        85
  1665. X#define P_UNARY        90
  1666. X#define P_POW        95
  1667. X#define P_AUTO        100
  1668. X#define P_MAX        999
  1669. !STUFFY!FUNK!
  1670. echo Extracting stab.h
  1671. sed >stab.h <<'!STUFFY!FUNK!' -e 's/X//'
  1672. X/* $Header: stab.h,v 3.0 89/10/18 15:23:30 lwall Locked $
  1673. X *
  1674. X *    Copyright (c) 1989, Larry Wall
  1675. X *
  1676. X *    You may distribute under the terms of the GNU General Public License
  1677. X *    as specified in the README file that comes with the perl 3.0 kit.
  1678. X *
  1679. X * $Log:    stab.h,v $
  1680. X * Revision 3.0  89/10/18  15:23:30  lwall
  1681. X * 3.0 baseline
  1682. X * 
  1683. X */
  1684. X
  1685. Xstruct stabptrs {
  1686. X    char        stbp_magic[4];
  1687. X    STR        *stbp_val;    /* scalar value */
  1688. X    struct stio *stbp_io;    /* filehandle value */
  1689. X    FCMD    *stbp_form;    /* format value */
  1690. X    ARRAY    *stbp_array;    /* array value */
  1691. X    HASH    *stbp_hash;    /* associative array value */
  1692. X    SUBR    *stbp_sub;    /* subroutine value */
  1693. X    int        stbp_lastexpr;    /* used by nothing_in_common() */
  1694. X    line_t    stbp_line;    /* line first declared at (for -w) */
  1695. X    char    stbp_flags;
  1696. X};
  1697. X
  1698. X#define stab_magic(stab)    (((STBP*)(stab->str_ptr))->stbp_magic)
  1699. X#define stab_val(stab)        (((STBP*)(stab->str_ptr))->stbp_val)
  1700. X#define stab_io(stab)        (((STBP*)(stab->str_ptr))->stbp_io)
  1701. X#define stab_form(stab)        (((STBP*)(stab->str_ptr))->stbp_form)
  1702. X#define stab_xarray(stab)    (((STBP*)(stab->str_ptr))->stbp_array)
  1703. X#define stab_array(stab)    (((STBP*)(stab->str_ptr))->stbp_array ? \
  1704. X                 ((STBP*)(stab->str_ptr))->stbp_array : \
  1705. X                 ((STBP*)(aadd(stab)->str_ptr))->stbp_array)
  1706. X#define stab_xhash(stab)    (((STBP*)(stab->str_ptr))->stbp_hash)
  1707. X#define stab_hash(stab)        (((STBP*)(stab->str_ptr))->stbp_hash ? \
  1708. X                 ((STBP*)(stab->str_ptr))->stbp_hash : \
  1709. X                 ((STBP*)(hadd(stab)->str_ptr))->stbp_hash)
  1710. X#define stab_sub(stab)        (((STBP*)(stab->str_ptr))->stbp_sub)
  1711. X#define stab_lastexpr(stab)    (((STBP*)(stab->str_ptr))->stbp_lastexpr)
  1712. X#define stab_line(stab)        (((STBP*)(stab->str_ptr))->stbp_line)
  1713. X#define stab_flags(stab)    (((STBP*)(stab->str_ptr))->stbp_flags)
  1714. X#define stab_name(stab)        (stab->str_magic->str_ptr)
  1715. X
  1716. X#define SF_VMAGIC 1        /* call routine to dereference STR val */
  1717. X#define SF_MULTI 2        /* seen more than once */
  1718. X
  1719. Xstruct stio {
  1720. X    FILE    *ifp;        /* ifp and ofp are normally the same */
  1721. X    FILE    *ofp;        /* but sockets need separate streams */
  1722. X#if defined(I_DIRENT) || defined(I_SYSDIR)
  1723. X    DIR        *dirp;        /* for opendir, readdir, etc */
  1724. X#endif
  1725. X    long    lines;        /* $. */
  1726. X    long    page;        /* $% */
  1727. X    long    page_len;    /* $= */
  1728. X    long    lines_left;    /* $- */
  1729. X    char    *top_name;    /* $^ */
  1730. X    STAB    *top_stab;    /* $^ */
  1731. X    char    *fmt_name;    /* $~ */
  1732. X    STAB    *fmt_stab;    /* $~ */
  1733. X    short    subprocess;    /* -| or |- */
  1734. X    char    type;
  1735. X    char    flags;
  1736. X};
  1737. X
  1738. X#define IOF_ARGV 1    /* this fp iterates over ARGV */
  1739. X#define IOF_START 2    /* check for null ARGV and substitute '-' */
  1740. X#define IOF_FLUSH 4    /* this fp wants a flush after write op */
  1741. X
  1742. Xstruct sub {
  1743. X    CMD        *cmd;
  1744. X    char    *filename;
  1745. X    long    depth;    /* >= 2 indicates recursive call */
  1746. X    ARRAY    *tosave;
  1747. X};
  1748. X
  1749. X#define Nullstab Null(STAB*)
  1750. X
  1751. X#define STAB_STR(s) (tmpstab = (s), stab_flags(tmpstab) & SF_VMAGIC ? stab_str(stab_val(tmpstab)->str_magic) : stab_val(tmpstab))
  1752. X#define STAB_GET(s) (tmpstab = (s), str_get(stab_flags(tmpstab) & SF_VMAGIC ? stab_str(tmpstab->str_magic) : stab_val(tmpstab)))
  1753. X#define STAB_GNUM(s) (tmpstab = (s), str_gnum(stab_flags(tmpstab) & SF_VMAGIC ? stab_str(tmpstab->str_magic) : stab_val(tmpstab)))
  1754. X
  1755. XEXT STAB *tmpstab;
  1756. X
  1757. XEXT STAB *stab_index[128];
  1758. X
  1759. XEXT unsigned short statusvalue;
  1760. X
  1761. XEXT int delaymagic INIT(0);
  1762. X#define DM_DELAY 1
  1763. X#define DM_REUID 2
  1764. X#define DM_REGID 4
  1765. X
  1766. XSTAB *aadd();
  1767. XSTAB *hadd();
  1768. !STUFFY!FUNK!
  1769. echo ""
  1770. echo "End of kit 20 (of 24)"
  1771. cat /dev/null >kit20isdone
  1772. run=''
  1773. config=''
  1774. for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do
  1775.     if test -f kit${iskit}isdone; then
  1776.     run="$run $iskit"
  1777.     else
  1778.     todo="$todo $iskit"
  1779.     fi
  1780. done
  1781. case $todo in
  1782.     '')
  1783.     echo "You have run all your kits.  Please read README and then type Configure."
  1784.     chmod 755 Configure
  1785.     ;;
  1786.     *)  echo "You have run$run."
  1787.     echo "You still need to run$todo."
  1788.     ;;
  1789. esac
  1790. : Someone might mail this, so...
  1791. exit
  1792.  
  1793.