home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / lang / c / 13352 < prev    next >
Encoding:
Internet Message Format  |  1992-09-08  |  42.9 KB

  1. Xref: sparky comp.lang.c:13352 comp.sources.d:1251 comp.unix.wizards:3851 alt.sources:2021 misc.misc:3276
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!ucbvax!hoptoad!chongo
  3. From: chongo@hoptoad.uucp (Landon C. Noll)
  4. Newsgroups: comp.lang.c,comp.sources.d,comp.unix.wizards,alt.sources,misc.misc
  5. Subject: 1992 International Obfuscated C Code Contest winners, 2 of 4
  6. Keywords: ioccc
  7. Message-ID: <34849@hoptoad.uucp>
  8. Date: 9 Sep 92 01:40:13 GMT
  9. Expires: 28 Nov 92 00:00:00 GMT
  10. Reply-To: chongo@hoptoad.UUCP (Landon C. Noll)
  11. Organization: Nebula Consultants in San Francisco
  12. Lines: 1572
  13.  
  14. Submitted-by: chongo@toad.com (Landon Curt Noll)
  15. #
  16. # Send comments, questions, bugs to: 
  17. #
  18. #    judges@toad.com   -or-   ...!{sun,uunet,utzoo,pyramid}!hoptoad!judges
  19. #
  20. # You are strongly encouraged to read the new contest rules before
  21. # sending any entries.  The rules, and sometimes the contest Email
  22. # address itself, change over time.  A valid entry one year may
  23. # be rejected in a later year due to changes in the rules.  The typical
  24. # start date for a contest is early March.  The typical end date for a
  25. # contest is early May.
  26. #
  27. # The contest rules are posted to comp.unix.wizards, comp.lang.c,
  28. # misc.misc, alt.sources and comp.sources.d.  If you do not have access 
  29. # to these groups, or if you missed the early March posting, you may 
  30. # request a copy from the judges, via Email, at the address above.
  31. #
  32. Archive-name: ioccc.1992/part02
  33.  
  34. ---- Cut Here and unpack ----
  35. #!/bin/sh
  36. # This is part 02 of ioccc.1992
  37. if touch 2>&1 | fgrep 'amc' > /dev/null
  38.  then TOUCH=touch
  39.  else TOUCH=true
  40. fi
  41. # ============= 1992/albert.c ==============
  42. echo "x - extracting 1992/albert.c (Text)"
  43. sed 's/^X//' << 'SHAR_EOF' > 1992/albert.c &&
  44. X#include <stdio.h>
  45. X#include <malloc.h>
  46. X#include <setjmp.h>
  47. X#include <ctype.h>
  48. X#define new(PP) (PP *) malloc(sizeof(PP)) 
  49. Xtypedef struct q {
  50. X    jmp_buf ppp;
  51. X    long qq;
  52. X    struct q *P;
  53. X    struct q *p;
  54. X} 
  55. XPP;
  56. X
  57. XPP *P;
  58. Xint aaaaaa=2;
  59. Xint aaaaaaa=1;
  60. X
  61. Xlong qqq;
  62. X
  63. X
  64. XaaAaaa(aa,aaa)
  65. Xchar *aa;
  66. Xchar *aaa;
  67. X{
  68. X    char aaaa = 0;
  69. X    if ((((( aaa )))))
  70. X    {
  71. X        aaaa = *aa;
  72. X        *aa=0;
  73. X        aa+=strlen(aa+1);
  74. X        P =new(PP);
  75. X        P->P=P;
  76. X        P->p=P;
  77. X    }
  78. X
  79. X    if ((((( !setjmp(P->ppp) ))))) 
  80. X        {
  81. X        if ((((( !isdigit(*aa) )))))
  82. X            longjmp(P->ppp,aaaaaaa);
  83. X        else {
  84. X            P->p->P = new(PP);
  85. X            P->p->P->P = P;
  86. X            P->p->P->p = P->p;
  87. X            P->p = P->p->P;
  88. X
  89. X            P->qq = *aa--;
  90. X            P = P->p;
  91. X            aaAaaa(aa,0);
  92. X        }
  93. X    } else {
  94. X        if ( !aaaa&&!*aa ) 
  95. X           longjmp(P->p->ppp,aaaaaaa);
  96. X
  97. X        if ((((( (P->qq=aaaa)<10     &&!
  98. X                 (isdigit(aaaa))     ||!
  99. X                 (isdigit(*aa)       ||!
  100. X                 *aa                        )))))) 
  101. X        {
  102. X            fprintf(stderr,"Usage %c%s <number>\n",
  103. X            (aaa[0]?7:aaaa),aaa+!aaa[0]);
  104. X            exit(1);
  105. X        }
  106. X    }
  107. X}
  108. X
  109. X
  110. XppPppp(pp,ppp)
  111. XPP **pp, *ppp;
  112. X{
  113. X    int aa;
  114. X    if ((((( !(aa=setjmp(ppp->ppp))||aa==aaaaaa )))))
  115. X    {
  116. X        if ((((( *pp==ppp )))))
  117. X        {
  118. X            ppp = (*pp)->p;
  119. X
  120. X            if ( qqq<47 ) return;
  121. X            if ( ppp->qq!=48 ) return;
  122. X
  123. X            while ( ppp->qq==48 ) 
  124. X            {
  125. X                printf("%ld\n",qqq-45);
  126. X                *pp = ppp;
  127. X                ppp = ppp->p;
  128. X            }
  129. X            qqq -= 1;
  130. X            longjmp(ppp->ppp,aaaaaaa);
  131. X        } else {
  132. X            PP *p;
  133. X
  134. X            ppPppp(pp,ppp->p);
  135. X            for (p=ppp;p!=*pp;p=p->p)
  136. X            {
  137. X                int qq=4;
  138. X                if ((((( qqq<47                            &&
  139. X                         (qq=0,p->qq+=p->p->qq-96)>=48-qqq ||
  140. X                         qqq>46                            &&
  141. X                         (p->qq-=p->p->qq)<0                   ))))) 
  142. X                {
  143. X                    p->qq += qqq+qq;
  144. X                    if ( p->p==P && qqq<=46 )
  145. X                    {
  146. X                        P->p->P = new(PP);
  147. X                        P->p->P->P = P;
  148. X                        P->p->P->p = P->p;
  149. X                        *pp = P = P->p = P->p->P;
  150. X                        P->qq = 48;
  151. X                    }
  152. X
  153. X                    p->p->qq+=qq==0;
  154. X                    p->p->qq-=qq!=0;
  155. X                }
  156. X                else
  157. X                {
  158. X                    p->qq += 48;
  159. X                }
  160. X            }
  161. X            if ( ppp->P==P ) longjmp(ppp->ppp,aaaaaaa);
  162. X        }
  163. X    }
  164. X    else
  165. X    {
  166. X        qqq += 1; 
  167. X
  168. X        while (48==P->qq )
  169. X        {
  170. X            P->P->p = P->p;
  171. X            P = P->p->P = P->P;
  172. X
  173. X        }
  174. X
  175. X        if ( ppp!=ppp->p->p || qqq<47 )
  176. X            longjmp(ppp->ppp,aaaaaa);
  177. X        else
  178. X        {
  179. X            printf("At most one remains\n");
  180. X            exit(0);
  181. X        }
  182. X    }
  183. X}
  184. X
  185. X
  186. Xmain(aaa,aaaa)
  187. Xint aaa;
  188. Xchar **aaaa;
  189. X{
  190. X    aaAaaa(aaa==aaaaaaa?aaaa[0]:aaaa[1],aaaa[0]);
  191. X    qqq = 39;
  192. X    ppPppp(&P,P->p);
  193. X}
  194. X
  195. X
  196. SHAR_EOF
  197. $TOUCH -am 0817110092 1992/albert.c &&
  198. chmod 0444 1992/albert.c ||
  199. echo "restore of 1992/albert.c failed"
  200. set `wc -c 1992/albert.c`;Wc_c=$1
  201. if test "$Wc_c" != "3164"; then
  202.     echo original size 3164, current size $Wc_c
  203. fi
  204. # ============= 1992/albert.hint ==============
  205. echo "x - extracting 1992/albert.hint (Text)"
  206. sed 's/^X//' << 'SHAR_EOF' > 1992/albert.hint &&
  207. XMost Useful Program: <albert%bsovax@sun4nl.nluug.nl> Albert van der Horst
  208. X
  209. X    Albert van der Horst
  210. X    S P&A R&C
  211. X    Oranjestraat 8
  212. X    3511 RA   UTRECHT
  213. X    The Netherlands
  214. X
  215. X
  216. XJudges' comments:
  217. X
  218. X    For a canned example:
  219. X    make albert
  220. X    albert 1234567890123456789
  221. X    
  222. X    We were impressed with the speed at which it was able to factor
  223. X    arbitrarily large numbers consisting of factors that fit into
  224. X    a long.
  225. X
  226. X
  227. XSelected notes from the author:
  228. X
  229. X    The Obfuscated version of the Horst algorithm.
  230. X
  231. X    This program will factor unlimited length numbers and print the 
  232. X    factors in ascending order. Numbers of one digit (e.g. 8) 
  233. X    are rejected without notice.
  234. X    It quits as soon as there is at most one
  235. X    factor left, but that factor will not be shown. 
  236. X    It accomplishes this efficiently, without resorting to division
  237. X    or multiplication, until the candidate factor no longer fits in 
  238. X    a signed long. 
  239. X
  240. X    The nicest way is to rename the program into e.g. 4294967297
  241. X    if you want to factor Fermat's 4th number. Then just run it.
  242. X    Or you may type "prog <some-number>"
  243. X    A nice one is also (30 ones)
  244. X    albert 111111111111111111111111111111
  245. X
  246. X    Apart from the foregoing there are no special execution instructions.
  247. X
  248. X    To customize the program into a factorizer of a fixed number, use
  249. X    cc albert.c -o 4294967297
  250. X    or some such.
  251. X
  252. X    There are no data files used, and it is not possible to feed input
  253. X    via stdin.
  254. X
  255. X    I think this program is a nice example of algorithmic obfuscation.
  256. X    Several times two similar algorithms are merged into one. Then you 
  257. X    need quite some tricks to get it running, such as long jumps 
  258. X    through recursive subroutines. I felt like a sword smith, 
  259. X    welding the sword very long, folding it again to the proper 
  260. X    length, keep on hammering till it is tight, then fold again.
  261. X    Always keeping it at the proper red hot temperature, but not too
  262. X    hot lest the hardness fades.
  263. X    The strict naming conventions for subroutines did not make things 
  264. X    much clearer after all, but it was not supposed to.
  265. X
  266. X    I would like to draw attention to the robustness of the program
  267. X    with respect to error handling and the nice stopping criterion.
  268. X    The esthetic appeal of some lines is at the expense of clearness, 
  269. X    I apologize.
  270. X    Running the program through the c-beautifier reveals nothing,
  271. X    it will only destroy some of the lay out.
  272. X    Running the program through lint shows the usual remarks for a
  273. X    K&R program. Defeating this through casts does not make a program 
  274. X    cleaner in my opinion.
  275. X
  276. X    Here are some hints, but they may not be too helpful.
  277. X    1. The Horst algorithm is described in the Hobby Computer Club 
  278. X    Newsletter, year 82, part 4, a real Dutch treat.
  279. X       Assembler, c and Forth version have been around for some years.
  280. X    2. Does fractal programming exist after all?
  281. X    3. You remember the ToomCook algorithm in Knuth?
  282. X       It uses iteration instead of recursion and is quite jumpy.
  283. X       This program shares these disadvantages in a modified form.
  284. X    4. The Conversion is to be found in Knuth, not so the Observation.
  285. X       The Observation: "if it ends in a zero, it is divisible by ten"
  286. SHAR_EOF
  287. $TOUCH -am 0908160292 1992/albert.hint &&
  288. chmod 0444 1992/albert.hint ||
  289. echo "restore of 1992/albert.hint failed"
  290. set `wc -c 1992/albert.hint`;Wc_c=$1
  291. if test "$Wc_c" != "3193"; then
  292.     echo original size 3193, current size $Wc_c
  293. fi
  294. # ============= 1992/albert.orig.c ==============
  295. echo "x - extracting 1992/albert.orig.c (Text)"
  296. sed 's/^X//' << 'SHAR_EOF' > 1992/albert.orig.c &&
  297. X#include <stdio.h>
  298. X#include <malloc.h>
  299. X#include <setjmp.h>
  300. X#include <ctype.h>
  301. X#define new(PP) (PP *) malloc(sizeof(PP)) 
  302. Xtypedef struct q {
  303. X    jmp_buf ppp;
  304. X    long qq;
  305. X    struct q *P;
  306. X    struct q *p;
  307. X} 
  308. XPP;
  309. X
  310. XPP *P;
  311. Xint aaaaaa=2;
  312. Xint aaaaaaa=1;
  313. X
  314. Xlong qqq;
  315. X
  316. X
  317. XaaAaaa(aa,aaa)
  318. Xchar *aa;
  319. Xchar *aaa;
  320. X{
  321. X    char aaaa = 0;
  322. X    if ((((( aaa )))))
  323. X    {
  324. X        aaaa = *aa;
  325. X        *aa=0;
  326. X        aa+=strlen(aa+1);
  327. X        P =new(PP);
  328. X        P->P=P;
  329. X        P->p=P;
  330. X    }
  331. X
  332. X    if ((((( !setjmp(P->ppp) ))))) 
  333. X        {
  334. X        if ((((( !isdigit(*aa) )))))
  335. X            longjmp(P->ppp,aaaaaaa);
  336. X        else {
  337. X            P->p->P = new(PP);
  338. X            P->p->P->P = P;
  339. X            P->p->P->p = P->p;
  340. X            P->p = P->p->P;
  341. X
  342. X            P->qq = *aa--;
  343. X            P = P->p;
  344. X            aaAaaa(aa,0);
  345. X        }
  346. X    } else {
  347. X        if ( !aaaa&&!*aa ) 
  348. X           longjmp(P->p->ppp,aaaaaaa);
  349. X
  350. X        if ((((( (P->qq=aaaa)<10     &&!
  351. X                 (isdigit(aaaa))     ||!
  352. X                 (isdigit(*aa)       ||!
  353. X                 *aa                        )))))) 
  354. X        {
  355. X            fprintf(stderr,"Usage %c%s <number>\n",
  356. X            (aaa[0]?7:aaaa),aaa+!aaa[0]);
  357. X            exit(1);
  358. X        }
  359. X    }
  360. X}
  361. X
  362. X
  363. XppPppp(pp,ppp)
  364. XPP **pp, *ppp;
  365. X{
  366. X    int aa;
  367. X    if ((((( !(aa=setjmp(ppp->ppp))||aa==aaaaaa )))))
  368. X    {
  369. X        if ((((( *pp==ppp )))))
  370. X        {
  371. X            ppp = (*pp)->p;
  372. X
  373. X            if ( qqq<47 ) return;
  374. X            if ( ppp->qq!=48 ) return;
  375. X
  376. X            while ( ppp->qq==48 ) 
  377. X            {
  378. X                printf("%ld\n",qqq-45);
  379. X                *pp = ppp;
  380. X                ppp = ppp->p;
  381. X            }
  382. X            qqq -= 1;
  383. X            longjmp(ppp->ppp,aaaaaaa);
  384. X        } else {
  385. X            PP *p;
  386. X
  387. X            ppPppp(pp,ppp->p);
  388. X            for (p=ppp;p!=*pp;p=p->p)
  389. X            {
  390. X                int qq=4;
  391. X                if ((((( qqq<47                            &&
  392. X                         (qq=0,p->qq+=p->p->qq-96)>=48-qqq ||
  393. X                         qqq>46                            &&
  394. X                         (p->qq-=p->p->qq)<0                   ))))) 
  395. X                {
  396. X                    p->qq += qqq+qq;
  397. X                    if ( p->p==P && qqq<=46 )
  398. X                    {
  399. X                        P->p->P = new(PP);
  400. X                        P->p->P->P = P;
  401. X                        P->p->P->p = P->p;
  402. X                        *pp = P = P->p = P->p->P;
  403. X                        P->qq = 48;
  404. X                    }
  405. X
  406. X                    p->p->qq+=qq==0;
  407. X                    p->p->qq-=qq!=0;
  408. X                }
  409. X                else
  410. X                {
  411. X                    p->qq += 48;
  412. X                }
  413. X            }
  414. X            if ( ppp->P==P ) longjmp(ppp->ppp,aaaaaaa);
  415. X        }
  416. X    }
  417. X    else
  418. X    {
  419. X        qqq += 1; 
  420. X
  421. X        while (48==P->qq )
  422. X        {
  423. X            P->P->p = P->p;
  424. X            P = P->p->P = P->P;
  425. X
  426. X        }
  427. X
  428. X        if (ppp!=ppp->p->p )
  429. X            longjmp(ppp->ppp,aaaaaa);
  430. X        else
  431. X        {
  432. X            printf("At most one remains\n");
  433. X            exit(0);
  434. X        }
  435. X    }
  436. X}
  437. X
  438. X
  439. Xmain(aaa,aaaa)
  440. Xint aaa;
  441. Xchar **aaaa;
  442. X{
  443. X    aaAaaa(aaa==aaaaaaa?aaaa[0]:aaaa[1],aaaa[0]);
  444. X    qqq = 39;
  445. X    ppPppp(&P,P->p);
  446. X}
  447. X
  448. X
  449. SHAR_EOF
  450. $TOUCH -am 0817110092 1992/albert.orig.c &&
  451. chmod 0444 1992/albert.orig.c ||
  452. echo "restore of 1992/albert.orig.c failed"
  453. set `wc -c 1992/albert.orig.c`;Wc_c=$1
  454. if test "$Wc_c" != "3153"; then
  455.     echo original size 3153, current size $Wc_c
  456. fi
  457. # ============= 1992/ant.README ==============
  458. echo "x - extracting 1992/ant.README (Text)"
  459. sed 's/^X//' << 'SHAR_EOF' > 1992/ant.README &&
  460. XNAME
  461. X
  462. X    am        Anthony's Make 
  463. X
  464. X
  465. XSYNOPSIS
  466. X
  467. X    am <makefile> [target]
  468. X
  469. X
  470. XDESCRIPTION
  471. X
  472. XAM is a programmer's tool to maintain, update, and regenerate groups
  473. Xof files and/or programs.  It is similar to MAKE as described by the
  474. XPOSIX.2 draft standard 11.2, and this document parallels the draft
  475. Xin order to point out the subtle differences between AM and MAKE.
  476. X
  477. XThe AM utility can be used as part of software development to update
  478. Xfiles that are derived from other files.  A typical case is one where
  479. Xobject files are derived from the corresponding source files.  The AM
  480. Xutility examines time relationships and updates those derived files
  481. X(targets) that have modified times earlier than the modified times of
  482. Xthe files (prerequisites) from which they are derived.  A description 
  483. Xfile ("makefile") contains a description of the relationships between 
  484. Xfiles, and the commands that must be executed to update the targets to
  485. Xreflect changes in their prerequisites.  Each specification, or rule, 
  486. Xshall consist of a target, optional prerequisites, and optional 
  487. Xcommands to be executed when a prerequisite is newer than the target.
  488. X
  489. X
  490. XOPTIONS
  491. X
  492. XNone.
  493. X
  494. X
  495. XOPERANDS
  496. X
  497. Xmakefile    This required argument, is a pathname of a description
  498. X        file, which is also referred to as the "makfile".  A
  499. X        pathname of "-", shall *NOT* denote the standard input.
  500. X
  501. Xtarget        This optional argument, is the first target to be 
  502. X        processed.  If no target is specified, when AM is
  503. X        processing the makefile, the first target that AM
  504. X        encounters shall be used.
  505. X
  506. X
  507. XEXTERNAL INFLUENCES
  508. X
  509. XSTANDARD INPUT
  510. X
  511. XNot used.
  512. X
  513. X
  514. XINPUT FILES
  515. X
  516. XThe input file, otherwise known as the makefile, is a text file
  517. Xcontaining rules, macro definitions, and comments.
  518. X
  519. X
  520. XASYNCHRONOUS EVENTS
  521. X
  522. XAll traps are left to their default actions.  If AM receives a SIGHUP,
  523. XSIGTERM, SIGINT, or SIGQUIT then AM will terminate as per request
  524. X*WITHOUT* removing the current target.
  525. X
  526. X
  527. XEXTERNAL EFFECTS
  528. X
  529. XSTANDARD OUTPUT
  530. X
  531. XThe AM utility shall write all commands to be executed to standard
  532. Xoutput unless the command is prefixed with an at-sign (@).  If AM is
  533. Xinvoked without any work needing to be done, it shall *NOT* write a
  534. Xmessage to standard output indicating that no action was taken. 
  535. X
  536. X
  537. XSTANDARD ERROR
  538. X
  539. XStandard error is used for diagnostic messages only.
  540. X
  541. X
  542. XOUTPUT FILES
  543. X
  544. XNone.  However, the utilities invoked by AM may create additional files.
  545. X
  546. X
  547. XEXTENDED DESCRIPTION
  548. X
  549. XThe AM utility attempts to perform the actions required to ensure
  550. Xthat the specified target(s) are up-to-date.  A target is considered
  551. Xout-of-date if it is older than any of its prerequisites or it does
  552. Xnot exist.  The AM utility shall treat all prerequisites as targets
  553. Xthemselves and recursively ensure that they are up-to-date, processing
  554. Xthem in the order which they appear in the rule.  The AM utility shall
  555. Xuse the modification times of files to determine if the corresponding
  556. Xtargets are out-of-date.
  557. X
  558. XAfter AM has ensured that all of the prerequisites of a target are
  559. Xup-to-date, and if the target is out-of-date, the commands associated
  560. Xwith the target entry shall be executed.  If there are no commands
  561. Xlisted for the target, the target shall be treated as up-to-date.
  562. X
  563. X
  564. XMAKEFILE SYNTAX
  565. X
  566. XA makefile can contain rules, macro definitions, and comments.  If a
  567. Xmacro is defined more than once, the value of the macro shall be the
  568. Xlast one specified.  Comments start with a number-sign (#) and
  569. Xcontinue until an unescaped <newline> is reached.
  570. X
  571. XA backslash before a <newline> serves as a line continuation mark, and 
  572. Xis used to create long-lines.   A line will continue to be extended until 
  573. Xan unescaped <newline> is reached.
  574. X
  575. XWhen an escaped <newline> (one preceded by a backslash) is found anywhere
  576. Xin the makefile, it shall be replaced, along with any leading white 
  577. Xspace on the following line, with a single <space>.  
  578. X
  579. X
  580. XMAKEFILE EXECUTION
  581. X
  582. XCommand lines shall be processed one at a time by writing the command
  583. Xline to standard output, unless prefixed with an at-sign (@), and
  584. Xexecuting the command(s) in the line.  Commands shall be executed by
  585. Xpassing the command line to the command interpreter via the system()
  586. Xfunction.
  587. X
  588. XThe environment for the command being executed shall contain all of the
  589. Xvariables in the environment of AM.  All macros are considered to be part 
  590. Xof the environment too.
  591. X
  592. XBy default, when AM receives a non-zero status from the execution of a
  593. Xcommand, it terminates with an error message to standard error.  If
  594. Xthe command is prefixed by a hyphen (-) then any error found while
  595. Xexecuting the command shall be ignored.
  596. X
  597. XCommand lines can have one or more of the following prefixes: a hyphen
  598. X(-) to ignore errors, an at-sign (@) to be silent, or a plus-sign (+)
  599. Xif the command is always executed (this prefix is for compatibility with
  600. XMAKE and is ignored).
  601. X
  602. X
  603. XTARGET RULES
  604. X
  605. XTarget rules are formatted as follows:
  606. X
  607. X    target [target ...] : [prerequisite ...]
  608. X    [<tab>command
  609. X     <tab>command
  610. X     ...]
  611. X
  612. X    (line that does not begin with <tab>)
  613. X
  614. XTarget entries are specified by a <blank>-separated, non-null list of
  615. Xtargets, then a colon, then a <blank>-separated, possibly empty list
  616. Xof prerequisite.  All following lines, if any, that begin with a <tab>,
  617. Xare command lines to be executed to update the target(s).  The first
  618. Xline that does not begin with a <tab> shall begin a new entry.
  619. X
  620. XTarget names can be any character supported by the host system,
  621. Xexcluding <blank>s, <tab>s, <newline>s, and colons (:), which are used 
  622. Xfor delimiters.
  623. X
  624. XFor any given target there can be only one target rule.  The first
  625. Xoccurrence of a target in a makefile shall be used.  All subsequent
  626. Xrules for the same target are ignored.  There is *no* support for 
  627. Xadding prerequisites to a target's prerequisite list once a target
  628. Xrule is defined.
  629. X
  630. XThere are no special targets or inference rule support.  
  631. X
  632. X
  633. XMACROS
  634. X
  635. XMacro definitions are in the form:
  636. X
  637. X    string1 = [string2]
  638. X
  639. XThe macro named string1 is defined as having the value of string2,
  640. Xwhere string2 is defined as all characters, if any, after the equal
  641. Xsign up to an unescaped <newline>.  Any <blank>s immediately before or
  642. Xafter the equal sign shall be ignored.
  643. X
  644. XSubsequent appearances of $(string1) shall be replaced by string2.
  645. XThe parentheses are *NOT* optional if string1 is a single character.
  646. XThe macro $$ shall be replaced by the single character $.  
  647. X
  648. XMacro names can be any character that the host system would allow in 
  649. Xthe definition of environment variables, excluding parentheses, ( and ), 
  650. Xwhich are used for delimiters.
  651. X
  652. XMacros can appear anywhere in the makefile, except within other macro 
  653. Xreferences (ie. no nesting).  Macros in target and command lines shall 
  654. Xbe evaluated when the line is read.  Macros in macro definition lines 
  655. Xshall be evaluated *IMMEDIATELY*.  A macro that has not been defined 
  656. Xshall evaluate to a null string without causing any error condition.  
  657. X
  658. XIf a macro is defined more than once, the value of the macro shall be the 
  659. Xlast one specified prior to it being referenced.
  660. X
  661. XMacro assignments shall be accepted from the sources listed below, in 
  662. Xthe order shown.  If a macro name already exists at the time it is being
  663. Xprocessed, the newer definition shall replace the existing definition.
  664. X
  665. X   1)    The contents of the environment, including the variables with
  666. X    null values in the order defined in the environment.
  667. X
  668. X   2)    Macros defined in the makefile, processed in the order specified.
  669. X
  670. XThere are no internal macros supported.  The SHELL macro shall *NOT* be
  671. Xtreated specially.
  672. X
  673. X
  674. XEXIT STATUS
  675. X
  676. X  0    Successful completion.
  677. X  1    General error.
  678. X  2    Usage error.
  679. X  3    Failed to open makefile.
  680. X  4    Failed to allocate memory.
  681. X
  682. X
  683. XINSTALLATION
  684. X
  685. XAM can be built on any system providing at least K&R C.  It has been 
  686. Xtested on 
  687. X
  688. X    o  SunOS with GCC
  689. X    o  ATARI Mega ST with Sozobon C
  690. X    o  PC clone with Turbo C
  691. X    o  Interactive UNIX System V/386 release 3.2
  692. X
  693. XFor all machines, the compile command line should be
  694. X
  695. X    cc -O -o am am.c
  696. X
  697. XThe value RULES represents the number of slots available to record
  698. Xtarget rules, dependencies, and commands.  The default value chosen
  699. Xshould handle most project makefiles.  RULES can be overridden on the
  700. Xcommand line with -DRULES=nn, where 0 < nn < INT_MAX.
  701. X
  702. XOn a DOS machine using Turbo C, it may be necessary to add the include
  703. Xdirective
  704. X
  705. X    #include <time.h>
  706. X
  707. Xwith the rest of the includes if sys/stat.h does not properly define or
  708. Xuse time_t.  Also, on some older K&R C compilers, stdlib.h may not be 
  709. Xdefined and so it might be necessary to remove the include directive for 
  710. Xit. 
  711. X
  712. X
  713. XREFERENCES
  714. X
  715. X[Mil87]    Webb Miller, "A Software Tools Sampler", Prentice Hall, 87
  716. X    ISBN 0-13-822305-X, chaper 2
  717. X
  718. X[POSIX]    POSIX.2 draft 11.2 MAKE
  719. X
  720. X
  721. XFILES
  722. X
  723. Xant.c        Obfuscated source
  724. Xant.README    Manual for AM
  725. Xant.test.mk    Test makefile
  726. X
  727. X
  728. XBUGS
  729. X
  730. XUnknown as of 20 March 92.
  731. SHAR_EOF
  732. $TOUCH -am 0817110092 1992/ant.README &&
  733. chmod 0400 1992/ant.README ||
  734. echo "restore of 1992/ant.README failed"
  735. set `wc -c 1992/ant.README`;Wc_c=$1
  736. if test "$Wc_c" != "8745"; then
  737.     echo original size 8745, current size $Wc_c
  738. fi
  739. # ============= 1992/ant.c ==============
  740. echo "x - extracting 1992/ant.c (Text)"
  741. sed 's/^X//' << 'SHAR_EOF' > 1992/ant.c &&
  742. X#define W while
  743. X#define S strspn 
  744. X#define R return 
  745. X#define F fprintf(stderr,
  746. X#define C continue;
  747. X
  748. X#include <stdlib.h>
  749. X#include <stdio.h>
  750. X#include <string.h>
  751. X#include <sys/stat.h>
  752. X
  753. X#ifndef RULES
  754. X#define RULES    500
  755. X#endif
  756. X
  757. X#define N(p, i)    (p += i, p += S(p, w), i = strcspn(p, w))
  758. X
  759. Xchar *b, l[BUFSIZ], *t[RULES], *d[RULES], *c[RULES], w[] = "\n\t ";
  760. X
  761. Xtime_t M();
  762. Xint T();
  763. Xvoid U();
  764. X
  765. X
  766. Xtime_t
  767. XM(f)
  768. Xchar *f;
  769. X{
  770. X    int j, x;
  771. X    size_t i = 0;
  772. X    struct stat s;
  773. X    N(f, i);
  774. X    x = f[i];
  775. X    f[i] = 0; 
  776. X    j = stat(f, &s);
  777. X    f[i] = x;
  778. X    R j < 0 ? 0 : s.st_mtime;
  779. X}
  780. X
  781. Xint
  782. XT(f)
  783. Xchar *f;
  784. X{
  785. X    char *q;
  786. X    size_t i = 0, j, k = 1;
  787. X    N(f, i);
  788. X    W ((q = t[k])) {
  789. X        j = 0;
  790. X        W (N(q, j)) {
  791. X            if (i == j && !strncmp(f, q, i))
  792. X                R k;
  793. X        }
  794. X        ++k;
  795. X    }
  796. X    R 0;
  797. X}
  798. X
  799. Xvoid
  800. XU(f)
  801. Xchar *f;
  802. X{
  803. X    time_t t = M(f);
  804. X    size_t i = 0, j = !t, k = T(f);
  805. X    char *p = d[k], *q = c[k];
  806. X    if (!N(p, i) && q && *q != '\t' && j) {
  807. X        F "am: Don't know how to make '%s'.\n", f);
  808. X        exit(1);
  809. X    }
  810. X    W (0 < i) {
  811. X        U(p);
  812. X        if (t < M(p))
  813. X            j = 1;
  814. X        N(p, i);
  815. X    }
  816. X    if (j && q && *q == '\t') {
  817. X        sleep(1);
  818. X        W (*q++ == '\t') {
  819. X            i = j = 1;
  820. X            W (0 < S(q, "-+@")) {
  821. X                if (*q == '@')
  822. X                    
  823. X                    i = 0;
  824. X                if (*q++ == '-')
  825. X                    
  826. X                    j = 0;
  827. X            }
  828. X            if (i)
  829. X                puts(q);
  830. X            if (system(q) && j) {
  831. X                F "am: Error making '%s'\n", f);
  832. X                exit(1);
  833. X            }
  834. X            q += strlen(q) + 1;
  835. X        }
  836. X        c[k] = 0;
  837. X    }
  838. X}
  839. X
  840. Xint
  841. Xmain(u, v)
  842. Xint u;
  843. Xchar **v;
  844. X{
  845. X    FILE *f;
  846. X    struct stat s;
  847. X    size_t i, j, k;
  848. X    char *m, *n, *p, *q, *r;
  849. X    if (u < 2) {
  850. X        F "usage: am <makefile> [target]\n");
  851. X        R 2;
  852. X    }
  853. X    if (stat(*++v, &s) || !(f = fopen(*v, "r")))
  854. X        R 3;
  855. X    q = b = malloc(2*s.st_size);
  856. X    if (!b)
  857. X        R 4;
  858. X    i = 1;
  859. X    k = 0;
  860. X    m = 0;
  861. X    *t = *d = *c = "";
  862. X    W ((r = fgets(l, BUFSIZ, f))) {
  863. X        if (RULES <= i) {
  864. X            F "am: Number of target-rules exceeds %d.\n", RULES);
  865. X            R 1;
  866. X        }
  867. X        if (k) {
  868. X            *q++ = ' ';
  869. X            r += S(r, w);
  870. X        } else {
  871. X            if (t[i])
  872. X                c[i++] = q;
  873. X            if (m && putenv(m))
  874. X                F "am: No more environment space.\n");
  875. X            m = 0;
  876. X            if (*l == '#' || *l == '\n')
  877. X                C
  878. X            p = q;
  879. X        }
  880. X        W (!(k = *r == '\\' && r[1] == '\n') && *r) {
  881. X            if (*r == '$') {
  882. X                if (r[1] == '(') {
  883. X                    n = r+2;
  884. X                    r += strcspn(r, ")");
  885. X                    *r++ = 0;
  886. X                    n = getenv(n);
  887. X                    if (n) 
  888. X                        q = strcpy(q, n) + strlen(n);
  889. X                    C
  890. X                }
  891. X                if (*r == r[1])
  892. X                    ++r;
  893. X            } 
  894. X            if (*r == '=' && *l != '\t' && !m) {
  895. X                *q = 0;
  896. X                m = p;
  897. X                j = 0;
  898. X                q = N(m, j) + m;
  899. X                *q++ = *r;
  900. X                j = 1;
  901. X                if (!N(r, j))
  902. X                    *q++ = 0;
  903. X                C
  904. X            }
  905. X            if (*r == ':') {
  906. X                t[i] = p;
  907. X                *r = 0;
  908. X                d[i] = q+1;
  909. X            }
  910. X            if (*r == '\n')
  911. X                *r = 0;
  912. X            *q++ = *r++;
  913. X        }
  914. X    }
  915. X    fclose(f);
  916. X    U(2 < u ? *++v : t[1]);
  917. X    R 0;
  918. X}
  919. X
  920. SHAR_EOF
  921. $TOUCH -am 0817110092 1992/ant.c &&
  922. chmod 0444 1992/ant.c ||
  923. echo "restore of 1992/ant.c failed"
  924. set `wc -c 1992/ant.c`;Wc_c=$1
  925. if test "$Wc_c" != "2547"; then
  926.     echo original size 2547, current size $Wc_c
  927. fi
  928. # ============= 1992/ant.hint ==============
  929. echo "x - extracting 1992/ant.hint (Text)"
  930. sed 's/^X//' << 'SHAR_EOF' > 1992/ant.hint &&
  931. XBest Utility: <ant@mks.com> Anthony C Howe
  932. X
  933. X    Anthony C Howe
  934. X    Mortice Kern Systems Inc.
  935. X    Unit 1, 14 Weber Street North
  936. X    Waterloo, Ontario
  937. X    N2J 3G4
  938. X    Canada
  939. X
  940. X
  941. XJudges' comments:
  942. X
  943. X   To use:
  944. X    make am
  945. X    am ant.test.mk
  946. X    
  947. X    Like much of Posix, obfuscation has its place.  Your task is to
  948. X    figure out where.
  949. X
  950. X    This entry comes complete with a Posix-like command description.
  951. X    Interested Posix balloters should lobby the IEEE for an obfuscated 
  952. X    P1003 sub-committee.
  953. X
  954. X    We also suggest that you try:
  955. X    make am
  956. X    am Makefile am_clobber        <-- clobber everything except am
  957. X    am Makefile all
  958. X
  959. X
  960. XSelected notes from the author:
  961. X
  962. X    See the file ant.README.
  963. SHAR_EOF
  964. $TOUCH -am 0908160292 1992/ant.hint &&
  965. chmod 0444 1992/ant.hint ||
  966. echo "restore of 1992/ant.hint failed"
  967. set `wc -c 1992/ant.hint`;Wc_c=$1
  968. if test "$Wc_c" != "656"; then
  969.     echo original size 656, current size $Wc_c
  970. fi
  971. # ============= 1992/ant.test.mk ==============
  972. echo "x - extracting 1992/ant.test.mk (Text)"
  973. sed 's/^X//' << 'SHAR_EOF' > 1992/ant.test.mk &&
  974. X#
  975. X#    Test makefile for AM
  976. X#
  977. X
  978. X#
  979. X#  Allow for empty macros.
  980. X#
  981. XEMPTY=
  982. X
  983. X#
  984. X#  Allow for white space in macro assignment.
  985. X#
  986. XTEXT_1=no white space
  987. XTEXT_2 =left hand side
  988. XTEXT_3= right hand side
  989. XTEXT_4 = both sides
  990. XTEXT_5    =    tabs boths sides
  991. X
  992. X#
  993. X#  Test psuedo targets.
  994. X#
  995. Xall : print_macros repeat redefine many flags multiple split errors done
  996. X
  997. Xprint_macros : empty t1 t2 t3 t4 t5 t.all
  998. X
  999. X#
  1000. X#  Targets with no dependencies.
  1001. X#
  1002. Xempty :
  1003. X    echo EMPTY='$(EMPTY)'
  1004. X
  1005. Xt1 :
  1006. X    echo TEXT_1='$(TEXT_1)'
  1007. X
  1008. Xt2 :
  1009. X    echo TEXT_2='$(TEXT_2)'
  1010. X
  1011. Xt3 :
  1012. X    echo TEXT_3='$(TEXT_3)'
  1013. X
  1014. Xt4 :
  1015. X    echo TEXT_4='$(TEXT_4)'
  1016. X
  1017. Xt5 :
  1018. X    echo TEXT_5='$(TEXT_5)'
  1019. X
  1020. Xt.all :
  1021. X    echo $(TEXT_1) $(TEXT_2) $(TEXT_3) $(TEXT_4) $(TEXT_5)
  1022. X
  1023. X#
  1024. X#  Test redefinition of macros.  AM allows redefinition and 
  1025. X#  evaluates macros immediately.
  1026. X#
  1027. XTEXT_1    =text number 1
  1028. XTEXT_2    = test macro split \
  1029. X    across lines \
  1030. X    three lines
  1031. XTEXT_3    = test dollar macro '$$'
  1032. XTEXT_4    = test dollar again "$$(TEXT_1)"
  1033. XTEXT_5    =    imbeded macro '$(TEXT_1)'
  1034. X
  1035. Xredefine : r1 r2 r3 r4 r5 
  1036. X
  1037. Xr1 :
  1038. X    echo TEXT_1='$(TEXT_1)'
  1039. X
  1040. Xr2 :
  1041. X    echo TEXT_2='$(TEXT_2)'
  1042. X
  1043. Xr3 :
  1044. X    echo TEXT_3='$(TEXT_3)'
  1045. X
  1046. Xr4 :
  1047. X    echo TEXT_4='$(TEXT_4)'
  1048. X
  1049. Xr5 :
  1050. X    echo TEXT_5='$(TEXT_5)'
  1051. X
  1052. X#
  1053. X#  Try to update a prerequisite more than once.  Subsequent occurences
  1054. X#  should be ignored once a prerequisite has been updated.
  1055. X#
  1056. Xrepeat: t1 repeat.a t3
  1057. Xrepeat.a : t2 t1
  1058. X
  1059. X
  1060. X#
  1061. X#  Target with multi-line receipe.
  1062. X#
  1063. Xmany : leaf.1 leaf.2
  1064. X    echo Execute receipe with multiple commands.
  1065. X    ls -1 leaf.*
  1066. X    echo Last line of receipe for target 'many'.
  1067. X
  1068. Xleaf.1 :
  1069. X    touch leaf.1
  1070. X
  1071. Xleaf.2 : 
  1072. X    touch leaf.2
  1073. X
  1074. X
  1075. X#
  1076. X#  Test receipe line flags.
  1077. X#
  1078. Xflags : silence ignore always combination
  1079. X
  1080. X#  Command not displayed before execution.
  1081. Xsilence :
  1082. X    echo You should not see the 'ls' command printed. 
  1083. X    @ls leaf.*
  1084. X
  1085. X#  Ignore errors from command.
  1086. Xignore :
  1087. X    echo The 'ls' command should fail but not terminate AM.
  1088. X    -ls unknown
  1089. X
  1090. X#  This flag is ignored by AM since we don't support a silence option (-n).
  1091. Xalways :
  1092. X    +echo The '+' flag is accepted and ignored.
  1093. X
  1094. Xcombination:
  1095. X    -@echo The next displayed line should not be 'ls unknown'
  1096. X    @-ls unknown
  1097. X    @+-echo Combined flags test completed.
  1098. X
  1099. X
  1100. X#
  1101. X#  Multiple targets.
  1102. X#
  1103. Xmultiple : node.2 node.5
  1104. X
  1105. Xnode.1 node.2 node.3 : leaf.1 leaf.2
  1106. X    touch node.1 node.2 node.3
  1107. X
  1108. Xnode.4 node.5 : node.2 leaf.3 
  1109. X    touch node.4 node.5
  1110. X
  1111. Xleaf.3 :
  1112. X    touch leaf.3
  1113. X
  1114. X
  1115. X#
  1116. X#  Test split lines.
  1117. X#
  1118. Xsplit : node.6 leaf.4 split.cmd
  1119. X    echo Completed split line tests.
  1120. X
  1121. X#  Target dependencies split across lines.
  1122. Xnode.6 : leaf.1 \
  1123. X    leaf.2 \
  1124. X    leaf.3
  1125. X    echo Test dependency list split across lines.
  1126. X    touch node.6
  1127. X
  1128. X#  Target list split across lines.
  1129. Xsplit.tar \
  1130. Xleaf.4 \
  1131. Xleaf.5 :
  1132. X    echo Test target list split across lines
  1133. X    touch leaf.4 leaf.5 
  1134. X
  1135. X#  Command lines split across lines.
  1136. Xsplit.cmd:
  1137. X    echo Try spliting command \
  1138. X        lines across more \
  1139. X    than one line.
  1140. X
  1141. X
  1142. X#
  1143. X#  Test AM error reports and exit statuses.
  1144. X#
  1145. Xerrors:
  1146. X    -am test.mk error.1
  1147. X    -am test.mk error.2
  1148. X    -am test.mk error.3
  1149. X    
  1150. X#  Target that does not exist, has no dependencies, and no commands.
  1151. Xerror.1:
  1152. X
  1153. X#  Target where dependency does not exist.
  1154. Xerror.2: unknown
  1155. X
  1156. X#  Receipe command causes error.
  1157. Xerror.3: t1 fail t2
  1158. Xfail:
  1159. X    ls -l unknown
  1160. X
  1161. X
  1162. X#
  1163. X#
  1164. X#
  1165. Xdone:
  1166. X    echo AM Test Complete
  1167. X
  1168. Xclean:
  1169. X    rm leaf.* node.*
  1170. SHAR_EOF
  1171. $TOUCH -am 0817110092 1992/ant.test.mk &&
  1172. chmod 0444 1992/ant.test.mk ||
  1173. echo "restore of 1992/ant.test.mk failed"
  1174. set `wc -c 1992/ant.test.mk`;Wc_c=$1
  1175. if test "$Wc_c" != "3164"; then
  1176.     echo original size 3164, current size $Wc_c
  1177. fi
  1178. # ============= 1992/buzzard.1.c ==============
  1179. echo "x - extracting 1992/buzzard.1.c (Text)"
  1180. sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.1.c &&
  1181. X#define A(c,a,b) t=b;t+=a;_(c)
  1182. X#define    B(b,a) P(u,a)t=0;t-=a;R t+=u;t+=1;t/=2;_(b)
  1183. X#define b(x) x(g)
  1184. X#define C ;main(argc,argv)char**argv;{for(;!w;){q=0;l
  1185. X#define c(y) x
  1186. X#define D(c,a,b) t=a;t/=b;_(c)
  1187. X#define d(x) S(x,x,1)
  1188. X#define E(a,d) t=d;t-=p;t*=r;t*=a;p+=t;t=1;t-=a;r*=t;
  1189. X#define e(x) y
  1190. X#define f(x) x(e)
  1191. X#define G(x,y) Q(x,atoi(argv[y]))
  1192. X#define g(x) x(b)
  1193. X#define H Q(w,1)Q(p,0)r=0;
  1194. X#define h(x) x(c)
  1195. X#define i(c,a,b) a(b,b,c)
  1196. X#define J(x) Q(p,x)r=0;
  1197. X#define j(x) Q(f(g),x)
  1198. X#define K(x) Q(x,argc)
  1199. X#define k(x) S(a,y,x)
  1200. X#define L(x) u=p;u-=x;t=u;t*=u;R r+=2;r-=t;r/=2;
  1201. X#define l L(q) q+=1;
  1202. X#define M(c,a,b) t=a;t*=b;_(c)
  1203. X#define m(x) x(a,a)
  1204. X#define n(x) x(a,y)
  1205. X#define O(c,a,b) t=b;t+=1;t+=a;t/=2;Q(c,t)
  1206. X#define o(x,y) M(x,x,y)
  1207. X#define P(b,a) t=a;R _(b)
  1208. X#define R t+=2047;t/=2048;t+=8191;t/=8192;
  1209. X#define Q(a,b) t=b;_(a)
  1210. X#define S(c,a,b) t=a;t-=b;_(c)
  1211. X#define T }
  1212. X#define U(c,a,b) u=b;t=b;t-=1;t*=r;t+=1;b=t;t=a;t/=b;b=u;_(c)
  1213. X#define V int t,u,q,p=0,r,w=0,
  1214. X#define X(y) printf("%x\n",y);
  1215. X#define Z(a,d) t=p;t-=d;t*=a;t+=d;_(p)r*=a;
  1216. X#define _(a) t-=a;t*=r;a+=t;
  1217. X
  1218. XV a,x,y,s C
  1219. X
  1220. X        G(f(g),q)G(          g(h),2)n(B)Z(a,4)n(
  1221. X    P)E(a,1)j(2989)H l k     (1)m(B)Z(a,6)l k(h(b))
  1222. X      B(s,a             )m(P)        Z(s             ,8)E
  1223. X    (a,q                   )Q(       s,h               (g)
  1224. X   )Q(                               f(c                ),f
  1225. X  (g)                                )j(                s)l
  1226. X  i(b                                (h)                ,S,
  1227. X f(b                                 ))n               (B)
  1228. X E(a                                 ,2)             J(8)
  1229. Xl j(                                x)Q(x,1)l n(P)Z(a,8
  1230. X)o(x                                ,g(f))d(f(e))J(5)l j
  1231. X(x)l                                 d(x              )S(a
  1232. X ,x,                                 1)m                (B)
  1233. X  Z(a                                ,10                 )U(
  1234. X  a,y                                ,x)                 o(a
  1235. X   ,x)                               k(a                 )m(
  1236. X    P)E(                   a,7)      l j                (0)
  1237. X      Q(s,1            )l D(a        ,x,              q)o(
  1238. X    a,q)S(a,h(g),a)i(s,       M,a)i(a,A,g(f))i(q,D,x
  1239. X        )o(s,16)B(a          ,x)E(a,9)H l j(2766)H
  1240. X
  1241. XT  X(b(f))  T
  1242. SHAR_EOF
  1243. $TOUCH -am 0817110092 1992/buzzard.1.c &&
  1244. chmod 0444 1992/buzzard.1.c ||
  1245. echo "restore of 1992/buzzard.1.c failed"
  1246. set `wc -c 1992/buzzard.1.c`;Wc_c=$1
  1247. if test "$Wc_c" != "2236"; then
  1248.     echo original size 2236, current size $Wc_c
  1249. fi
  1250. # ============= 1992/buzzard.1.hint ==============
  1251. echo "x - extracting 1992/buzzard.1.hint (Text)"
  1252. sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.1.hint &&
  1253. XMost Obfuscated Algorithm: <sean@stat.tamu.edu> Sean Barrett
  1254. X
  1255. X    Sean Barrett
  1256. X    Software Construction Company
  1257. X    430 Southwest Parkway, #1906
  1258. X    College Station, TX 77840
  1259. X    USA
  1260. X
  1261. X    Direct bounced email to <jon@stat.tamu.edu>.
  1262. X
  1263. XJudges' comments:
  1264. X
  1265. X    To see clearly why this won an award:
  1266. X    make babble
  1267. X    
  1268. X    Try:
  1269. X    babble 0 10
  1270. X    babble 56 720
  1271. X    babble 1 521
  1272. X    
  1273. X    To see good C Preprocessor babble, try:
  1274. X    make babble.cppcb
  1275. X    cat babble.cppcb
  1276. X    
  1277. X    Notice how many statements it takes to do anything useful?
  1278. X
  1279. X
  1280. XSelected notes from the author:
  1281. X
  1282. X    What you shouldn't think about babble:
  1283. X
  1284. X      babble doesn't just do a mass of #defines as its obfuscation.
  1285. X
  1286. X
  1287. X    What you should be glad about:
  1288. X
  1289. X      I didn't just submit the post-C-preprocessed output as an entry.
  1290. X
  1291. X
  1292. X    Cute trick warning:
  1293. X
  1294. X      babble contains only a numeric printf, yet sometimes it prints out
  1295. X      short strings.
  1296. X
  1297. X
  1298. X    What it does:
  1299. X
  1300. X      babble is a simple mathematical program. It expects two numeric
  1301. X      arguments.
  1302. X
  1303. X      % babble 0 <num>
  1304. X      will print out the factorial of <num>.
  1305. X
  1306. X      % babble <num1> <num2>
  1307. X      will print out the largest common factor of num1 and num2.
  1308. X
  1309. X      % babble 1 <num2>
  1310. X      will print out a factor of num2 if it's composite, or else
  1311. X      it will print a string informing you that num2 is prime.
  1312. X
  1313. X      If the first argument is less than 0, it prints out an
  1314. X      error message.
  1315. X
  1316. X
  1317. X    What it is:
  1318. X
  1319. X      babble is a translator from a pseudo-assembly language into a
  1320. X      subset of C suitable for execution on Charles Babbage's
  1321. X      Analytical Engine.  Or rather, the #defines in babble are that
  1322. X      translator.  The rest of babble is a babble program.  If you run the
  1323. X      whole mess through CPP and a beautifier, you will see that
  1324. X      all you have is a loop that runs until a variable is not 0, and
  1325. X      a sequence of assignment statements.  The assignment statements
  1326. X      are all of the form 'a op= b' or 'a = b'.  The Engine actually
  1327. X      allowed 'a = b op c'.  Only +, -, /, and * are used--no boolean
  1328. X      or bitwise operators.  The infinite loop could have been
  1329. X      simulated on the AE by connecting the already-processed 
  1330. X      card stack to the input card stack.
  1331. X
  1332. X
  1333. X    How to try to understand it:
  1334. X
  1335. X      *Don't* expand the #defines!  Rather, decipher what they do.
  1336. X      Some of them are mere obfuscational fodder, put in to encourage
  1337. X      you to run it through CPP.
  1338. X
  1339. X
  1340. X    What it doesn't quite do right as an emulator:
  1341. X
  1342. X      Because of the definitional constraints, calls to atoi(argv[#])
  1343. X      also appear inside the loop.  These could be put outside--
  1344. X      the initial values of the "registers" on the AE--but the
  1345. X      macro conventions being used didn't lend themselves to it.
  1346. X
  1347. X
  1348. X    Theoretical observations:
  1349. X
  1350. X      The simulated comparison operations only work with a certain
  1351. X      range of numbers; numbers that are too large will cause the
  1352. X      output code to fail to simulate the input code.  This means
  1353. X      that this implementation of babble would not be turing-complete,
  1354. X      even if the AE could process indefinitely-sized numbers.
  1355. X      However, this is actually a constraint that no actual computer
  1356. X      can meet, either, so we can conclude that if an AE, with
  1357. X      card bins connected as suggested above, were hooked up to
  1358. X      a memory unit of sufficient size, it would be as turing
  1359. X      complete as any existing machine (or, for those who
  1360. X      interpret that excessively critically, i.e. "not at all" for
  1361. X      both, we can simply say that the AE could simulate any
  1362. X      existing machine--although not quickly).  This would be a
  1363. X      good place to site some references on the AE, but I don't
  1364. X      have any.
  1365. X
  1366. X
  1367. X    Definition of the input language to babble:
  1368. X    (OR What Exactly Do All The Macros Do?)
  1369. X
  1370. X    [Don't read this unless you're stumped!]
  1371. X
  1372. X
  1373. X      MACRO        FUNCTION                MNEMONIC
  1374. X        V               begin variable declarations        Variable
  1375. X        C               begin program                Code
  1376. X
  1377. X        Q(b,a)          let b = a                eQuals
  1378. X        A(c,a,b)        let c = a + b                Add
  1379. X        S(c,a,b)        let c = a - b                Subtract
  1380. X        D(c,a,b)        let c = a / b, where b is a *constant*  Divide
  1381. X        U(c,a,b)        let c = a / b, where b is anything      Unknown
  1382. X        M(c,a,b)        let c = a * b                Multiply
  1383. X
  1384. X        O(c,a,b)        let c = a boolean-or b (a,b are 0 or 1) Or
  1385. X        B(b, a)         let b = boolean value of a        Boolean
  1386. X        P(b, a)         let b = 1 if a>0, else 0.        Positive
  1387. X
  1388. X        l               emit next sequential label        Label
  1389. X        J(x)            goto label #x                Jump
  1390. X
  1391. X        Z(a,d)          if a is 0 goto d    (a is 0 or 1)    Zero
  1392. X        E(a,d)          if a is 1 goto d    (a is 0 or 1)    Else
  1393. X
  1394. X        H               halt                    Haly
  1395. X
  1396. X        K(x)            let x = number of cmd line arguments    Kount
  1397. X        G(x,y)          let x = the value if the yth argument   Get argument
  1398. X
  1399. X        T               end of code; begin output section    Terminate
  1400. X        X(y)            print out hexadecimal value of y    heXadecimal
  1401. X        T               end of output section and program    Terminate
  1402. X
  1403. X        You can figure out the other macros yourself.  In the sample
  1404. X        program, I've actually implemented subroutines by saving
  1405. X        a return address in a variable and then jumping to a routine--
  1406. X        specifically, a routine that converts a number into bcd, so
  1407. X        it can be output by the hexadecimal output statement.
  1408. X
  1409. X
  1410. X    How it works, i.e., how to get useful programs from a op= b
  1411. X
  1412. X      The essential statement to be able to do to do interesting
  1413. X      programs is the conditional (given that we have loops).
  1414. X      Since all you can do in the given operation output set is
  1415. X      assignment, we implement "conditional assignment":
  1416. X
  1417. X        if (x) y = z;
  1418. X
  1419. X      To implement this, we constrain x to be either 0 or 1, and
  1420. X      simply compute:
  1421. X
  1422. X        y = (z * x) + (y * (1-x));
  1423. X
  1424. X      This is more obscured by factoring out common terms and restricting
  1425. X      ourselves to two operand operations:
  1426. X
  1427. X        temp = z;                       (temp == z)
  1428. X        temp -= y;                      (temp == z-y)
  1429. X        temp *= x;                      (temp == (z-y)*x)
  1430. X        y += temp;                      (y    == (z-y)*x + y)
  1431. X                                        (     == z*x - y*x + y)
  1432. X                                        (     == z*x + y*(1-x))
  1433. X
  1434. X      Next we imagine we have a pc.  "I'm supposed to execute statement
  1435. X      pc next", says our emulator.  But suppose we're not currently
  1436. X      coming up on statement pc.  To handle this, we simply make every
  1437. X      operation conditional on the pc having the correct value:
  1438. X
  1439. X        if (pc == some_constant) y = z;
  1440. X
  1441. X      To combine this with other operations, we simply multiply by our
  1442. X      (pc == some_constant) flag right after the above 'temp *= x'.
  1443. X
  1444. X      To evaluate pc == some_constant requires one more trick.  We assume
  1445. X      that numbers can only be in some limited range.  Then we use successive
  1446. X      additions and divisions to reduce that number down to -1, 0, or 1.
  1447. X      You could, for instance, do this by using mod by 2 and div by 2 to
  1448. X      count bits, stopping after, say, 32 iterations.  The number you get
  1449. X      is between 0..32, so another 6 iterations on it reduces it to 0..6.
  1450. X      Three iterations on this produces 0..2 (3 would be '7'), and then
  1451. X      two iterations on this produces 0 or 1.  Instead I use a shorter
  1452. X      two-divide approach that assumes I'm allowed to use numbers slightly 
  1453. X      larger than the numbers I'm operating on.
  1454. X
  1455. X      A similar approach is used to detect positive numbers.
  1456. X
  1457. X      Note that the obvious code to compute y/x will not work correctly,
  1458. X      because every value is computed, even if the pc is not set correctly;
  1459. X      if x is ever 0 when the real C code reaches this computation the
  1460. X      program will die.  (This was discovered the hard way.)  The solution
  1461. X      is to stick x in a temporary, and if the current code is not about
  1462. X      to be executed, set the temporary to 1.
  1463. X  
  1464. X    Thanks to Bill Pugh for bringing the loopability of the AE to
  1465. X    my attention.
  1466. X
  1467. X    babble was originally named 'cb', for obvious reasons, and is
  1468. X    dedicated to the memory of Charles Barrett.
  1469. SHAR_EOF
  1470. $TOUCH -am 0908160292 1992/buzzard.1.hint &&
  1471. chmod 0444 1992/buzzard.1.hint ||
  1472. echo "restore of 1992/buzzard.1.hint failed"
  1473. set `wc -c 1992/buzzard.1.hint`;Wc_c=$1
  1474. if test "$Wc_c" != "8217"; then
  1475.     echo original size 8217, current size $Wc_c
  1476. fi
  1477. # ============= 1992/buzzard.2.README ==============
  1478. echo "x - extracting 1992/buzzard.2.README (Text)"
  1479. sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.2.README &&
  1480. Xbuzzard.2.README    this file
  1481. Xbuzzard.2.design    description of FIRST (design documentation of THIRD)
  1482. Xthird            implementation of THIRD in FIRST
  1483. Xhelp.th            online listing of THIRD primitives
  1484. X
  1485. X    FIRST demos:  use  'first < {demo}'
  1486. X
  1487. Xdemo1.1st        prints Hello World! assuming ASCII
  1488. X
  1489. X    THIRD demos:  use  'cat third {demo} | first'
  1490. X
  1491. Xdemo1.th        prints Hello World! regardless of character set
  1492. Xdemo2.th        demonstrates a simple loop
  1493. Xdemo3.th        demonstrates a simple if test
  1494. Xdemo4.th        recursive factorial calculating on the way up
  1495. Xdemo5.th        recursive factorial calculating on the way down
  1496. Xdemo6.th        demonstrates switching from compiler to execution mode
  1497. X
  1498. X    Interactive THIRD: use 'cat third - | first'.
  1499. X
  1500. X    To include the primitive on-line help, use
  1501. X    'cat third help.th - | first'.
  1502. SHAR_EOF
  1503. $TOUCH -am 0817110092 1992/buzzard.2.README &&
  1504. chmod 0444 1992/buzzard.2.README ||
  1505. echo "restore of 1992/buzzard.2.README failed"
  1506. set `wc -c 1992/buzzard.2.README`;Wc_c=$1
  1507. if test "$Wc_c" != "756"; then
  1508.     echo original size 756, current size $Wc_c
  1509. fi
  1510. # ============= 1992/buzzard.2.c ==============
  1511. echo "x - extracting 1992/buzzard.2.c (Text)"
  1512. sed 's/^X//' << 'SHAR_EOF' > 1992/buzzard.2.c &&
  1513. X#define c m[m[0]++] =
  1514. X#define z;break;case
  1515. X
  1516. Xchar s[5000];
  1517. Xint m[20000]={32},L=1,I,T[500],*S=T,t=64,w,f;
  1518. X
  1519. Xa(x)
  1520. X{
  1521. X   c L;
  1522. X   L= *m-1;
  1523. X   c t;
  1524. X   c x;
  1525. X   scanf("%s",s+t);
  1526. X   t+=strlen(s+t)+1;
  1527. X}
  1528. X
  1529. Xr(x)
  1530. X{
  1531. X   switch(m[x++]){
  1532. X    z 5:    for(w=scanf("%s",s)<1?exit(0),0:L;strcmp(s,&s[m[w+1]]);w=m[w]);
  1533. X        w-1 ? r(w+2) : (c 2,c atoi(s))
  1534. X    z 12:    I=m[m[1]--]
  1535. X    z 15:    f=S[-f]
  1536. X    z 1:    c x 
  1537. X    z 9:    f *=* S--
  1538. X    z 7:    m[f]= *S--;
  1539. X        f= *S--
  1540. X    z 0:    *++S=f;
  1541. X        f=m[I++]
  1542. X    z 8:    f= *S --- f
  1543. X    z 2:    m[++m[1]]=I;
  1544. X        I=x
  1545. X    z 11:    f=0>f
  1546. X    z 4:    *m-=2;c 2
  1547. X    z 6:    f=m[f]
  1548. X    z 10:    f= *S--/f
  1549. X    z 3:    a(1);
  1550. X        c 2
  1551. X    z 13:    putchar(f);
  1552. X        f= *S--
  1553. X    z 14:    *++S=f;
  1554. X        f=getchar();
  1555. X   }
  1556. X}
  1557. X
  1558. Xmain()
  1559. X{
  1560. X   a(3);
  1561. X   a(4);
  1562. X   a(1);
  1563. X   w= *m;
  1564. X   c 5;
  1565. X   c 2;
  1566. X   I= *m;
  1567. X   c w;
  1568. X   c I-1;
  1569. X   for(w=6;w<16;)
  1570. X      a(1),c w++;
  1571. X   m[1]= *m;
  1572. X   for(*m+=512;;r(m[I++]));
  1573. X}
  1574. SHAR_EOF
  1575. $TOUCH -am 0817110492 1992/buzzard.2.c &&
  1576. chmod 0444 1992/buzzard.2.c ||
  1577. echo "restore of 1992/buzzard.2.c failed"
  1578. set `wc -c 1992/buzzard.2.c`;Wc_c=$1
  1579. if test "$Wc_c" != "791"; then
  1580.     echo original size 791, current size $Wc_c
  1581. fi
  1582. echo "End of part 2, continue with part 3"
  1583. exit 0
  1584. -- 
  1585. For a good prime, call:  391581 * 2^216193 - 1
  1586.