home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume39 / ioccc.1993 / part01 next >
Encoding:
Text File  |  1993-09-26  |  62.4 KB  |  1,954 lines

  1. Newsgroups: comp.sources.misc
  2. From: chongo@toad.com (Landon Curt Noll)
  3. Subject: v39i104:  ioccc.1993 - 1993 International Obfuscated C Code Contest winners, Part01/04
  4. Message-ID: <csm-v39i104=ioccc.1993.122324@sparky.Sterling.COM>
  5. X-Md4-Signature: fe403d217821bf7d08519da4ec7ec4c4
  6. Keywords: ioccc
  7. Sender: kent@sparky.sterling.com (Kent Landfield)
  8. Reply-To: chongo@toad.com (Landon Curt Noll)
  9. Organization: Nebula Consultants in San Francisco
  10. Date: Sun, 26 Sep 1993 17:25:14 GMT
  11. Approved: kent@sparky.sterling.com
  12.  
  13. Submitted-by: chongo@toad.com (Landon Curt Noll)
  14. Posting-number: Volume 39, Issue 104
  15. Archive-name: ioccc.1993/part01
  16. Environment: C
  17.  
  18. Enclosed is the first of a 4 part shar file containing the winners of
  19. the 1993 International Obfuscated C Code Contest.
  20.  
  21. We congratulate the winners for doing a fine job.  Their efforts and
  22. feedback have resulted another good year for the contest.
  23.  
  24. We apologize to both the 1993 winners and to the net for the delay in
  25. posting of these results.  We had extended discussions with several of
  26. the contest winners that took some time to resolve.  In addition one
  27. of us, Landon Curt Noll, became very busy running for City Council in
  28. Sunnyvale California, USA.
  29.  
  30. Please note:  
  31.  
  32.     The 1994 contest will not open until early March 1994.  The rules
  33.     are expected to be very similar to the 1993 rules, though the input
  34.     format will change slightly.  Please wait for the 1994 rules to be
  35.     posted before submitting 1994 entries.
  36.  
  37. If you find problems with some of the contest entries, or find typos
  38. in our notes, please send ->PATCH FILES OR COMPLETE FILES<- containing 
  39. the corrections to:
  40.  
  41.     judges@toad.com   -or-   ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
  42.  
  43. chongo <Landon Curt Noll> /\cc/\        chongo@toad.com
  44. Larry Bassel                            lab@sun.com
  45.  
  46. p.s. previous winners are available on ftp.uu.net via anonymous ftp
  47.      under the directory pub/ioccc.  Any 'patches' to the 1993 winners
  48.      will be deposited there in a few months.
  49.  
  50. =-=
  51.  
  52.   Send comments, questions, bugs to: 
  53.  
  54.      judges@toad.com   -or-   ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
  55.  
  56.   You are strongly encouraged to read the new contest rules before
  57.   sending any entries.  The rules, and sometimes the contest Email
  58.   address itself, change over time.  Valid entries one year may
  59.   be rejected in a later year due to changes in the rules.  The typical
  60.   start date for contests is in early March.  Contest rules are normally not 
  61.   finalized and posted until the beginning of the contest.  The typical closing
  62.   date for contests are in early May.
  63.  
  64.   The contest rules are posted to comp.unix.wizards, comp.lang.c,
  65.   misc.misc, alt.sources and comp.sources.d.  If you do not have access 
  66.   to these groups, or if you missed the early March posting, you may 
  67.   request a copy from the judges, via Email, at the address above.
  68.  
  69.   Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
  70.   All Rights Reserved.  Permission for personal, educational or non-profit
  71.   use is granted provided this this copyright and notice are included in its
  72.   entirety and remains unaltered.  All other uses must receive prior permission
  73.   in writing from both Landon Curt Noll and Larry Bassel.
  74.  
  75.   Previous contest winners are available via anonymous ftp from
  76.   ftp.uu.net under the directory /pub/ioccc.
  77.  
  78. ---- Cut Here and unpack ----
  79. #! /bin/sh
  80. # This is ioccc.1993, a shell archive.  Remove anything before this line, 
  81. # then feed it into a shell via "sh file" or similar.  To overwrite existing
  82. # files, type "sh file -c".
  83. #
  84. # Contents:  1993 1993/ant.doc 1993/ejb.explain2 1993/jonth.hint
  85. #   1993/mkentry.c
  86. #
  87. # Send comments, questions, bugs to: 
  88. #
  89. #    judges@toad.com   -or-   ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
  90. #
  91. # You are strongly encouraged to read the new contest rules before
  92. # sending any entries.  The rules, and sometimes the contest Email
  93. # address itself, change over time.  Valid entries one year may
  94. # be rejected in a later year due to changes in the rules.  The typical
  95. # start date for contests is in early March.  Contest rules are normally not 
  96. # finalized and posted until the beginning of the contest.  The typical closing 
  97. # date for contests are in early May.
  98. #
  99. # The contest rules are posted to comp.unix.wizards, comp.lang.c,
  100. # misc.misc, alt.sources and comp.sources.d.  If you do not have access 
  101. # to these groups, or if you missed the early March posting, you may 
  102. # request a copy from the judges, via Email, at the address above.
  103. #
  104. # Copyright (c) 1993, Landon Curt Noll & Larry Bassel.
  105. # All Rights Reserved.  Permission for personal, educational or non-profit
  106. # use is granted provided this this copyright and notice are included in its
  107. # entirety and remains unaltered.  All other uses must receive prior permission
  108. # in writing from both Landon Curt Noll and Larry Bassel.
  109. #
  110. # Previous contest winners are available via anonymous ftp from
  111. # ftp.uu.net under the directory /pub/ioccc.
  112. #
  113. # Wrapped by kent@sparky on Sun Sep 26 12:05:11 1993
  114. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  115. echo If this archive is complete, you will see the following message:
  116. echo '          "shar: End of archive 1 (of 4)."'
  117. if test ! -d '1993' ; then
  118.     echo shar: Creating directory \"'1993'\"
  119.     mkdir '1993'
  120. fi
  121. if test -f '1993/ant.doc' -a "${1}" != "-c" ; then 
  122.   echo shar: Will not clobber existing file \"'1993/ant.doc'\"
  123. else
  124.   echo shar: Extracting \"'1993/ant.doc'\" \(12274 characters\)
  125.   sed "s/^X//" >'1993/ant.doc' <<'END_OF_FILE'
  126. X0. NAME
  127. X
  128. X    ag        Anthony's Grep
  129. X
  130. X
  131. X1. SYNOPSIS
  132. X
  133. X    ag <pattern> [file...]
  134. X
  135. X
  136. X2. DESCRIPTION
  137. X
  138. XThe AG utility shall search input files, selecting lines matching a
  139. Xpattern.  An input line shall be selected if the pattern, treated as a
  140. Xsubset of Extended Regular Expressions as described by POSIX.2
  141. XStandard section 2.8.4, matches any part of the line; a null pattern
  142. Xshall match every line.  Each selected input line shall be written to
  143. Xthe standard output.
  144. X
  145. XRegular expression matching shall be based on text lines, which are
  146. Xseparated by a <newline> character.  A regular expression cannot
  147. Xcontain a <newline> and there is no way for a pattern to match a
  148. X<newline> found in the input.
  149. X
  150. X
  151. X3. OPTIONS
  152. X
  153. XNone.
  154. X
  155. X
  156. X4. OPERANDS
  157. X
  158. Xpattern         Specify one pattern to be used during the search for
  159. X        input.  See Extended Regular Exprssions below on what
  160. X        constitutes a valid pattern.
  161. X
  162. Xfile            A pathname of a file to be searched for the pattern.
  163. X        If no file operands are specified or the file operand
  164. X        is dash (-), the standard input shall be used.
  165. X
  166. X
  167. X5. EXTERNINAL INFLUENCES
  168. X
  169. X5.1. STANDARD INPUT
  170. X
  171. XThe standard input shall be used only if no file operands are
  172. Xspecifed.  See Input Files.
  173. X
  174. X
  175. X5.2. INPUT FILES
  176. X
  177. XThe input files shall be text files.
  178. X
  179. X
  180. X5.3. ENVIRONMENT VARIABLES
  181. X
  182. XNo environment variables are used.
  183. X
  184. X
  185. X5.4. ASYNCHRONOUS EVENTS
  186. X
  187. XDefault.
  188. X
  189. X
  190. X6. EXTERNAL EFFECTS
  191. X
  192. X6.1. STANDARD OUTPUT
  193. X
  194. XFor each selected input line from a file, a single output line shall
  195. Xbe written:
  196. X
  197. X    "%s:%s\n", file, line
  198. X
  199. XStandard input will have the filename dash (-).
  200. X
  201. X
  202. X6.2. STANDARD ERROR
  203. X
  204. XStandard error is used for diagnostic messages only.
  205. X
  206. X
  207. X6.3. OUTPUT FILES
  208. X
  209. XNone.
  210. X
  211. X
  212. X7. EXTENDED DESCRIPTION
  213. X
  214. X7.1. EXTENDED REGULAR EXPRESSIONS
  215. X
  216. X7.1.1. MATCHING A SINGLE CHARACTER
  217. X
  218. XAn ERE ordinary character, a special character preceded by a
  219. Xbackslash, or a period shall match a single character.  A bracket
  220. Xexpression shall match a single character.  An ERE matching a single
  221. Xcharacter enclosed in parentheses shall match the same as the ERE
  222. Xwithout parentheses would have matched.
  223. X
  224. X
  225. X7.1.1.1. ERE ORDINARY CHARACTERS
  226. X
  227. XAn oridinary character is an ERE that matches itself.  An ordinary
  228. Xcharacter is any character in the supported character set, except for
  229. Xthe ERE special characters listed in 7.1.1.2.  The interpretation of
  230. Xan ordinary character preceded by a backslash (\) is the ordinary
  231. Xcharacter.
  232. X
  233. X
  234. X7.1.1.2. ERE SPECIAL CHARACTERS
  235. X
  236. XAn ERE special character has special properties in certain contexts.
  237. XOutside of those contexts, or when preceded by a backslash, such a
  238. Xcharacter shall be an ERE that matches the special character itself.
  239. XThe extended regular expression special characters and the contexts in
  240. Xwhich they have their special meaning are:
  241. X
  242. X    . [ \ (         The period, left-bracket, backslash, and left-
  243. X            parenthesis are special except when used in a
  244. X            bracket expression.  Outside a bracket
  245. X            expression, a left-parenthesis immediately
  246. X            followed by a right-parenthesis will be
  247. X            treated as a null expression.
  248. X
  249. X    )               The right-parenthesis is special when matched
  250. X            with a preceding left-parenthesis, both
  251. X            outside of a bracket expression.
  252. X
  253. X    * ?             The asterisk and question-mark are special
  254. X            except when used in a bracket expression.
  255. X            Results are undefined if this character
  256. X            appears first in an ERE, or immediately
  257. X            following a vertial-line, circumflex, or
  258. X            left-parenthesis.
  259. X
  260. X    |               The vertical-line is special except when used
  261. X            in a bracket expression.  A vertical-line
  262. X            appearing first or last in an ERE or
  263. X            immediately following a vertical-line or
  264. X            left-parenthesis, or preceding a
  265. X            right-parenthesis, produces a null expression.
  266. X
  267. X    ^               The circumflex shall be special when used as
  268. X            an anchor or, as the first character of a
  269. X            bracket expression.
  270. X
  271. X    $               The dollar-sign shall be special when used as
  272. X            an anchor.
  273. X
  274. X
  275. X7.1.1.3 PERIODS IN ERE
  276. X
  277. XA period (.), when used outside of a bracket expression, is an ERE
  278. Xthat shall match any character in the supported character set except
  279. XNUL.
  280. X
  281. X7.1.2. ERE BRACKET EXPRESSION
  282. X
  283. XA bracket expression (an expression enclosed in square brackets, []),
  284. Xis an ERE that matches a single character contained in the nonempty
  285. Xset of characters represented by the bracket expression.
  286. X
  287. XThe following rules and definitions apply to bracket expressions:
  288. X
  289. X   1)   A bracket expression is either a matching list expression
  290. X    or a nonmatching list expression.  It consists of one or more
  291. X    characters and/or range expressions.  The right-bracket (])
  292. X    shall lose its special meaning and represent itself in a
  293. X    bracket expression if it occurs first in the list [after an
  294. X    initial circumflex (^), if any].  Otherwise, it shall
  295. X    terminate the bracket expression.  The special characters
  296. X    period (.), asterisk (*), left-bracket ([), and backslash (\)
  297. X    shall lose their special meaning within a bracket expression.
  298. X
  299. X   2)   A matching list expression specifies a list that shall match
  300. X    any one of the expressions represented in the list.  The first
  301. X    character of the list shall not be the circumflex.  For
  302. X    example,  [abc]  is an ERE that matches any of a, b, or c.
  303. X
  304. X   3)   A nonmatching list expression begins with a circumflex (^),
  305. X    and specifies a list that shall match any character except for
  306. X    the expressions represented in the list after the leading
  307. X    circumflex.  For example,  [^abc]  is an ERE that matches any
  308. X    character except a, b, or c.  The circumflex shall have this
  309. X    special meaning only when it occurs first in the list,
  310. X    immediately following the left-bracket.
  311. X
  312. X   4)   A range expression represents the set of characters that
  313. X    fall between two elements in the current collation sequence,
  314. X    inclusive.  It shall be expressed as the starting point and
  315. X    the ending point separated by a hyphen (-).
  316. X
  317. X    In the following, all examples assume the collation sequence
  318. X    specified for the POSIX Locale (a.k.a ASCII Character Set),
  319. X    unless another collation sequence is sepecifically defined
  320. X    by the hardware.
  321. X
  322. X    The starting range point and the ending range point shall be a
  323. X    collating element (character).  The ending range point shall
  324. X    collate higher than the starting range point; otherwise the
  325. X    expression shall be treated as invalid.
  326. X
  327. X    The interpretation of a range expression where the ending
  328. X    range point is the starting range point of a subsequent range
  329. X    expression is undefined.
  330. X
  331. X    The hyphen character shall be treated as itself if it occurs
  332. X    first (after an initial ^, if any) or last in the list, or as
  333. X    an ending range point in a range expression.  As examples, the
  334. X    expressions  [-ac]  and  [ac-] are equivalent and match any of
  335. X    the characters a, c, or -; the expressions  [^-ac]  and [^ac-]
  336. X    are equivalent and match ant character except a, c, -; the
  337. X    expression  [%--]  matches any of the characters between % and
  338. X    - inclusive;  the expression  [--@]  matches any of the
  339. X    characters between - and @ inclusive; and the expression
  340. X    [a--@] is invalid, because the letter a follows the symbol -
  341. X    in the POSIX Locale.
  342. X
  343. X
  344. X7.1.3. ERE MATCHING MULTIPLE CHARACTERS
  345. X
  346. XThe following rules shall be used to construct EREs matching multiple
  347. Xcharacters from EREs matching a single character:
  348. X
  349. X   1)   A concatenation of EREs shall match the concatenation of the
  350. X    character sequences matched by each component of the ERE.  A
  351. X    concatenation of EREs enclosed in parentheses shall match
  352. X    whatever the concatenation without parentheses matches.  For
  353. X    example, both the ERE cd and the ERE (cd) are matched by the
  354. X    third and forth character of the string abcdefabcdef.
  355. X
  356. X   2)   When an ERE matching a single character, or a concatention of
  357. X    EREs enclosed in parentheses is followed by the special
  358. X    character asterisk (*), together with that asterisk it shall
  359. X    match what zero or more consecutive occurences of the ERE
  360. X    would match.  For example, the ERE b*c matches the first
  361. X    character in the string cabbbcde, and the ERE b*cd matches the
  362. X    third through seventh characters in the string
  363. X    cabbbcdebbbbbbcdbc.  And, [ab]* and [ab][ab] are equivalent
  364. X    when matching the string ab.
  365. X
  366. X    3)  When an ERE matching a single character or an ERE enclosed in
  367. X    parentheses is followed by the special character question-mark
  368. X    (?), together with that question mark it shall match what zero
  369. X    or one consecutive occurences of the ERE would match.  For
  370. X    example, the ERE b?c matches the second character in the
  371. X    string acabbbcde.
  372. X
  373. XThe behaviour of multiple adjacent duplication symbols (*, ?) produces
  374. Xundefined results.
  375. X
  376. X
  377. X7.1.4. ERE ALTERATION
  378. X
  379. XTwo EREs separated by the special character vertical-line (|) shall
  380. Xmatch a string that is matched by either.  For example, the ERE
  381. Xa((bc)|d) matches the string abc and the string ad.  Single
  382. Xcharacters, or expressions matching single characters, separated by
  383. Xthe vertical-line and enclosed in parentheses, shall be treated as an
  384. XERE matching a single character.
  385. X
  386. X
  387. X7.1.5. ERE PRECEDENCE
  388. X
  389. XThe order of precedence shall be as shown in the table below, from 
  390. Xhigh to low:
  391. X
  392. X    escaped characters            \<special character>
  393. X    bracket expression            [ ]
  394. X    grouping                ( )
  395. X    single-character-ERE duplication    * ?
  396. X    concatenation
  397. X    anchoring                ^ $
  398. X    alteration                |
  399. X
  400. XFor example, the ERE abba|cde matches either the string abba or the
  401. Xstring cde (because concatenation has a higher order of precedence
  402. Xthan alteration).
  403. X
  404. X
  405. X7.1.6. ERE EXPRESSION ANCHORING
  406. X
  407. XAn ERE can be limited to matching strings that begin or end a line;
  408. Xthis is called anchoring.  The circumflex and dollar-sign special
  409. Xcharacters shall be considered ERE anchors in the following contexts:
  410. X
  411. X   1)   A circumflex (^) outside a bracket expression shall anchor
  412. X    the (sub)expression it begins to the beginning of a string;
  413. X    such a (sub)expression can match only a sequence starting at
  414. X    the first character of a string.  For example, the EREs ^ab
  415. X    and (^ab) match ab in the string abcdef, but fail to match in
  416. X    the string cdefab, and the ERE a^b is valid, but can never
  417. X    match because the character a prevents the expression ^b from
  418. X    matching the first character of a string.
  419. X
  420. X   2)   A dollar-sign ($) outside a bracket expression shall anchor
  421. X    the (sub)expression it ends to the end of a string; such a
  422. X    (sub)expression can match only a sequence ending at the last
  423. X    character of a string.  For example, the EREs ef$ and (ef$)
  424. X    match ef in the string abcdef, but fail to match in the string
  425. X    cdefab, and the ERE e$f is valid, but can never match because
  426. X    the character f prevents the expression e$ from matching the
  427. X    last character of a string.
  428. X
  429. X
  430. X8. EXIT STATUS
  431. X
  432. XThe following exit codes will be returned:
  433. X    0    Successful match.
  434. X    1    No match.
  435. X    2    Usage error.
  436. X    3    General error.
  437. X
  438. X
  439. X9. INSTALLATION
  440. X
  441. XAG can be built on any system providing at least K&R C.  It has been 
  442. Xtested on 
  443. X
  444. X    o  SunOS with GCC
  445. X    o  ATARI Mega ST with Sozobon C
  446. X    o  PC clone with Turbo C and WatCom C
  447. X    o  Interactive UNIX System V/386 release 3.2
  448. X
  449. XFor most machines, the compile command line should be
  450. X
  451. X    cc -O -o ag ag.c
  452. X
  453. XPC class machines may require that medium or large memory model be used
  454. Xand that ARRAY be set to 256.  For Watcom C the command line would be
  455. X
  456. X    wcl -ml -DARRAY=256 ag.c
  457. X
  458. XThe value ARRAY represents the size of the compiled pattern array and
  459. Xthe size of the array used to record matched states.  The default
  460. Xvalue choosen should handle most patterns.  ARRAY can be overridden on
  461. Xthe command line with -DARRAY=nn, where 255 < nn < INT_MAX.
  462. X
  463. X
  464. X10. REFERENCES
  465. X
  466. X[Aho86]    Aho, Sethi, and Ullman, "Compilers - Principles, Techniques,
  467. X    and Tools", Addison-Wesley, 86, ISBN 0-201-10088-6, chapter 3
  468. X
  469. X[K&P81] Kernighan and Plauger, "Software Tools in Pascal".
  470. X    Addison-Wesley, 81, ISBN 0-201-10342-7, chapter 5
  471. X
  472. X[Mil87]    Webb Miller, "A Software Tools Sampler", 
  473. X    Prentice Hall, 87, ISBN 0-13-822305-X, chaper 4
  474. X
  475. X[POSIX]    POSIX.2 Standard, 2.8.4 Extended Regular Expressions, 4.28 Grep
  476. X
  477. X
  478. X11. FILES
  479. X
  480. Xag.c        Obfuscated source
  481. Xag.doc        Manual for AG
  482. Xagag.c        Unobfuscated source
  483. Xtest.mk        Makefile test driver for AG.
  484. X
  485. X
  486. X12. BUGS
  487. X
  488. XThe expression (a*)* compiles but loops forever.
  489. X
  490. XThere is no check for trailing backslash (\) in the pattern.
  491. X
  492. XThere is no check for unbalanced brackets.  Omitting a closing bracket
  493. Xwill generate a "Patern too long" error, which is not the real error.
  494. X
  495. X
  496. X13. NOTICES
  497. X
  498. XPublic Domain 1992, 1993 by Anthony Howe.  No warranty.
  499. X
  500. X
  501. END_OF_FILE
  502.   if test 12274 -ne `wc -c <'1993/ant.doc'`; then
  503.     echo shar: \"'1993/ant.doc'\" unpacked with wrong size!
  504.   fi
  505.   # end of '1993/ant.doc'
  506. fi
  507. if test -f '1993/ejb.explain2' -a "${1}" != "-c" ; then 
  508.   echo shar: Will not clobber existing file \"'1993/ejb.explain2'\"
  509. else
  510.   echo shar: Extracting \"'1993/ejb.explain2'\" \(7258 characters\)
  511.   sed "s/^X//" >'1993/ejb.explain2' <<'END_OF_FILE'
  512. X    The Patience puzzle, probably of Chinese origin, consists of
  513. X    an iron U-shaped piece and several rings that link around
  514. X    it.  The physical shape of the puzzle is very difficult to
  515. X    describe verbally, but here is an attempt.
  516. X
  517. X    This description of the puzzle is presented as a set of
  518. X    instructions for constructing the puzzle.  Start with a flat
  519. X    piece of iron about 15 centimeters long by about two
  520. X    centimeters wide.  Drill six holes in the piece of iron.
  521. X    Through each hole, place a rod.  The rod should have a
  522. X    diameter slightly less than that of the hole so that it can
  523. X    move freely.  One end of the rod is like the head of a nail
  524. X    and is larger than the hole to prevent it from coming free.
  525. X    The other end is looped around a metal ring with a diameter
  526. X    of about five centimeters.  This completely prevents the
  527. X    iron rod from separating from the base.  Each rod, in
  528. X    addition to going through the iron base, goes through the
  529. X    ring at the end of the rod to its right.  The only rod free
  530. X    of this restriction is the rightmost rod.  What has been
  531. X    described so far is one of the two components of the puzzle.
  532. X
  533. X    The other component is another iron rod shaped like a U.
  534. X    the U is as long from the tips to the base as the original
  535. X    piece of iron with the holes in it.  The ends of the U are
  536. X    looped around another ring of about five centimeters in
  537. X    diameter.  In the puzzle's initial configuration, the U is
  538. X    placed through the rings so that it is held in place by the
  539. X    iron rods.  Imagine starting with the U piece before the
  540. X    iron loop is placed at the end.  Slide the legs of the U
  541. X    through the loops so that the iron rods securing the loops
  542. X    to the metal strip go up the center of the U.  Placing the
  543. X    final ring at the ends of the U prevents it from coming out.
  544. X    The object of the puzzle is to free the U-shaped piece from
  545. X    the other piece.
  546. X
  547. X    The following illustration (sideways) shows a three-ring
  548. X    case of this puzzle.  If you look carefully, you can see
  549. X    that the first ring could be lifted over the edge of the U
  550. X    and slid down through the center of the U, thereby freeing
  551. X    the U from the first iron rod.  The second ring can also be
  552. X    freed in the initial configuration since it is already over
  553. X    the rod for the first ring.  The third ring cannot be moved,
  554. X    however, since it is blocked by the iron rod two which the
  555. X    first ring is attached.  If the first first is removed, then
  556. X    the third ring is no longer blocked by the first ring's iron
  557. X    rod and can be removed freely.  The second ring, however
  558. X    cannot be moved if the first ring is gone because it will
  559. X    then be blocked by the first ring in its new position
  560. X    outside of the U.
  561. X
  562. X    Here is an illustration of the three-ring case.  The bottom
  563. X    of the puzzle is on the left-hand side of the page.
  564. X
  565. X
  566. X
  567. X                               //==\\
  568. X                              ||    ||
  569. X                              ||    ||
  570. X                         *****||**  ||
  571. X                       ***    || ***||
  572. X                       **     ||   *||
  573. X          |\           **     ||    ||**
  574. X          | \           ***   ||    ||  ***
  575. X          |  \            ***  |    ||    ===
  576. X          |   \             ***     ||  // * \\
  577. X          |    \              ***   || || **  ||
  578. X          |     |             | **********    ||
  579. X          |     |             ||    || ||     ||
  580. X          |     |             ||    || ||     ||
  581. X          |     |        *****||**  ||  \\    ||
  582. X       |  | |\  |      ***    || ***||        ||
  583. X       |==| |=========-**-===-||-============//
  584. X       |==| |=========-**-===-||-===========//
  585. X       |  |  \| |       ***   ||    ||  ***
  586. X          |     |         *** ||    ||    ===
  587. X          |     |           ***|    ||  // * \\
  588. X          |     |             ***   || || **  ||
  589. X          |     |             ||**********    ||
  590. X          |     |             ||    || ||     ||
  591. X          |     |        *****||**  ||  \\    ||
  592. X       |  | |\  |      ***    || ***||        ||
  593. X       |==| |=========-**-===-||-============//
  594. X       |==| |=========-**-===-||-===========//
  595. X       |  |  \| |       ***   ||    ||  ***
  596. X          |     |         *** ||    ||    ===
  597. X          |     |           ***|    ||  // * \\
  598. X          |     |             ***   || || **  ||
  599. X          |     |             ||**********    ||
  600. X          |     |             ||    || ||     ||
  601. X          |     |             ||    || ||     ||
  602. X       |  |     |             ||    ||  \\    ||
  603. X       |  | |\  |             ||    ||        ||
  604. X       |==| |================-||-============//
  605. X       |==| |================-||-===========//
  606. X       |  |  \| |             ||    ||
  607. X          |     |             ||    ||
  608. X          |     |             ||    ||
  609. X          |     |             ||    ||
  610. X          \     |             ||    ||
  611. X           \    |              \\   ||
  612. X            \   |               \\  ||
  613. X             \  |                \\ ||
  614. X              \ |                 \\||
  615. X               \|                  \||
  616. X
  617. X    This puzzle takes other forms as well.  One such puzzle is
  618. X    called "Spin-Out".  This puzzle consists of one plastic
  619. X    piece that encases another piece that can slide in and out
  620. X    of it.  The movement of the smaller piece is restricted by
  621. X    discs that, when turned to one angle, lock the smaller piece
  622. X    inside the larger one and, when turned the other way, allow
  623. X    it to move.  This puzzle is as difficult to describe as the
  624. X    first and, since I don't have one in front of me, I will not
  625. X    attempt to describe it.  The object of this puzzle is to
  626. X    free the smaller piece from the larger one.  The other
  627. X    puzzle that is like this one consists of a cylinder with
  628. X    rods protruding from the top.  The rods can be slid from the
  629. X    center to the edge of the cylinder constrained by a series
  630. X    of discs in the center.  The discs have cuts in them that
  631. X    allow some rods to move and force others in one place based
  632. X    on the relative rotations of the discs.  The object here is
  633. X    to move all the rods from the inside to the outside.
  634. X
  635. X    What makes these puzzles similar is that the physical shapes
  636. X    of the puzzles put the same restrictions on the movement of
  637. X    the pieces.  Specifically, there is always one piece that is
  638. X    free to move.  The only other piece that is free to move is
  639. X    the second one that is still attached to the base it is
  640. X    trying to be freed from.  In the case of the original
  641. X    puzzle, consider the rings numbered from 1 to 6 with ring 1
  642. X    being the one at the closed send of the U.  Ring 1 can
  643. X    always be removed from or added to the U.  In the initial
  644. X    state, when all rings are around the U, ring 2 is the other
  645. X    one that can be moved because it is second.  If ring 1 is
  646. X    removed, then only two operations are possible: the
  647. X    restoration of ring 1 and the removal of ring 3.  This is
  648. X    because ring 1 is always movable, and ring 3 is currently
  649. X    the second ring still attached to the U.  This constraint
  650. X    leads to a recursive solution to the puzzle.  Like the
  651. X    Towers of Hanoi, the number of steps to solve this puzzle is
  652. X    exponential in the number of rings.
  653. END_OF_FILE
  654.   if test 7258 -ne `wc -c <'1993/ejb.explain2'`; then
  655.     echo shar: \"'1993/ejb.explain2'\" unpacked with wrong size!
  656.   fi
  657.   # end of '1993/ejb.explain2'
  658. fi
  659. if test -f '1993/jonth.hint' -a "${1}" != "-c" ; then 
  660.   echo shar: Will not clobber existing file \"'1993/jonth.hint'\"
  661. else
  662.   echo shar: Extracting \"'1993/jonth.hint'\" \(844 characters\)
  663.   sed "s/^X//" >'1993/jonth.hint' <<'END_OF_FILE'
  664. XMost Obfuscated X Program: <jonth@ifi.uio.no> Jon Thingvold
  665. X
  666. X    Jon Thingvold
  667. X    University of Oslo
  668. X    Sogn Studentby 8231
  669. X    N 0858 Oslo
  670. X    Norway
  671. X
  672. X
  673. XJudges' comments:
  674. X
  675. X    To use:
  676. X    make jonth        # requires the X11 library
  677. X    ./jonth            # must be run on an X11 server
  678. X
  679. X    Use 'h' and 'l' to shift objects left or right.  Use 'k' to
  680. X    rotate and press SPACE to drop.
  681. X
  682. X    This program's output may be even more obfuscated when played 
  683. X    on inverse video.  :-)
  684. X
  685. X
  686. XSelected notes from the author:
  687. X
  688. X    This is jonth (jon's t(h)etris) for the X Window System.
  689. X
  690. X    This program is also an example of data abstraction.  The X array is 
  691. X    after initialization hidden by the well defined macros t, u and F.
  692. X
  693. X    This program is highly portable as it runs on a "Notebook" size SPARC.
  694. X    This program will not work on machines with sizeof(int)!=sizeof(void *).
  695. END_OF_FILE
  696.   if test 844 -ne `wc -c <'1993/jonth.hint'`; then
  697.     echo shar: \"'1993/jonth.hint'\" unpacked with wrong size!
  698.   fi
  699.   # end of '1993/jonth.hint'
  700. fi
  701. if test -f '1993/mkentry.c' -a "${1}" != "-c" ; then 
  702.   echo shar: Will not clobber existing file \"'1993/mkentry.c'\"
  703. else
  704.   echo shar: Extracting \"'1993/mkentry.c'\" \(34486 characters\)
  705.   sed "s/^X//" >'1993/mkentry.c' <<'END_OF_FILE'
  706. X/* @(#)mkentry.c    1.25 4/5/93 15:58:08 */
  707. X/*
  708. X * Copyright (c) Landon Curt Noll & Larry Bassel, 1993.
  709. X * All Rights Reserved.  Permission for personal, educational or non-profit 
  710. X * use is granted provided this this copyright and notice are included in 
  711. X * its entirety and remains unaltered.  All other uses must receive prior
  712. X * permission in writing from both Landon Curt Noll and Larry Bassel.
  713. X */
  714. X/*
  715. X * mkentry - make an International Obfuscated C Code Contest entry
  716. X *
  717. X * usage:
  718. X *    mkentry -r remarks -b build -p prog.c -o ioccc.entry
  719. X *
  720. X *    -r remarks        file with remarks about the entry
  721. X *    -b build        file containing how prog.c should be built
  722. X *    -p prog.c        the obfuscated program source file
  723. X *    -o ioccc.entry        ioccc entry output file
  724. X *
  725. X * compile by:
  726. X *    cc mkentry.c -o mkentry
  727. X */
  728. X/*
  729. X * Placed in the public domain by Landon Curt Noll, 1992.
  730. X *
  731. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  732. X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  733. X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  734. X */
  735. X/*
  736. X * WARNING:
  737. X *
  738. X * This program attempts to implement the IOCCC rules.  Every attempt
  739. X * has been made to make sure that this program produces an entry that
  740. X * conforms to the contest rules.  In all cases, where this program
  741. X * differs from the contest rules, the contest rules will be used.  Be
  742. X * sure to check with the contest rules before submitting an entry.
  743. X *
  744. X * FOR MORE INFORMATION:
  745. X *
  746. X *   You may contact the judges by sending Email to the following address:
  747. X *
  748. X *    ...!{apple,pyramid,sun,uunet}!hoptoad!judges    (not the address for
  749. X *    judges@toad.com                     submitting entries)
  750. X *
  751. X *   Questions and comments about the contest are welcome.
  752. X *
  753. X *  The rules and the guidelines may (and often do) change from year to
  754. X *  year.  You should be sure you have the current rules and guidelines
  755. X *  prior to submitting entries.  To obtain them, send Email to the address
  756. X *  above and use the subject 'send rules'.
  757. X *
  758. X *  One may obtain winners of previous contests (1984 to date), via ftp from:
  759. X *
  760. X *    host: ftp.uu.net    (192.48.96.9)
  761. X *    user: anonymous
  762. X *    pass: yourname@yourhost
  763. X *    dir:  ~/pub/ioccc
  764. X *
  765. X *  As a last resort, previous winners may be obtained by sending Email
  766. X *  to the above address.  Please use the subject 'send YEAR winners',
  767. X *  where YEAR is a single 4 digit year, a year range, or 'all'.
  768. X *
  769. X * Because contest rules change from year to year, one should only use this
  770. X * program for the year that it was intended.  Be sure that the RULE_YEAR
  771. X * define below matches this current year.
  772. X */
  773. X
  774. X#include <stdio.h>
  775. X#include <ctype.h>
  776. X#include <time.h>
  777. X#include <sys/types.h>
  778. X#include <sys/stat.h>
  779. X
  780. X/* logic */
  781. X#ifndef TRUE
  782. X# define TRUE 1
  783. X#endif /* TRUE */
  784. X#ifndef FALSE
  785. X# define FALSE 0
  786. X#endif /* FALSE */
  787. X#define EOF_OK TRUE
  788. X#define EOF_NOT_OK FALSE
  789. X
  790. X/* global limits */
  791. X#define RULE_YEAR 1993        /* NOTE: should match the current year */
  792. X#define START_DATE "1Mar92 0:00 UTC"    /* first confirmation received */
  793. X#define MAX_COL 79        /* max column a line should hit */
  794. X#define MAX_BUILD_SIZE 256    /* max how to build size */
  795. X#define MAX_PROGRAM_SIZE 3217    /* max program source size */
  796. X#define MAX_PROGRAM_SIZE2 1536    /* max program source size not counting
  797. X                   whitespace and {}; not followed by
  798. X                   whitespace or EOF */
  799. X#define MAX_TITLE_LEN 12    /* max chars in the title */
  800. X#define MAX_ENTRY_LEN 1        /* max length in the entry input line */
  801. X#define MAX_ENTRY 8        /* max number of entries per person per year */
  802. X#define MAX_FILE_LEN 1024    /* max filename length for a info file */
  803. X
  804. X/* where to send entries */
  805. X#define ENTRY_ADDR1 "...!{apple,pyramid,sun,uunet}!hoptoad!obfuscate"
  806. X#define ENTRY_ADDR2 "obfuscate@toad.com"
  807. X
  808. X/* uuencode process - assumes ASCII */
  809. X#define UUENCODE(c) (encode_str[(int)(c)&0xff])
  810. X#define UUENCODE_LEN 45        /* max uuencode chunk size */
  811. X#define UUINFO_MODE 0444    /* mode of an info file's uuencode file */
  812. X#define UUBUILD_MODE 0444    /* mode of the build file's uuencode file */
  813. X#define UUBUILD_NAME "build"    /* name for the build file's uuencode file */
  814. X#define UUPROG_MODE 0444    /* mode of the program's uuencode file */
  815. X#define UUPROG_NAME "prog.c"    /* name for the program's uuencode file */
  816. X
  817. X/* encode_str[(char)val] is the uuencoded character of val */
  818. Xchar encode_str[256+1] = "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
  819. X
  820. X/* global declarations */
  821. Xchar *program;            /* our name */
  822. Xlong start_time;        /* the startup time */
  823. X
  824. X/* forward declarations */
  825. Xvoid parse_args();
  826. Xvoid usage();
  827. XFILE *open_remark();
  828. XFILE *open_build();
  829. XFILE *open_program();
  830. XFILE *open_output();
  831. Xvoid output_entry();
  832. Xvoid output_remark();
  833. Xvoid output_author();
  834. Xvoid output_info();
  835. Xvoid output_build();
  836. Xvoid output_program();
  837. Xvoid output_end();
  838. Xint get_line();
  839. Xvoid output_till_dot();
  840. Xint col_len();
  841. Xvoid check_io();
  842. Xvoid uuencode();
  843. X
  844. Xmain(argc, argv)
  845. X    int argc;        /* arg count */
  846. X    char **argv;    /* the args */
  847. X{
  848. X    FILE *remark=NULL;    /* open remarks stream */
  849. X    FILE *build=NULL;    /* open build file stream */
  850. X    FILE *prog=NULL;    /* open program stream */
  851. X    FILE *output=NULL;    /* open output stream */
  852. X    char *rname=NULL;    /* file with remarks about the entry */
  853. X    char *bname=NULL;    /* file containing how prog.c should be built */
  854. X    char *pname=NULL;    /* the obfuscated program source file */
  855. X    char *oname=NULL;    /* ioccc entry output file */
  856. X    struct tm *tm;    /* startup time structure */
  857. X
  858. X    /*
  859. X     * check on the year
  860. X     */
  861. X    start_time = time((long *)0);
  862. X    tm = gmtime(&start_time);
  863. X    if (tm->tm_year != RULE_YEAR-1900) {
  864. X    fprintf(stderr,
  865. X    "%s: WARNING: this program applies to %d, which may differ from %d\n\n",
  866. X        argv[0], RULE_YEAR, 1900+tm->tm_year);
  867. X    }
  868. X
  869. X    /*
  870. X     * parse the command line args
  871. X     */
  872. X    parse_args(argc, argv, &rname, &bname, &pname, &oname);
  873. X
  874. X    /*
  875. X     * open/check the input and output files
  876. X     *
  877. X     * We open and truncate the output file first, in case it is the same
  878. X     * as one of the input files.
  879. X     */
  880. X    output = open_output(oname);
  881. X    remark = open_remark(rname);
  882. X    build = open_build(bname);
  883. X    prog = open_program(pname);
  884. X    if (output==NULL || remark==NULL || build==NULL || prog==NULL) {
  885. X    exit(1);
  886. X    }
  887. X
  888. X    /*
  889. X     * output each section
  890. X     */
  891. X    output_entry(output, oname);
  892. X    output_remark(output, oname, remark, rname);
  893. X    output_author(output, oname);
  894. X    output_info(output, oname);
  895. X    output_build(output, oname, build, bname);
  896. X    output_program(output, oname, prog, pname);
  897. X    output_end(output, oname);
  898. X
  899. X    /*
  900. X     * flush the output
  901. X     */
  902. X    if (fflush(output) == EOF) {
  903. X    fprintf(stderr, "%s: flush error in %s: ", program, oname);
  904. X    perror("");
  905. X    exit(2);
  906. X    }
  907. X
  908. X    /*
  909. X     * final words
  910. X     */
  911. X    printf("\nYour entry can be found in %s.  You should check this file\n",
  912. X    oname);
  913. X    printf("correct any problems and verify that the uudecode utility will\n");
  914. X    printf("correctly decode your build file and program.\n\n");
  915. X    printf("This program has been provided as a guide for submitters.  In\n");
  916. X    printf("cases where it conflicts with the rules, the rules shall apply.\n");
  917. X    printf("It is your responsibility to ensure that your entry conforms to\n");
  918. X    printf("the current rules.\n\n");
  919. X    printf("Email your entries to:\n");
  920. X    printf("\t%s\n", ENTRY_ADDR1);
  921. X    printf("\t%s\n\n", ENTRY_ADDR2);
  922. X    printf("Please use the following subject when you Email your entry:\n");
  923. X    printf("\tioccc entry\n\n");
  924. X    /* all done */
  925. X    exit(0);
  926. X}
  927. X
  928. X/*
  929. X * parse_args - parse the command line args
  930. X *
  931. X * Given the command line args, this function parses them and sets the
  932. X * required name flags.  This function will return only if the command
  933. X * line syntax is correct.
  934. X */
  935. Xvoid
  936. Xparse_args(argc, argv, rname, bname, pname, oname)
  937. X    int argc;        /* arg count */
  938. X    char **argv;    /* the args */
  939. X    char **rname;    /* file with remarks about the entry */
  940. X    char **bname;    /* file containing how prog.c should be built */
  941. X    char **pname;    /* the obfuscated program source file */
  942. X    char **oname;    /* ioccc entry output file */
  943. X{
  944. X    char *optarg;    /* -flag option operand */
  945. X    int flagname;    /* the name of the -flag */
  946. X    int i;
  947. X
  948. X    /*
  949. X     * Not everyone has getopt, so we must parse args by hand.
  950. X     */
  951. X    program = argv[0];
  952. X    for (i=1; i < argc; ++i) {
  953. X
  954. X    /* determine the flagname */
  955. X    if (argv[i][0] != '-') {
  956. X        usage(1);
  957. X        /*NOTREACHED*/
  958. X    }
  959. X    flagname = (int)argv[i][1];
  960. X
  961. X    /* determine the flag's operand */
  962. X    if (flagname != '\0' && argv[i][2] != '\0') {
  963. X        optarg = &argv[i][2];
  964. X    } else {
  965. X        if (i+1 >= argc) {
  966. X        usage(2);
  967. X        /*NOTREACHED*/
  968. X        } else {
  969. X        optarg = argv[++i];
  970. X        }
  971. X    }
  972. X
  973. X    /* save the flag's operand in the correct global variable */
  974. X    switch (flagname) {
  975. X    case 'r':
  976. X        *rname = optarg;
  977. X        break;
  978. X    case 'b':
  979. X        *bname = optarg;
  980. X        break;
  981. X    case 'p':
  982. X        *pname = optarg;
  983. X        break;
  984. X    case 'o':
  985. X        *oname = optarg;
  986. X        break;
  987. X    default:
  988. X        usage(3);
  989. X        /*NOTREACHED*/
  990. X    }
  991. X    }
  992. X
  993. X    /*
  994. X     * verify that we have all of the required flags
  995. X     */
  996. X    if (*rname == NULL || *bname == NULL || *pname == NULL || *oname == NULL) {
  997. X    usage(4);
  998. X    /*NOTREACHED*/
  999. X    }
  1000. X    return;
  1001. X}
  1002. X
  1003. X/*
  1004. X * usage - print a usage message and exit
  1005. X *
  1006. X * This function does not return.
  1007. X */
  1008. Xvoid
  1009. Xusage(exitval)
  1010. X    int exitval;        /* exit with this value */
  1011. X{
  1012. X    fprintf(stderr,
  1013. X    "usage: %s -r remarks -b build -p prog.c -o ioccc.entry\n\n", program);
  1014. X    fprintf(stderr, "\t-r remarks\tfile with remarks about the entry\n");
  1015. X    fprintf(stderr, "\t-b build\tfile containing how prog.c should be built\n");
  1016. X    fprintf(stderr, "\t-p prog.c\tthe obfuscated program source file\n");
  1017. X    fprintf(stderr, "\t-o ioccc.entry\tioccc entry output file\n");
  1018. X    exit(exitval);
  1019. X}
  1020. X
  1021. X/*
  1022. X * open_remark - open/check the remark file
  1023. X *
  1024. X * The remark file should be indented by 4 spaces, and should not extend
  1025. X * beyond column MAX_COL.  These are not requirements, so we only warn.
  1026. X *
  1027. X * This function returns NULL on I/O or format error.
  1028. X */
  1029. XFILE *
  1030. Xopen_remark(filename)
  1031. X    char *filename;
  1032. X{
  1033. X    FILE *stream;        /* the opened file stream */
  1034. X    char buf[BUFSIZ+1];        /* input buffer */
  1035. X    int toolong=0;        /* number of lines that are too long */
  1036. X    int non_indent=0;        /* number of lines not indented by 4 spaces */
  1037. X
  1038. X    /*
  1039. X     * open the remark input file
  1040. X     */
  1041. X    stream = fopen(filename, "r");
  1042. X    if (stream == NULL) {
  1043. X    fprintf(stderr, "%s: cannot open remark file: %s: ",
  1044. X        program, filename);
  1045. X    perror("");
  1046. X    return(NULL);
  1047. X    }
  1048. X
  1049. X    /*
  1050. X     * look at each line
  1051. X     */
  1052. X    while (fgets(buf, BUFSIZ, stream) != NULL) {
  1053. X
  1054. X    /* count lines that do not start with 4 spaces */
  1055. X    if (buf[0] != '\n' && strncmp(buf, "    ", 4) != 0) {
  1056. X        ++non_indent;
  1057. X    }
  1058. X
  1059. X    /* count long lines */
  1060. X    if (col_len(buf) > MAX_COL) {
  1061. X        /* found a line that is too long */
  1062. X        ++toolong;
  1063. X    }
  1064. X    }
  1065. X
  1066. X    /* watch for I/O errors */
  1067. X    check_io(stream, filename, EOF_OK);
  1068. X
  1069. X    /* note long lines if needed */
  1070. X    if (toolong > 0) {
  1071. X    fprintf(stderr,
  1072. X        "%s: WARNING: %d line(s) from %s extend beyond the 80th column\n",
  1073. X        program, toolong, filename);
  1074. X    fprintf(stderr,
  1075. X        "%s:          This is ok, but it would be nice to avoid\n\n",
  1076. X        program);
  1077. X    }
  1078. X
  1079. X    /* note non-indented lines, if needed */
  1080. X    if (non_indent > 0) {
  1081. X    fprintf(stderr,
  1082. X        "%s: WARNING: %d line(s) from %s are not indented by 4 spaces\n",
  1083. X        program, non_indent, filename);
  1084. X    fprintf(stderr,
  1085. X        "%s:          This is ok, but it would be nice to avoid\n\n",
  1086. X        program);
  1087. X    }
  1088. X
  1089. X    /* return the open file */
  1090. X    rewind(stream);
  1091. X    return(stream);
  1092. X}
  1093. X
  1094. X/*
  1095. X * open_build - open/check the build file
  1096. X *
  1097. X * The how to build file must not be longer than MAX_BUILD_SIZE bytes.
  1098. X *
  1099. X * This function returns NULL on I/O or size error.
  1100. X */
  1101. XFILE *
  1102. Xopen_build(filename)
  1103. X    char *filename;
  1104. X{
  1105. X    FILE *stream;        /* the opened file stream */
  1106. X    struct stat statbuf;    /* the status of the open file */
  1107. X
  1108. X    /*
  1109. X     * open the how to build input file
  1110. X     */
  1111. X    stream = fopen(filename, "r");
  1112. X    if (stream == NULL) {
  1113. X    fprintf(stderr, "%s: cannot open how to build file: %s: ",
  1114. X        program, filename);
  1115. X    perror("");
  1116. X    return(NULL);
  1117. X    }
  1118. X
  1119. X    /*
  1120. X     * determine the size of the file
  1121. X     */
  1122. X    if (fstat(fileno(stream), &statbuf) < 0) {
  1123. X    fprintf(stderr, "%s: cannot stat how to build file: %s: ",
  1124. X        program, filename);
  1125. X    perror("");
  1126. X    return(NULL);
  1127. X    }
  1128. X    if (statbuf.st_size > MAX_BUILD_SIZE) {
  1129. X    fprintf(stderr,
  1130. X        "%s: FATAL: the how to build file: %s, is %d bytes long\n",
  1131. X        program, filename, statbuf.st_size);
  1132. X    fprintf(stderr,
  1133. X        "%s:        it may not be longer than %d bytes\n",
  1134. X        program, MAX_BUILD_SIZE);
  1135. X    return(NULL);
  1136. X    }
  1137. X
  1138. X    /* return the open file */
  1139. X    return(stream);
  1140. X}
  1141. X
  1142. X/*
  1143. X * open_program - open/check the program source file
  1144. X *
  1145. X * The program source file must be <= 3217 bytes.  The number of
  1146. X * non-whitespace and }{; chars not followed by whitespace must
  1147. X * be <= 1536 bytes.
  1148. X *
  1149. X * This function returns NULL on I/O or size error.
  1150. X */
  1151. XFILE *
  1152. Xopen_program(filename)
  1153. X    char *filename;
  1154. X{
  1155. X    FILE *stream;        /* the opened file stream */
  1156. X    struct stat statbuf;    /* the status of the open file */
  1157. X    int count;            /* special count size */
  1158. X    int c;            /* the character read */
  1159. X
  1160. X    /*
  1161. X     * open the program source input file
  1162. X     */
  1163. X    stream = fopen(filename, "r");
  1164. X    if (stream == NULL) {
  1165. X    fprintf(stderr, "%s: cannot open program source file: %s: ",
  1166. X        program, filename);
  1167. X    perror("");
  1168. X    exit(7);
  1169. X    }
  1170. X
  1171. X    /*
  1172. X     * determine the size of the file
  1173. X     */
  1174. X    if (fstat(fileno(stream), &statbuf) < 0) {
  1175. X    fprintf(stderr, "%s: cannot stat program source file: %s: ",
  1176. X        program, filename);
  1177. X    perror("");
  1178. X    return(NULL);
  1179. X    }
  1180. X    if (statbuf.st_size > MAX_PROGRAM_SIZE) {
  1181. X    fprintf(stderr,
  1182. X        "%s: FATAL: the program source file: %s, is %d bytes long\n",
  1183. X        program, filename, statbuf.st_size);
  1184. X    fprintf(stderr,
  1185. X        "%s:        it may not be longer than %d bytes\n",
  1186. X        program, MAX_PROGRAM_SIZE);
  1187. X    return(NULL);
  1188. X    }
  1189. X
  1190. X    /*
  1191. X     * count the non-whitespace, non {}; followed by whitespace chars
  1192. X     */
  1193. X    count = 0;
  1194. X    c = 0;
  1195. X    while ((c=fgetc(stream)) != EOF) {
  1196. X    /* look at non-whitespace */
  1197. X    if (!isascii(c) || !isspace(c)) {
  1198. X        switch (c) {
  1199. X        case '{':        /* count if not followed by EOF or whitespace */
  1200. X        case '}':
  1201. X        case ';':
  1202. X        /* peek at next char */
  1203. X        c = fgetc(stream);
  1204. X        if (c != EOF && isascii(c) && !isspace(c)) {
  1205. X            /* not followed by whitespace or EOF, count it */
  1206. X            ungetc(c, stream);
  1207. X            ++count;
  1208. X        }
  1209. X        break;
  1210. X        default:
  1211. X        ++count;
  1212. X        break;
  1213. X        }
  1214. X    }
  1215. X    }
  1216. X
  1217. X    /* watch for I/O errors */
  1218. X    check_io(stream, filename, EOF_OK);
  1219. X
  1220. X    /* look at the special size */
  1221. X    if (count > MAX_PROGRAM_SIZE2) {
  1222. X    fprintf(stderr,
  1223. X        "%s: FATAL: the number of bytes that are non-whitespace, and\n",
  1224. X        program);
  1225. X    fprintf(stderr,
  1226. X        "%s:        that are not '{', '}', ';' followed by whitespace\n",
  1227. X        program);
  1228. X    fprintf(stderr,
  1229. X        "%s:        or EOF must be <= %d bytes\n",
  1230. X        program, MAX_PROGRAM_SIZE2);
  1231. X    fprintf(stderr,
  1232. X        "%s:        in %s, %d bytes were found\n",
  1233. X        program, filename, count);
  1234. X    return(NULL);
  1235. X    }
  1236. X
  1237. X    /* return the open file */
  1238. X    rewind(stream);
  1239. X    return(stream);
  1240. X}
  1241. X
  1242. X/*
  1243. X * open_output - open/check the entry output file
  1244. X *
  1245. X * This function returns NULL on open error.
  1246. X */
  1247. XFILE *
  1248. Xopen_output(filename)
  1249. X    char *filename;
  1250. X{
  1251. X    FILE *stream;        /* the opened file stream */
  1252. X
  1253. X    /*
  1254. X     * open the ioccc entry output file
  1255. X     */
  1256. X    stream = fopen(filename, "w");
  1257. X    if (stream == NULL) {
  1258. X    fprintf(stderr, "%s: cannot open ioccc entry file for output: %s: ",
  1259. X        program, filename);
  1260. X    perror("");
  1261. X    exit(8);
  1262. X    }
  1263. X
  1264. X    /* return the open file */
  1265. X    return(stream);
  1266. X}
  1267. X
  1268. X/*
  1269. X * output_entry - output the ---entry--- section
  1270. X *
  1271. X * Read the needed information form stdin, and write the entry section.
  1272. X */
  1273. Xvoid
  1274. Xoutput_entry(output, oname)
  1275. X    FILE *output;        /* entry's output file stream */
  1276. X    char *oname;        /* name of the output file */
  1277. X{
  1278. X    char title[MAX_TITLE_LEN+1+1];    /* the entry's title */
  1279. X    char buf[MAX_COL+1+1];        /* I/O buffer */
  1280. X    int entry=0;            /* entry number */
  1281. X    int ret;                /* fields processed by fscanf */
  1282. X    int ok_line=0;            /* 0 => the line is not ok */
  1283. X    char skip;                /* input to skip */
  1284. X    FILE *date_pipe;            /* pipe to a date command */
  1285. X    time_t epoch_sec;            /* seconds since the epoch */
  1286. X    char *p;
  1287. X
  1288. X    /*
  1289. X     * write the start of the section
  1290. X     */
  1291. X    fprintf(output, "---entry---\n");
  1292. X    check_io(output, oname, EOF_NOT_OK);
  1293. X
  1294. X    /*
  1295. X     * write the rule year
  1296. X     */
  1297. X    fprintf(output, "rule:\t%d\n", RULE_YEAR);
  1298. X    check_io(output, oname, EOF_NOT_OK);
  1299. X
  1300. X    /* determine if this is a fix */
  1301. X    printf("Is this a fix, update or resubmittion to a ");
  1302. X    printf("previous entry (enter y or n)? ");
  1303. X    while (get_line(buf, 1+1, 0) <= 0 || !(buf[0]=='y' || buf[0]=='n')) {
  1304. X    printf("\nplease answer y or n: ");
  1305. X    }
  1306. X    if (buf[0] == 'y') {
  1307. X    fprintf(output, "fix:\ty\n");
  1308. X    check_io(output, oname, EOF_NOT_OK);
  1309. X    printf("\nBe sure that the title and entry number that you give\n");
  1310. X    printf("are the same of as the entry you are replacing\n");
  1311. X    } else {
  1312. X    fprintf(output, "fix:\tn\n");
  1313. X    check_io(output, oname, EOF_NOT_OK);
  1314. X    }
  1315. X
  1316. X    /*
  1317. X     * write the title
  1318. X     */
  1319. X    printf("\nYour title must match expression be a [a-zA-Z0-9_=] character\n");
  1320. X    printf("followed by 0 to %d more [a-zA-Z0-9_=+-] characters.\n\n",
  1321. X    MAX_TITLE_LEN-1);
  1322. X    printf("It is suggested, but not required, that the title should\n");
  1323. X    printf("incorporate your username; in the\n");
  1324. X    printf("case of multiple authors, consider using parts of the usernames\n");
  1325. X    printf("of the authors.\n\n");
  1326. X    printf("enter your title: ");
  1327. X    do {
  1328. X    /* prompt and read a line */
  1329. X    if ((ok_line = get_line(title, MAX_TITLE_LEN+1, MAX_COL-9)) <= 0) {
  1330. X        printf("\ntitle is too long, please re-enter: ");
  1331. X        continue;
  1332. X    }
  1333. X
  1334. X    /* verify the pattern, not everyone has regexp, so do it by hand */
  1335. X    if (!isascii((int)title[0]) ||
  1336. X        !(isalnum((int)title[0]) || title[0] == '_' || title[0] == '=')) {
  1337. X        printf("\ninvalid first character in the title\n\n");
  1338. X        printf("enter your title: ");
  1339. X        ok_line = 0;
  1340. X    } else {
  1341. X        for (p=(&title[1]); *p != '\0' && *p != '\n'; ++p) {
  1342. X        if (!isascii((int)*p) ||
  1343. X            !(isalnum((int)*p) ||
  1344. X              *p == '_' || *p == '=' || *p == '+' || *p == '-')) {
  1345. X            printf("\ninvalid character in the title\n\n");
  1346. X            printf("enter your title: ");
  1347. X            ok_line = 0;
  1348. X        }
  1349. X        }
  1350. X    }
  1351. X    } while (ok_line <= 0);
  1352. X    fprintf(output, "title:\t%s", title);
  1353. X    check_io(output, oname, EOF_NOT_OK);
  1354. X
  1355. X    /*
  1356. X     * write the entry number
  1357. X     */
  1358. X    printf("\nEach person may submit up to %d entries per year.\n\n",
  1359. X    MAX_ENTRY);
  1360. X    printf("enter an entry number from 0 to %d inclusive: ", MAX_ENTRY-1);
  1361. X    do {
  1362. X    /* get a valid input line */
  1363. X    fflush(stdout);
  1364. X    ret = fscanf(stdin, "%d[\n]", &entry);
  1365. X    check_io(stdin, "stdin", EOF_NOT_OK);
  1366. X    /* skip over input until newline is found */
  1367. X    do {
  1368. X        skip = fgetc(stdin);
  1369. X        check_io(stdin, "stdin", EOF_NOT_OK);
  1370. X        if (skip != '\n') {
  1371. X        /* bad text in input, invalidate entry number */
  1372. X        entry = -1;
  1373. X        }
  1374. X    } while (skip != '\n');
  1375. X
  1376. X    /* check if we have a number, and if it is in range */
  1377. X    if (ret != 1 || entry < 0 || entry > MAX_ENTRY-1) {
  1378. X        printf(
  1379. X          "\nThe entry number must be between 0 and %d inclusive\n\n",
  1380. X        MAX_ENTRY-1);
  1381. X        printf("enter the entry number: ");
  1382. X    }
  1383. X    } while (ret != 1 || entry < 0 || entry > MAX_ENTRY-1);
  1384. X    fprintf(output, "entry:\t%d\n", entry);
  1385. X    check_io(output, oname, EOF_NOT_OK);
  1386. X
  1387. X    /*
  1388. X     * write the submission date
  1389. X     */
  1390. X    /* returns a newline */
  1391. X    epoch_sec = time(NULL);
  1392. X    fprintf(output, "date:\t%s", asctime(gmtime(&epoch_sec)));
  1393. X    check_io(output, oname, EOF_NOT_OK);
  1394. X
  1395. X    /*
  1396. X     * write the OS/machine host information
  1397. X     */
  1398. X    printf(
  1399. X      "\nEnter the machine(s) and OS(s) under which your entry was tested.\n");
  1400. X    output_till_dot(output, oname, "host:");
  1401. X}
  1402. X
  1403. X/*
  1404. X * output_remark - output the ---remark--- section
  1405. X *
  1406. X * Read the needed information form stdin, and write the entry section.
  1407. X */
  1408. Xvoid
  1409. Xoutput_remark(output, oname, remark, rname)
  1410. X    FILE *output;        /* entry's output file stream */
  1411. X    char *oname;        /* name of the output file */
  1412. X    FILE *remark;        /* stream to the file containing remark text */
  1413. X    char *rname;        /* name of the remark file */
  1414. X{
  1415. X    char buf[BUFSIZ+1];        /* input/output buffer */
  1416. X
  1417. X    /*
  1418. X     * write the start of the section
  1419. X     */
  1420. X    fprintf(output, "---remark---\n");
  1421. X    check_io(output, oname, EOF_NOT_OK);
  1422. X
  1423. X    /*
  1424. X     * copy the remark file to the section
  1425. X     */
  1426. X    while (fgets(buf, BUFSIZ, remark) != NULL) {
  1427. X    fputs(buf, output);
  1428. X    check_io(output, oname, EOF_NOT_OK);
  1429. X    }
  1430. X    check_io(remark, rname, EOF_OK);
  1431. X
  1432. X    /* be sure that the remark section ends with a newline */
  1433. X    if (buf[strlen(buf)-1] != '\n') {
  1434. X    fputc('\n', output);
  1435. X    check_io(output, oname, EOF_NOT_OK);
  1436. X    }
  1437. X}
  1438. X
  1439. X/*
  1440. X * output_author - output the ---author--- section
  1441. X *
  1442. X * Read the needed information from stdin, and write the author section.
  1443. X * If multiple authors exist, multiple author sections will be written.
  1444. X */
  1445. Xvoid
  1446. Xoutput_author(output, oname)
  1447. X    FILE *output;        /* entry's output file stream */
  1448. X    char *oname;        /* name of the output file */
  1449. X{
  1450. X    char buf[MAX_COL+1+1];    /* I/O buffer */
  1451. X    int more_auths;        /* TRUE => more authors to note */
  1452. X    int auth_cnt=0;        /* number of authors processed */
  1453. X
  1454. X    /*
  1455. X     * prompt the user for the author section
  1456. X     */
  1457. X    printf("\nEnter information about each author.  If your entry is after\n");
  1458. X    printf("%s and before the contest deadline, the judges\n", START_DATE);
  1459. X    printf("will attempt to Email back a confirmation to the first author\n");
  1460. X
  1461. X    /*
  1462. X     * place author information for each author in an individual section
  1463. X     */
  1464. X    do {
  1465. X
  1466. X    /* write the start of the section */
  1467. X    fprintf(output, "---author---\n");
  1468. X    check_io(output, oname, EOF_NOT_OK);
  1469. X
  1470. X    /* write the author */
  1471. X    printf("\nAuthor #%d name: ", ++auth_cnt);
  1472. X    while (get_line(buf, MAX_COL+1, MAX_COL-9) <= 0) {
  1473. X        printf("\nname too long, please re-enter: ");
  1474. X    }
  1475. X    fprintf(output, "name:\t%s", buf);
  1476. X    check_io(output, oname, EOF_NOT_OK);
  1477. X
  1478. X    /* write the organization */
  1479. X    printf("\nEnter the School/Company/Organization of author #%d\n",
  1480. X        auth_cnt);
  1481. X    printf("\nAuthor #%d org: ", auth_cnt);
  1482. X    while (get_line(buf, MAX_COL+1, MAX_COL-9) <= 0) {
  1483. X        printf("\nline too long, please re-enter: ");
  1484. X    }
  1485. X    fprintf(output, "org:\t%s", buf);
  1486. X    check_io(output, oname, EOF_NOT_OK);
  1487. X
  1488. X    /* write the address */
  1489. X    printf(
  1490. X        "\nEnter the postal address for author #%d.  Be sure to include\n",
  1491. X        auth_cnt);
  1492. X    printf("your country and do not include your name.\n");
  1493. X    output_till_dot(output, oname, "addr:");
  1494. X
  1495. X    /* write the Email address */
  1496. X    printf(
  1497. X        "\nEnter the Email address for author #%d.  Use an address from\n",
  1498. X        auth_cnt);
  1499. X    printf(
  1500. X        "a registered domain or well known site.  If you give several\n");
  1501. X    printf("forms, list them one per line.\n");
  1502. X    output_till_dot(output, oname, "email:");
  1503. X
  1504. X    /* write the anonymous status */
  1505. X    printf("\nShould author #%d remain anonymous (enter y or n)? ",
  1506. X        auth_cnt);
  1507. X    while (get_line(buf, 1+1, 0) <= 0 || !(buf[0]=='y' || buf[0]=='n')) {
  1508. X        printf("\nplease answer y or n: ");
  1509. X    }
  1510. X    fprintf(output, "anon:\t%s", buf);
  1511. X    check_io(output, oname, EOF_NOT_OK);
  1512. X
  1513. X    /* determine if there is another author */
  1514. X    printf("\nIs there another author (enter y or n)? ");
  1515. X    while (get_line(buf, 1+1, 0) <= 0 || !(buf[0]=='y' || buf[0]=='n')) {
  1516. X        printf("\nplease answer y or n: ");
  1517. X    }
  1518. X    if (buf[0] == 'y') {
  1519. X        more_auths = TRUE;
  1520. X    } else {
  1521. X        more_auths = FALSE;
  1522. X    }
  1523. X    } while (more_auths == TRUE);
  1524. X    return;
  1525. X}
  1526. X
  1527. X/*
  1528. X * output_info - output the ---info--- section(s)
  1529. X *
  1530. X * Read the needed information from stdin, and write the info section.
  1531. X * If multiple info files exist, multiple info sections will be written.
  1532. X */
  1533. Xvoid
  1534. Xoutput_info(output, oname)
  1535. X    FILE *output;        /* entry's output file stream */
  1536. X    char *oname;        /* name of the output file */
  1537. X{
  1538. X    char infoname[MAX_FILE_LEN+1];    /* filename buffer */
  1539. X    char yorn[1+1];        /* y or n answer */
  1540. X    char *uuname;        /* name to uuencode as */
  1541. X    FILE *infile;        /* info file stream */
  1542. X
  1543. X    /*
  1544. X     * prompt the user for info information
  1545. X     */
  1546. X    printf("\nInfo files should be used only to supplement your entry.\n");
  1547. X    printf("For example, info files may provide sample input or detailed\n");
  1548. X    printf("information about your entry.  Because they are supplemental,\n");
  1549. X    printf("the entry should not require them to exist.\n\n");
  1550. X
  1551. X    /*
  1552. X     * while there is another info file to save, uuencode it
  1553. X     */
  1554. X    printf("Do you have a info file to include (enter y or n)? ");
  1555. X    while (get_line(yorn, 1+1, 0) <= 0 || !(yorn[0]=='y' || yorn[0]=='n')) {
  1556. X    printf("\nplease answer y or n: ");
  1557. X    }
  1558. X    while (yorn[0] == 'y') {
  1559. X
  1560. X    /* read the filename */
  1561. X    printf("\nEnter the info filename: ");
  1562. X    while (get_line(infoname, MAX_FILE_LEN+1, 0) <= 0) {
  1563. X        printf("\nInfo filename too long, please re-enter: ");
  1564. X    }
  1565. X
  1566. X    /* compute the basename of the info filename */
  1567. X    /* remove the trailing newline */
  1568. X    uuname = &infoname[strlen(infoname)-1];
  1569. X    *uuname = '\0';
  1570. X    /* avoid rindex/shrrchr compat issues, do it by hand */
  1571. X    for (--uuname; uuname > infoname; --uuname) {
  1572. X        if (*uuname == '/') {
  1573. X        ++uuname;
  1574. X        break;
  1575. X        }
  1576. X    }
  1577. X
  1578. X    /* attempt to open the info file */
  1579. X    infile = fopen(infoname, "r");
  1580. X    if (infile == NULL) {
  1581. X        fprintf(stderr, "\n%s: cannot open info file: %s: ",
  1582. X        program, infoname);
  1583. X        perror("");
  1584. X        continue;
  1585. X    }
  1586. X
  1587. X    /*
  1588. X     * write the start of the section
  1589. X     */
  1590. X    fprintf(output, "---info---\n");
  1591. X    check_io(output, oname, EOF_NOT_OK);
  1592. X
  1593. X    /* uuencode the info file */
  1594. X    uuencode(output, oname, infile, infoname, UUINFO_MODE, uuname);
  1595. X
  1596. X    printf("\nDo you have another info file to include (enter y or n)? ");
  1597. X    while (get_line(yorn, 1+1, 0) <= 0 || !(yorn[0]=='y' || yorn[0]=='n')) {
  1598. X        printf("\nplease answer y or n: ");
  1599. X    }
  1600. X    };
  1601. X    return;
  1602. X}
  1603. X
  1604. X/*
  1605. X * output_build - output the ---build--- section
  1606. X *
  1607. X * Read the needed information from stdin, and write the build section.
  1608. X */
  1609. Xvoid
  1610. Xoutput_build(output, oname, build, bname)
  1611. X    FILE *output;        /* entry's output file stream */
  1612. X    char *oname;        /* name of the output file */
  1613. X    FILE *build;        /* open build file stream */
  1614. X    char *bname;        /* name of the build file */
  1615. X{
  1616. X    /*
  1617. X     * write the start of the section
  1618. X     */
  1619. X    fprintf(output, "---build---\n");
  1620. X    check_io(output, oname, EOF_NOT_OK);
  1621. X
  1622. X    /*
  1623. X     * uuencode the program file
  1624. X     */
  1625. X    uuencode(output, oname, build, bname, UUBUILD_MODE, UUBUILD_NAME);
  1626. X    return;
  1627. X}
  1628. X
  1629. X/*
  1630. X * output_program - output the ---program--- section
  1631. X *
  1632. X * Read the needed information form stdin, and write the program section.
  1633. X */
  1634. Xvoid
  1635. Xoutput_program(output, oname, prog, pname)
  1636. X    FILE *output;        /* entry's output file stream */
  1637. X    char *oname;        /* name of the output file */
  1638. X    FILE *prog;            /* open program stream */
  1639. X    char *pname;        /* name of program file */
  1640. X{
  1641. X    /*
  1642. X     * write the start of the section
  1643. X     */
  1644. X    fprintf(output, "---program---\n");
  1645. X    check_io(output, oname, EOF_NOT_OK);
  1646. X
  1647. X    /*
  1648. X     * uuencode the program file
  1649. X     */
  1650. X    uuencode(output, oname, prog, pname, UUPROG_MODE, UUPROG_NAME);
  1651. X    return;
  1652. X}
  1653. X
  1654. X/*
  1655. X * output_end - output the ---end--- section
  1656. X *
  1657. X * Read the needed information form stdin, and write the 'end section'.
  1658. X */
  1659. Xvoid
  1660. Xoutput_end(output, oname)
  1661. X    FILE *output;        /* entry's output file stream */
  1662. X    char *oname;        /* name of the output file */
  1663. X{
  1664. X    /*
  1665. X     * write the final section terminator
  1666. X     */
  1667. X    fprintf(output, "---end---\n");
  1668. X    check_io(output, oname, EOF_NOT_OK);
  1669. X    return;
  1670. X}
  1671. X
  1672. X/*
  1673. X * get_line - get an answer from stdin
  1674. X *
  1675. X * This function will flush stdout, in case a prompt is pending, and
  1676. X * read in the answer.
  1677. X *
  1678. X * This function returns 0 if the line is too long, of the length of the
  1679. X * line (including the newline) of the line was ok.  This function does
  1680. X * not return if ERROR or EOF.
  1681. X */
  1682. Xint
  1683. Xget_line(buf, siz, maxcol)
  1684. X    char *buf;            /* input buffer */
  1685. X    int siz;            /* length of input, including the newline */
  1686. X    int maxcol;            /* max col allowed, 0 => disable check */
  1687. X{
  1688. X    int length;            /* the length of the input line */
  1689. X
  1690. X    /* flush terminal output */
  1691. X    fflush(stdout);
  1692. X
  1693. X    /* read the line */
  1694. X    if (fgets(buf, siz+1, stdin) == NULL) {
  1695. X    /* report the problem */
  1696. X    check_io(stdin, "stdin", EOF_NOT_OK);
  1697. X    }
  1698. X
  1699. X    /* look for the newline */
  1700. X    length = strlen(buf);
  1701. X    if (buf[length-1] != '\n') {
  1702. X    int eatchar;        /* the char being eaten */
  1703. X
  1704. X    /* no newline found, line must be too long, eat the rest of the line */
  1705. X    do {
  1706. X        eatchar = fgetc(stdin);
  1707. X    } while (eatchar != EOF && eatchar != '\n');
  1708. X    check_io(stdin, "stdin", EOF_NOT_OK);
  1709. X
  1710. X    /* report the situation */
  1711. X    return 0;
  1712. X    }
  1713. X
  1714. X    /* watch for long lines, if needed */
  1715. X    if (maxcol > 0 && (length > maxcol || col_len(buf) > maxcol)) {
  1716. X    /* report the situation */
  1717. X    return 0;
  1718. X    }
  1719. X
  1720. X    /* return length */
  1721. X    return length;
  1722. X}
  1723. X
  1724. X/*
  1725. X * output_till_dot - output a set of lines until '.' by itself is read
  1726. X *
  1727. X * This routine will read a set of lines until (but not including)
  1728. X * a single line with '.' is read.  The format of the output is:
  1729. X *
  1730. X *    leader:\tfirst line
  1731. X *    \tnext line
  1732. X *    \tnext line
  1733. X *       ...
  1734. X *
  1735. X * This routine will not return if I/O error or EOF.
  1736. X */
  1737. Xvoid
  1738. Xoutput_till_dot(output, oname, leader)
  1739. X    FILE *output;        /* entry's output file stream */
  1740. X    char *oname;        /* name of the output file */
  1741. X    char *leader;        /* the lead text for the first line */
  1742. X{
  1743. X    char buf[BUFSIZ+1];        /* input buffer */
  1744. X    int count;            /* lines read */
  1745. X    int done=FALSE;        /* TRUE => finished reading input */
  1746. X
  1747. X    /* instruct the user on how to input */
  1748. X    printf("\nTo end input, enter a line with a single period.\n");
  1749. X
  1750. X    /* read lines until '.' or EOF */
  1751. X    count = 0;
  1752. X    while (!done) {
  1753. X    /* issue the prompt */
  1754. X    printf("%s\t", (count>0) ? "" : leader);
  1755. X    fflush(stdout);
  1756. X
  1757. X    /* get the line */
  1758. X    if (get_line(buf, BUFSIZ, MAX_COL-9) <= 0) {
  1759. X        printf("\nline too long, please re-enter:\n\t");
  1760. X        continue;
  1761. X    }
  1762. X
  1763. X    /* note if '.' was read */
  1764. X    if (strcmp(buf, ".\n") == 0) {
  1765. X        done = TRUE;
  1766. X    }
  1767. X
  1768. X    /* write line if we read something */
  1769. X    if (!done) {
  1770. X        fprintf(output, "%s\t%s", (count++>0) ? "" : leader, buf);
  1771. X        check_io(output, oname, EOF_NOT_OK);
  1772. X    }
  1773. X    }
  1774. X
  1775. X    /* if no lines read, at least output something */
  1776. X    if (count <= 0) {
  1777. X    fprintf(output, "%s\t.\n", leader);
  1778. X    check_io(output, oname, EOF_NOT_OK);
  1779. X    }
  1780. X    return;
  1781. X}
  1782. X
  1783. X/*
  1784. X * col_len - determine the highest that a string would reach
  1785. X *
  1786. X * Given a string, this routine returns that a string would reach
  1787. X * if the string were printed at column 1.  Tab stops are assumed
  1788. X * to start at 9, 17, 25, 33, ...
  1789. X */
  1790. Xint
  1791. Xcol_len(string)
  1792. X    char *string;        /* the string to examine */
  1793. X{
  1794. X    int col;    /* current column */
  1795. X    char *p;    /* current char */
  1796. X
  1797. X    /* scan the string */
  1798. X    for (col=0, p=string; *p != '\0' && *p != '\n'; ++p) {
  1799. X    /* note the column shift */
  1800. X    col = (*p=='\t') ? 1+((col+8)/8*8) : col+1;
  1801. X    }
  1802. X    if (*p == '\n') {
  1803. X    --col;
  1804. X    }
  1805. X
  1806. X    /* return the highest column */
  1807. X    return col;
  1808. X}
  1809. X
  1810. X/*
  1811. X * check_io - check for EOF or I/O error on a stream
  1812. X *
  1813. X * Does not return if EOF or I/O error.
  1814. X */
  1815. Xvoid
  1816. Xcheck_io(stream, name, eof_ok)
  1817. X    FILE *stream;        /* the stream to check */
  1818. X    char *name;            /* the name of this stream */
  1819. X    int eof_ok;            /* EOF_OK or EOF_NOT_OK */
  1820. X{
  1821. X    /* test for I/O error */
  1822. X    if (ferror(stream)) {
  1823. X    fprintf(stderr, "%s: error on %s: ", program, name);
  1824. X    perror("");
  1825. X    exit(1);
  1826. X
  1827. X    /* test for EOF */
  1828. X    } else if (eof_ok == EOF_NOT_OK && feof(stream)) {
  1829. X    fprintf(stderr, "%s: EOF on %s\n", program, name);
  1830. X    exit(1);
  1831. X    }
  1832. X    return;
  1833. X}
  1834. X
  1835. X/*
  1836. X * uuencode - uuencode a file
  1837. X *
  1838. X * Perform the uuencoding process identical to the process performed
  1839. X * by the uuencode(1) utility.
  1840. X *
  1841. X * This routine implements the algorithm described in the uuencode(5)
  1842. X * 4.3BSD Reno man page.
  1843. X */
  1844. Xvoid
  1845. Xuuencode(output, oname, infile, iname, umode, uname)
  1846. X    FILE *output;        /* output file stream */
  1847. X    char *oname;        /* output filename */
  1848. X    FILE *infile;        /* input file stream */
  1849. X    char *iname;        /* input filename */
  1850. X    int umode;            /* the mode to put on the uuencode file */
  1851. X    char *uname;        /* name to put on the uuencode file */
  1852. X{
  1853. X    char buf[UUENCODE_LEN+1];    /* the uuencode buffer */
  1854. X    int read_len;        /* actual number of chars read */
  1855. X    int val;            /* 6 bit chunk from buf */
  1856. X    char filler='\0';        /* filler uuencode pad text */
  1857. X    char *p;
  1858. X
  1859. X    /*
  1860. X     * output the initial uuencode header
  1861. X     */
  1862. X    fprintf(output, "begin %o %s\n", umode, uname);
  1863. X    check_io(output, oname, EOF_NOT_OK);
  1864. X
  1865. X    /*
  1866. X     * clear out the input buffer
  1867. X     */
  1868. X    for (p=buf; p < &buf[sizeof(buf)/sizeof(buf[0])]; ++p) {
  1869. X    *p = '\0';
  1870. X    }
  1871. X
  1872. X    /*
  1873. X     * We will process UUENCODE_LEN chars at a time, forming
  1874. X     * a single output line each time.
  1875. X     */
  1876. X    while ((read_len=fread(buf,sizeof(buf[0]),UUENCODE_LEN,infile)) > 0) {
  1877. X
  1878. X    /*
  1879. X     * the first character is the length character
  1880. X     */
  1881. X    fputc(UUENCODE(read_len), output);
  1882. X    check_io(output, oname, EOF_NOT_OK);
  1883. X
  1884. X    /*
  1885. X     * We will convert 24 bits at a time.  Thus we will convert
  1886. X     * 3 sets of 8 bits into 4 sets of uuencoded 6 bits.
  1887. X     */
  1888. X    for (p=buf; read_len>0; read_len-=3, p+=3) {
  1889. X
  1890. X        /* bits 0 to 5 */
  1891. X        val = (p[0]>>2)&0x3f;
  1892. X        fputc(UUENCODE(val), output);
  1893. X        check_io(output, oname, EOF_NOT_OK);
  1894. X
  1895. X        /* bits 6 to 11 */
  1896. X        val = ((p[0]<<4)&0x30) | ((p[1]>>4)&0x0f);
  1897. X        fputc(UUENCODE(val), output);
  1898. X        check_io(output, oname, EOF_NOT_OK);
  1899. X
  1900. X        /* bits 12 to 17 */
  1901. X        val = ((p[1]<<2)&0x3c) | ((p[2]>>6)&0x03);
  1902. X        fputc(UUENCODE(val), output);
  1903. X        check_io(output, oname, EOF_NOT_OK);
  1904. X
  1905. X        /* bits 18 to 23 */
  1906. X        val = p[2]&0x3f;
  1907. X        fputc(UUENCODE(val), output);
  1908. X        check_io(output, oname, EOF_NOT_OK);
  1909. X    }
  1910. X
  1911. X    /* end of UUENCODE_LEN line */
  1912. X    fputc('\n', output);
  1913. X    check_io(output, oname, EOF_NOT_OK);
  1914. X
  1915. X    /*
  1916. X     * clear out the input buffer  (don't depend on bzero() or memset())
  1917. X     */
  1918. X    for (p=buf; p < &buf[sizeof(buf)/sizeof(buf[0])]; ++p) {
  1919. X        *p = '\0';
  1920. X    }
  1921. X    }
  1922. X
  1923. X    /* check the last read on the input file */
  1924. X    check_io(infile, iname, EOF_OK);
  1925. X
  1926. X    /* write end of uuencode file */
  1927. X    fprintf(output, "%c\nend\n", UUENCODE(filler));
  1928. X    check_io(output, oname, EOF_NOT_OK);
  1929. X}
  1930. END_OF_FILE
  1931.   if test 34486 -ne `wc -c <'1993/mkentry.c'`; then
  1932.     echo shar: \"'1993/mkentry.c'\" unpacked with wrong size!
  1933.   fi
  1934.   # end of '1993/mkentry.c'
  1935. fi
  1936. echo shar: End of archive 1 \(of 4\).
  1937. cp /dev/null ark1isdone
  1938. MISSING=""
  1939. for I in 1 2 3 4 ; do
  1940.     if test ! -f ark${I}isdone ; then
  1941.     MISSING="${MISSING} ${I}"
  1942.     fi
  1943. done
  1944. if test "${MISSING}" = "" ; then
  1945.     echo You have unpacked all 4 archives.
  1946.     rm -f ark[1-9]isdone
  1947. else
  1948.     echo You still must unpack the following archives:
  1949.     echo "        " ${MISSING}
  1950. fi
  1951. exit 0
  1952. exit 0 # Just in case...
  1953.