K@/   pqrstuvwxyz{|}~.;IB ) l `ec2"a l_  ^  &\T,2!'-3"(Z .4#)~Y <?'WO!UX^TdSY_eNTZ`fzMU>hu{jzL"phyKxI%0H|mG !:F uC AG@ #A? >t T=  ; 9  L % 7*//06]=<+17!P=,2X8ZHrjs rq{ l 0\KQaUY xP z{ X|}#5'$[j[ݾ  P-xr4 Qݽݻ 2 (/5$*0[6%+178>DJ9?EK:@FHL)O8Q[agh@ntziou{j*k& 0pv|kqw$}lrx~msy*m \ @x.X[(T  |.JLi !9|$ yW   |  ! 0"#*| .4:)/5;*06<+17`= LRAGMSBHNTCIOUDDJPVE Z`fl[agm\b 4hn]cio ,pv|qw})$Xdm,@~Bho_%+)v)v &(v#\,<=C2()8>D('39?($1E6RX^MSY_`.f2%ct*nSQxz&t/{%Q|%Q}*netPbd6r2!'-3*neU"*ne^4hL . /)3G .5y@# yy y yL 1Iy !]!]T. ?$;9$8!$>W6Qmrr\4D 2 2<~& V V..))r-3y$p$S3<" $ ";" @e" UP#e$U $m0%e$eE[g d$ɗ !!&)Gu>'/ k$) e \eXy 7fl[agm dO\Ubhn]&cyiop byv|qy*w}yr,yox~s"_ ytzuy{yy)--% ~r b@, . .0S!! 3 D ' - 3 " ( . 43 #q"F4 % =~81 y< 9  cy; + 'y0 cU  by&: U% %Q  a Yj Z  "a8(,M%V~R|~/<qrs&b7j~Y   ƣ P2*m PZ  2̐ /  1̐t   1̐y  0̐)  0̐ 0̏h /̐  /̐.  "/̐ .̐- .̏  -̏{ &  -̏0 !,̏ 1 7+̏ = ,+̏" 2 C I O U D J P Vc, Y܎܎ n.]4t w fg     !  . U0 jU@ -3tV -3s$~   0 P kV   $,  $h :F. x-3e ;$e0 j$, Ɯ    !|L9& ƚ @ P   ~~~ nr[/ ~   0 !8 ^ d m9tϋϋ? Ɩ(      Ɣk Ƒ Ǝd "W Ƌ z {Ɖ  B & .< -(    & , 2Z ! ' - 3 "y ( . 4 # ) / 5 $^y * 0 6 % + 12y K7p @Ed 8   y  wƆ |u \ A Ɓ ~` x, z }Nf &+3 ~O | 2 &< &'C & M ~H, %; p  ` `   y   t"\D`aB>$~= bظu:9_*O*[F2E2>CD0u@ABV^>?Vl6789:;<=V./012345V+,-V"V$V+2V!V"kVnnW!KK JiMn%s943|>4RTKgw.d{s~h~hwM 1"/ " " "!"p"p d!_![!d8!8!h!h!d~ d!c 11" R Xm p lF...3bin2dev1etc0lib/tmp.usrC # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cbx'xX(P X@tPPPA@ &x #3&"$P@tCC@P@&Y 3XD X@t#:Y@t#&X@t [@pX0B0 &# PA@ " C P&A@ "  &# PA@ " X(#юp(p,Ї X@4B 'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@P&t !$%C& & P P X&PX(#юp(X!$P@%XP@DXP@H@!P@%X)!P@%XP@PP@TL!P@%#!P@%$XP@\XP@`X!P@%XP@hXP@lXd!P@%XP@tXP@xpP@%XP@|!$P@%!X'PP@%XP@XP@X!P@%H/tmp/p.tmpaanandasforisofonorthetouparg count %s: cannot open cannot create %s try again /bin/sortsort-d-o/usr/bin/sortsort-d-osomeone moved sort cannot reopen %s %s: cannot open .xx " " "0123456789ABCDEFCDEFLOSXcdeflD'xXP PA@,PA@ XpLЇ,$P@ XLC XPXPXC0tX&PC@$Q@CN$Q@CB$Q@C6$Q@C*$Q@CC@P@&Y 3XC~@8PA@#@=PA@ (A@TP@PPA@ZP@`PA|@PPXL#(XPXP#@cPAX@X!;@iPA@ (C@vP@ X@#7@P@ $PX@ PA@ P@#@PA@ (A't$PPp(p<Ї$PX<$@C0"X<$X@PX@PC X<$X@PX@PX<$X@'QXP't$PXPXPA@|&t'tP@PXPA@L&t#4$CC 'X B0& !2&$PCZ P X !7 C:X !X ~C $X&P! &#? &C' !5$ " PX@#7@MP#@TPA@ ($#C*$#юp<p(Ї@ PA@ A@ юp(p(ЇDXP@HX@!P@L%akltxz/devcannot change to /dev _proc_swapdev/unixNo namelist /dev/mem/usr/sys/coreNo mem TTY F S UID PID PRI ADDR SZ WCHAN COMMAND TTY PID COMMAND %c: %3o %c%4d0SWRIZT%6d%4d%6x%4d%6x /devcannot open /dev /dev/swapCan't find /dev/swap %.16s %.64s0123456789ABCDEFCDEFLOSXcdeflosx : \ H t : $PX@Q PX PA@&t$P@uPA@dP#@}PA@TAj@Q(PXPA@<'t$P@QxPXPA@&t't$P@QtPXPA@&t't$P@QPXPA@&tX@Q8$X @Q!&# P@Q'tX@QP@FPXPA@&tX@QxP@QxX@QtP@Qt@P@QX PA$P@QX@QC $P@QlX@QlC.@MPA@4X@Ql@Q(X@Ql&P@QlCX@Q0V@Q"B0X@Q4P@Q4X@Q4X@QP$P@QlX@QlC.X@Ql@Q(X @p(p(Їh(`ABh,`A6юp(p(Ї@OPX(PA@юp(p,Ї h@C # [,'$$$@!:@ PA@ (#XPA@PA@ ($QCA|ю,pLp|Ї\$P@PA@ PXXX#@PA@ (A4$P@-PA@ P@X@#@7PA@ (A$'tPXPXXPA@L&t B XXPA@P@CCX$&" XXC C0p tB0d tB0X yB0L B0B C08P &PA@B  @XP@&#CrCю\p|p(ЇX,&P,X.(&P(#3CюA@&t$P P юp(p(ЇX,?X,$юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(XP@!$P@L%X!$P@L%XP@ X!$P@L%XP@XP@!P@L%XP@ XP@$X!P@L%XP@,XP@0X(!$P@L%XP@8XP@<4!$P@L%XP@ :'xXP PA@,PA@ XpHЇ($P@OXL&PL@PP$XHC XLX-B0jX.LX&Pl!8X@Q&P@QXLXa!6 P@QXLXv!8X@Q&P@Q#XLXP$XH'PHXL&PLCP$PX$PA@dP CX$P@VPA@TAd't P@Q(PX PA@&tX@Q(C08X@Q(C0*X@Q( C0X$P@ePA@TAX@Q8P@QX@Q,Z@Q0P@QX@QD#8X@QP@Q't@PA@&x@P@QX@QU@QC X@Qh! m @Q` @Q'td/l@Q`X@QP@PA@T&tX@QX/!`.h@,iC0JX@QXP@PA@TX@Qh! hNl@@0-$`'@PA@T# @PA@TX@QP@QCAю(pHp(ЇX(Y,#X(#X,#юp(p(ЇX(Y,#$X(#X,#юp(p(ЇX(XX.,[#юp(p,Ї X0h! `.hX,k `hi@4#$$Chi@8#%#$#ю p,p(ЇX(PA6ю0 $$ ?X,CX(d#6X(D!6'- CbQ'xX(P X@QPPPA@ &x #3&"$P@QCC@(P@l&Y 3XD X@Q#:Y@Q#&X@Q [@QX0B0 &# PA@ " C P&A@ "  &# PA@ " X(#юp(p(ЇX4P@QX0P@QX,X.0Z(PX(PA юp(p8ЇX@QX<[8P  C X +!+P X8Z PPX8X< UCJXPPX@QAPB0X PXPPATCX# CUC PXPX@QAPB0PX PXPACXC PYB04'tPX PXPPA&tX PXCvPPA C C\YB0ZX[8X<[ B"XPX@pPA@ P@X@C&'tP@P$PA@@&tC$PX@tPA@DP@X@C&'tPЇX(X & C &X B'tP & PX PA@&t$P P юp(p(ЇX(X 'P C>'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(XP@X!$P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@XX0'xXP PA@,PA@Xp,Ї @P@0($PA@PP@$PA@8$P$PA@B0P$PA@A$PX,C $Q0X0X-B0X.0X&PCX,BX0&P0XP@H%Q,C,$Q@0C X0X&PPA4P@`CX0X&PPAP@\CX.0X&PC0X0XP@0$#$ P@0$C$Q@0 CX0XPAP@XCChB BX@lC\X0XCPA C0&ɰ C0X@L !X@0$#5PAC !6X@0B0rX@0$#:X@0$PACX@L # PA" Z@0&CvX@XPAC0ɰ #7PAC$ PAC*ю p,p(ЇX@X. ##'tPPX@TPA@&t!' C .!\ P@Xюp(p(ЇX(X@0 C0^ \PA@C* @/B0$ @/%Q@/!$$Cz$ Ct !6X@X#"$ C^.X!9AX!4$C&$Q X .!@\P 00 &&#2" X(X$00 && && &&&X(ʰX$ && && &&'X PPA'X dPPA'X dPPAv'X dPPA^&X(XPPAF@00#юp(p(ЇX($!4n#m#юp(p(ЇX(&X, B$X,$$0 &# &X,$0 & #юp(XX#%!Q!Q$QC@"p(Ї@PvDec@P$PA@@&tCC8 C00 B`@PA@ @PPA@ C@PA@ @PPA@  C&'t%P@P$PA@@&tCX@:C06 & B0\@PA@ @PPA@ C B0(@PA@  B~: >X@$ C&#3&" '$ Y@#:X@PA@D C0@P P&A@ C@P:PA@ $@PA@ @PPA@ 0B9!($  B:B0A@ C0, C0!$P@%XP@XP@X!P@%E?CCÀÀa.outCan't find %s Bad format: %s mon.outNo mon.out No symbols: %s No time accumulated name %%time #call ms/call %8.8s%6.1f%6d %7.2f AAAAAA AAA0123456789ABCDEFCDEFLOSXcdeflosxftftR+B0 X0X&PPAZP@0 C&X0PX0XPA$QX@0 !6%Q,C`X!6$PAA@A ю p,p(ЇX@0,PX@0(PA@ $PA@юp(plЇLX@PA@X@0(PX@PA@hXP@0,PX@0(PA@ юLplplЇLX@0#6$P@h#$ P@hX@`Y@h!&BP@`X@\!&HP@\X@XH!)X@XY@\C &'t$ P@P$PA@(&tA@X@0 C0XpPAX@/P@XX@\]@XP@0X@XX@HX@`' C0 #юp(p(ЇX@0#9X@0$P@0#X(PAX@0$#4 Cp C>$Q@P$T@P#5$ P@0 CH$P@PC*%Q@PCC@P@&Y 3X !$Q@P #юp(p(ЇX(C0 &#6PAT" юp(p(ЇX($#5PA$0PA юp(p(ЇX(X@0$C0PAX !5$Q@.C CX$Q@0$Q@LC$P@L$P@0$Q@.CB%Q@L#$P@L%Q@0#$P@0C@P@&Y 3XX@0C0^X@0A@#юp(p(ЇX,$PX(PA@P$P P  #%#$#юp(p,Ї X@B  &PA2@PA$ PA@PAX@HPA@PAX@0PA@"PAAC 8X@L[@0Y@LCX@L 'P@0$ PAC%Q@0 PAjC !$Q@LPAPюp(p(ЇX($&0B9B $ C #юp(p(ЇX@0Y@0 !X(PA@<юp(p(Ї'tX(PA&tPA#юp(p8ЇX8XPX8XP [@hPPA@PA:XwP/PX J#7X KB0 XX@(PXX@,PXPPAPXPPAvPX@tC0ZYB YB0JX B>Y$P P юp(p(ЇX(%Q C>'tP & PX PA@&t'P  #%C & P X&P#юp(XX]P@@p(ЇX,X(%Q CNX C06'tX & P & PX PA@(&t !$%C& & P P X&PX(#юp(XP@XP@!$P@D%X!$P@D%X)!P@D%XP@ X!$P@D%XP@XP@!P@D%XP@ XP@$X!xPA@D#$C~'tP@4PPA@p&tB0H@< B08PA@ @4P@X@X@& C  #3&" $ X@C06P$PA@X PP$PA@'t$P@P$PA@@&t'tP@P$PA@p&t@P@3C #3&" $ X@C08PP$PA@'t$P@P$PA@@&t$CCPA@ $#юp4p,Ї X,P%Q0C0(X&XPA8XPX&PCX,XPAXPю p,p,Ї X@@dX @PX@&P@#)$Q@$P@X#ю p,pЇ$P@$P@@LP@@P@@P@ @P@@DP@@P@@dPX&P$X&PX&PX.&P#3C%Q@dPXC.X@X.&P"X.$QCPX@PA PX@PA PX@ PAPX@PAPX@PAPX@PA@dPPporary file Cannot open /etc/passwd User name not found in password file Permission denied Urk Cannot create /etc/passwd Password file illformed /etc/utmpNew Password:   !"$(0LD/dev 0 P$P$P 'tP@PX8PA@&tPC h'tXP@PXPA@&tXQXB,Q$Q X Y@#*@PA@ #CjXPA@$Q@юp8p4Ї@PX8P $PX4X&PX &P P4C0X4X&P$QCX&P$'tX&P@PX@PA@&tюp4p0ЇPA@PA@#4$PtX&P@+&#2"'$P%QC0 &:#2"" X@#:Y@#&X@ [@X0B0 &# PA@ `" C P&A@ `"  &# PA@ `" X(#юp(p,Ї X@|B 'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%Cmain",exit"_exit""tfname#cfname#lfname#dfname#nact$tff$mailflg$person$inchar$ maxrec#pidfn"|signal"Lout"jnfile"ident"Xcopy"card"link"open"printf" close"unlink"texecl"Xread"write"getuid"getpw"getpid"XP@lPA@ CV$QH%QDXD#)XHXPA$P X@P X@P$PXY@CXAPX@B0FXXP@XC0X XY#3$#$P #XP$QCXC0~X C0PX@B0FX@#8XY@C0"AXP@X P@XP@XQ@C&AV'tXP@P PA&tX@C0@PAd$ PA@'tP & PX PA@p&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@@&t !$%C& & P P X&PX(#юp(X!$P@%XP@(XP@,$!( p'xXP PA@,PA@Xp4ЇAB$P$PA@LB0P$PA@L$P$PA@LB0P$PA@L$P$PA@LB0P$PA@L$P@PA,P@X4C nX8X -B0Z C(+PC6-PC*$P@CC@P@(&Y 3X%Q4$Q8CAX4!6$PA,%Q4C0:X8&P8XX+C0 /B0(X-C0PFPA$Q@C@PPA@B @aC0" @' @@PA@tC @aC0" @' @@PA@tC @aC0" @' @@PA@tCA@юp(C@"p(ЇX@B0$P@PA@P@X@#$C't$P$PX@PA@&tX@P@$P@$P@X(P(X,@PA@  C0 !$$C|&C$ &X,$'C0 &:C0 !4$CD" C&:C00 9 ,$ CY(!3$#C`$#юp(p(Ї,X( C0ɠ%#8P/lpd/cfaXXXXX/usr/lpd/lfaXXXXX/usr/lpd/dfaXXXXXcmrHCannot open %s Cannot remove %s Cannot rename %s /etc/lpdlpdCannot execute /etc/lpd Copy file is too large ***:::::$ ident Cannot create %s /etc/passwd0123456789ABCDEFCDEFLOSXcdeflosx $ z z 0  $ z z 0  A't$P$PX(PAN&t PA@<'t$P$PX(PA&tCC@P@ &Y 3Xюp(p0ЇAJP X !8$P@$C$A*PX!4$PX V#юp0p(ЇX@Y@BB'tP@PX@PA@0&tP@X@!$%CL$P@X@&P@Y@!$Q@$P@X@&P@@#юp(p(ЇX(P(X(C 8X(C,X(\C0 PA@tPA@AhhDFIKMOQSU ,XP@ 0 (!P@ L%XP@ 8XP@ < 4P@ L%XP@ DXP@ HX @!P@ L%arg count /usr/bin/%s not found 0123456789ABCDEFCDEFLOSXcdeflosxXd6Xd6PX@PA@ &t't$PX@PX@PA@ &tX@C0H't$PX@PX@PA@ &t't$PX@PX@PA@ &t'tPX@P$PA@ <&t !<@uPA@A@ PA@ P@'t PX@PX@PA@ p&tX@B0('xP PPX@PA@ &x$PA@ ,P@P$PA@ $ C6X@#:X@X C0 X@C0HX@_B0$ɰCX@ X @ +&CX@$X@Xİɰ#"$ !8X@X #2$X@#4 # CUC PXPX@APB0PX PPACXC JYB0.'tPX PPPA&tX PCPPA C CfYB0ZX[8X<[ B"XC # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@&x ,X( C0ɠ%#8PA@xC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@ &x #3&"$P@CC@@X!P@%a.outcannot open input bad format no name list %c UATDBCuatdbc%.8s 0123456789abcdef0123456789ABCDEFCDEFLOSXcdeflosx<H <H &X B'tP & PX PA@&t$P P юp(p(ЇX,?X,$юp(XX]P@p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X)!P@%XP@TXP@XP!P@%XP@`XP@dX\!P@%XP@lXP@pXh!$P@%XP@xXP@|Xt!P@%Tsrocrbxhbxlelpswthinhiclhiohixhilhichiahishisrhlslhlsrhaslhastmlmstblbclbalwbrbwhrhwdrdssoctssvcsintscplatlatrrlrllsrlsllsraslatiniclioixiliciaisi0123456789ABCDEFCDEFLOSXcdeflosx VV VV #3&"$P@CC@P@&Y 3XD X@#:Y@#&X@ [@X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@B 'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CN !Error 0Not super-userNo such file or directoryNo such processInterrupted system callI/O errorNo such device or addressArg list too longExec format errorBad file numberNo childrenNo more processesNot enough corePermission deniedError 14Block device requiredMount device busyFile existsCross-device linkNo such deviceNot a directoryIs a directoryInvalid argumentFile table overflowToo many open filesNot a typewriterText file busyFile too largeNo space left on d@ BX@`@B0@PX&PX.&P#3CX/@XXPXXPXC0$X&P/!5XPCX&PX.&P#3C@P@PXPA@ BX@Y@B08X@Y@B0('tP@ P$PA@ p&tA@h$PAPX@TB0b'tX@PXP@ PA@p&tAhPPX C0X#6AJP" Xy#4A@hXPA@ 0C('tP@ P$PA@ p&tA@hXPp(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(C@"p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@8$ɠ.B0,&ӡɠ9B ɠ0B$ CP@<'tPX PPA&t!&&C<юp(p(ЇX,`X(C'X( %P(C #4'C  #3&"C' 0   C # [,'   $Q@#4$P@#0X#ю p,pЇ$P@#0$P@#4@P@@dP@@ ,P@@ P@@!P@@"$P@@"PX&P$X&PX&PX.&P#3C%Q@"PX#,C.X@X.&P"X.$QCPX@PA PX@PA PX@PAPX@PAPX@PAPX@PA@"PPX'PC08X&PX@,X.". PX C06'tX & P & PX PA@X&t !$%C& & P P X&PX(#юp(XP@(P@,$!P@d%XP@4X0!$P@d%XP@PA@LX@PA@\# @TPA@Lюp(p0Ї$P@$P@PA@H'tPA@ `PX8P@^PA@L&tA@#7PA@" $ PA@A@X@ PA@%Q0C X4&P4XPACAюp0p(ЇAA\C0XX(PX PAC0:'x$PX P@PA$&xP@PA#5CC$P@ A@X(P@iPA@L$PA@xxC0TX@B0J@|P/PX J#7X KB0 XX@PXX@PXPPAPXPPAvPX@C0ZYB YB0JX B>YBYB0.X C"PPA@4PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@H&tX@xl<P &<<P &<$ $P&&$P@FPA B  cp ? Cannot unlink source file. 0123456789ABCDEFCDEFLOSXcdeflosx . . . . n  @ 4B DJ9A@\$Q@@PA@L't$P@P@PA &tюp(p,Ї @ P@PA@\@PX,PA@A@C0PA@#2" X@PA@@PX0PA@A@C0PA@#2" X@PA@A@X@ PA@@P@PA@X4C0NA@0C0.PA@X@PA@$P@ $C# A@xPA@ @ PX0PA@\C2X@PA@$P@ X4#8$PA@T#$C`A@C0PA@#2" A@X@ PA@XPA &" P@P@PAn!6P@$X@ !([@&" P@ &P &P&$P@@l#юp(p(ЇP &&#2" X(X$2P && && &&&X(ʰX$H && && &&'X PPA'X dPPA'X dPPAv'X dPPA^&X(XPPAF@P#юp(p(ЇX($!4n#m#юp(p(ЇX(&X, B$X$'xXP PA@,PA@Xp(ЇA@HP@8A@@P@<%Q(C0X,&P,XPACюp(pЇlX & C0*hBXP@PA@0Cx&CXPAp@@PPA@CP@*PA@0C2X@8C0HX@H@MY@8!3# @NY@AC0@PA@$P@ X4#7$PA@T$#ю p,p(ЇX@B0(@P@PA@X@P@#X@P@$P@'t$P$PX@PA@&tюp(p(ЇA@ C0 !$$C.#&C$ P@PA~P@PAnPA@ P@PATPA@ P@PA:P@PA*P@PAP@@#юp(p(ЇX( :C0 !4 C&"$ & #юp(p(Ї@PA@\@PA@\$PA@Tю,$$0 &# &X,$0 & #юp(XX#%!Q!Q$QC@"p(ЇPX(PA@BX,P$X,PX,P #юp(p(Ї@ PA@P#юp(p(ЇX,$PX(PA@P$P P  #%#$#юp(p(Ї@PA@#$# #юp(p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0$ PPA@P#@TPA@0C2$ PXPA@P#@kPA@0#юlpp(Ї$X( &C0ɠ/!2Ҭ&"  !6@C. $ @#юp(C@"p(ЇX(P@PA@0X@4Y@ C X@4P@PA@0C"X@4X@ @P@PA@0юp(p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@ ! + E W i y   ' 6 G [ o !Error 0Not super-userN'tPPPA@&tB0VȾ   B0< tB00 tB0$ yB0 C0 !4 #Cx#юPppXP@XP@!$P@%XP@X!$P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@!$P@%XP@XP@X!P@%/dev/ttyxcannot stat was y was n cannot change mode /dev.X Y@B0 'tX PX,PX(PAT&tC$P@ @PA@LAvюp(p(Ї$P@PA@P@C$P@ @PA@LA$$PA@xP@'tP@PX@PA@&tB0@Y@B0x @X@PA@@P@X@&P@ #2"X@'P@$@P@PATP@#CF@PX@PA@BA@C0X(CPA@A@ 9X@PA@yX(C6$PA@xxC0 @2PA@L$p(p4ЇA@pP $ PXB@X 0PXX@XX@X P %QCюp4p(ЇX(X, & B0&!3$#"$#юp(p(ЇX(0 &&#2" 'X, &&#2" @0#юp(p(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(p(Ї'tX(PA&tPA#юp(p8ЇX8XPX8XP [@PPA@4PA:XwPB$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C #3&"C' 0  9C'@p  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb 'xX(P X@ PPPA@&x #3&"$P@ CC@P@&Y 3XD X@ #:Y@ #&X@  [@ X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@ B YBYB0.X C"PPA@ PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp [@#,X0B0 &# PA@H" C P&A@H"  &# PA@H" X(#юp(p,Ї X@B 'tP & PX PA@&t'P  #%C & P X&P#юp(XX]P@xp(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@|%XP@$XP@( !P@|%#!P@|%$XP@0X,!$P@|%XP@8XP@<4!P@|%XP@DXP@HX@!P@|%XEK:@FL;AGM<BHN=CIP$P$P @ $PA@ P C0hX#%CX:!8$Q0PXB0XX&PZ<XB0X $ZP C|X Y8B0^X&PZ<$X8P@$#юp8p(Ї'tPX,PX(PA@&tT,#2&#+  #юp(p(ЇX(P@"XCX P&A " юp(p(ЇX(X&'BX &T@"X!3&" X PA@Hюp(p(Ї"tX( C0 &&" / &X,$ɰC &(p(Ї'tpPX(XPX(XPA@&tX@ #<P &<<P &<$ $P&&$P@# FPA B PA &" P@#P@#$PAn!6P@$X@ !([@&" P@ &P &P&$P@#(@##юp(p(Ї" &&#2" X(X$" && && &&&X(ʰX$ && && &PX PPACXC JYB0.'tPX PPPA&tX PCPPA C CfYB0ZX[8X<[ B"X'tP & PX PA@&t'P  #%C & P X&P#юp(XX]P@ p(ЇX,X(%Q CNX C06'tX & P & PX PA@T&t !$%C& & P P X&PX(#юp(X@X#X@ZP@P@ %X!$P@ %X)!P@ %XP@XP@!P@ %XP@XP@X!P@ %M:/ESTEDTDay Mon 00 00:00:00 1900 SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec0123456789ABCDEFCDEFLOSXcdeflosx^  l^  lJ@X\!9$Q\@P`$P8X8Y\CD$PX`&P`XPAC0X`XPX P $Q8C'xP (PX@#\($P@#\PA@&xX@#\CT #5X@"4#6X@"LC0X\C X P@PA@P@X PA X@"LB02'xP (PX@ ($PPA@&xX@"pC0X@"lP@ PA@U@#PA((" #PA(CA@4юX!$A@ C$X &XX@ &P@ Ї X,P%Q0C0(X&XPA8XPX&PCX,XPAXPю p,p,Ї X@@(X @PX@&P@#)$Q@$P@X#ю p,pЇ$P@$P@@P@@P@@P@@`P@@P@ @P@@(PX&P$X&PX&PX.&P#3C%Q@(PXC.X@X.&P"X.$QCPX@PA PX@PA PX@/dev/ttyxSorry. Name: Password: No directory /etc/utmp/usr/adm/wtmp/etc/motdYou have mail. /bin/sh-No shell. Login incorrect. /etc/passwdBad /etc/passwd   !"$(0`/dev   0B$ CP@x'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb|'xX(P X@xPPPA@x&x #3&"$P@xCC@P@&Y 3XD X@x#:Y@x#&X@x [@tX0B0 &# PA@" C P&A@"  &# PA@" 'xXP PA@,PA@Xp(ЇX(Z,$PX(P@X,P@$P@X(BVAC0L$PA0C0<'t$ P@P$PA@&t't$P$P$PA@x&tюp(p(ЇX@Y@#$$C X@&P@Z@X#юp(p,Ї A@P@PAPA*#6AV#%Q@X#ю p,p,Ї A@P@PAJPA#6AT#%Q@X#ю p,p(Ї@PAPAC0A$#3[aghntzio@CX@ $@# &" ,P@PAbB0,,PA> :C0 X@PX@P@@P$PA@T't$ P@P$PA@&t A@ P C0 X!$A@ (#X &C$ &XP@@P$PA@T't$P@P$PA@&t PA@ &&!2"' B0' :B0PA$P :C0X $, P &C&$P :C0X$, P&C&PAPAPA@ PC$'t$ PAPX@PAPX@ PAPX@PA@(PPX'PC08X&PX@X.". PC$PXB X@XX @ZX @ZX @ZX @ ZX @ZPX@XP@X@XP@X@XP@X@XP@X@ XP@ X@XP@$PPX'PC0&X XT!3$#$ZPCXPXaX@$QC@#юpC@"p(Ї dL'xXP PA@,PA@|Xp(ЇX(C.'tP@ P$PA@&t$PA@|X(B0'tP & PX PA@x&t'P  #%C & P X&P#юp(XP@ !$P@%XP@(XP@,$!$P@%X!$P@%XP@4P@80!P@%P@hXP@lXd!P@p%Usage: ln target [ newname ] No directory link Can't link SXcdeflosx^  l^  lJ$PA@&t$ PA@юp0p(ЇX,PX(PA@LP(X(BX(PA@$#$#юp(p(Ї$#юp(p(Ї$X( X., -#4$CZ(&!3$#Cюp(pЇ$A PC0:XC0@(PXPA~B0X&PCXC0 @*PXPAD!4$ C$P !5XC'tPPXPA@&t$@,P X C0Z ұ &"X $ 'tPPX &PA@&t'tPPX PA@&t$#юP  C$ &C$ &CX C0X C B0$ &C$ &$ &$P&^!8&$ @&X&P C0dCZ&]B0XX C( &C00$ &&C@P@4&Y 3XC@PAZюp0p4ЇX4C06$PX4PA@ hPCX4P@PA #$P@P @P$P@$P@$P@$P@%P@X@&P@!8X@&P@T@!4A@XU B'tP@PXPAA@ tXPA@X PA@ !4F't$P@NPPA@ &t't$ P@PP$PA@&tA@ 'tP@[P$PA@&tCюpp4ЇX@P$P $P@mPA@LP@BzX4X8A@ P C0XC XX &C$ &X8 &&!2"' #7X4& B ' :B0$P X@PA@ $P@$P@$P@X #юp4p(ЇX( :C0:&B0('tP@yP$PA@&tA@ C$ & #юp(p,XP@@XX@#7X4PAHC4X@!7X4PA0Cюp4p,Ї X,X0 &C@ &&"<$CF&B0$C2 C0$C"$C't$P P&PA &t#6 C$C't$P P&PA&t#6 C\$C&#2"CX & !2"&CB't @#5$P#$P P&PAl&t#3C #'PPA#4$C8 -$C.@PAC' , X@TCю p,p(ЇX(X,!4$C2ӽ& 'C0 & !5X0C"X0#3$#$#юp(p(ЇA@$P@dX,PX(PA@A@$PA@юp(p(ЇX@C0"X@&P@!8X@&P@CX@C X(P@!P@%bcnv$*.[\4>*TTUnknown flag RE error Can't open %s %s:%s RE botch %s:%l:%s:%s 0123456789ABCDEFCDEFLOSXcdeflosx ` l > ` l > @DXPB0$X P@PA@$ PA@'tPXPPA&tCC@PXPAB0.'tPX PA@,PzPA&tC@PXPAT&t#юp(p(Ї'tX(XPX(XP@'PA&t#юp(p(ЇX(X@'#3$#$#юp(p(Ї'tX(XPX(XP@'PA&t#юp(p(Ї@' X@'  'tX(XPX(XPPAR&t#юp(p,Ї X,X-!6X,X#PX@'TX,Y#3$#$#ю p,p(ЇX@'`X(Y#3$#$#юp(p(ЇX(XPA#юp(p0Ї$P'tX@'tPX0XZ@'XP@P  &PAC0 HC0$X +.#3&" /C0/&$  +.&#7ɠ #&C$'| PXP XPXPPA8&|B0XP@PA@&CXPC$#юpp(ЇX(.B0X,.#4$CX,PX(PA #юp(p0ЇX0PX4P C$X4&P4X4C0 C` C0,X4&P4X4PX0&P0X0PAC$CX4 #PA@X@C0X@P@PA@X@C00'tX@PX@PA:&tP@PA@@P@PA@юp(p(ЇX,'$0 $B0 #юp(C@"p(Ї@dPA@ $#юp(p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,v|kqw}lrx~msyPAB0.'tPX PA@,PPAl&tC\@PXPAnB0.'tPX PA@,PPA"&tC@PXPA$B0z$PX C0>X -C0XPX ZPX &P C'tPXPPA&tCCL@PXPAB0`d!5@C$b!5`Cc!4 #$P't$PXPPA&tCC@PXPAB0NX@''P@PABPA#2" 't$PXPPA&tCC@PA@&tA@ y!4$P #7A@ " XC0X0XPAz#$#юp0p(ЇX0+B0X(Y,!#$#$C6X0-B0X,%!Y(!#$#$CX(Y,#3$#$#юp(pЇ$PPX&PZ@'XPC0v@)PXPAC0Z@+PXPAB0 X@'tX&PPCXX&PPChX$PX!4$ CA@#:PA@C'tXPPXPA@&t$P@.P XZPC0XX$#$X ##$#$C@P@&Y 3X  P !2&CX$C C0,X4&P4X4PX0&P0X0PACb$C\X4&P4X4PX0PAHC: #3$#$C,C@P@&Y 3XX C0p$#юp0p(ЇX,!4$C:X(C0(X,PX(&P(PA@#3$#C$#юp(p(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(C@"p(Ї@'PA@<#$# #юp(p(ЇX(C'X( %P(C #4'C  #3&"C' 0   C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@ |&x #3&"$P@CC@P@&Y 3XD X@#:Y@#&X@ [@X0B0 &# PA@ " C P&A@ "  &# PA@ " X(#юp(p,Ї X@dB XlXPPAB0't$PX@P$PA@&tюHphp0Ї$PAP !4$CX :C0 X C0X #6AP " CAP !2"X C08X C0,X C0$X X&PZ0AP X'xXP PA@,PA@Xp,Ї @'xPA@X,P@'X0P@'$P@'X0XP@"@4PX0XPAB0,X@"&P@"X@'&P@'X0XP@"#$P@"X,Z0$PX,C@6PA@$ PA@APB0@IPA@$ PA@X@'Y,C@TPA@$ PA@'|X@PXP PfPX@"PAp&|ю p,p0ЇAP @iPABPPAB06X@"'P@"'tAPX Pf@PXPAB0JX@''P@PAPA#2" 't$PXPpPA@&tC0'tX PXP@PA@&t$ PA@юp<p(ЇX(X0@'l$/P@"X,X0@'l$/P@"X0X0@'l$/P@"X@'l&P@'l$"#юp(p(ЇX@'Y@'!@ C X@'&P@'Z@'X#юp(p(ЇX,P@'tX@"C0X@'tP@ PA@$X, C0&X, /!8X, &P@'p&CX(PX(XAX@"C0& #:@PA@&PZ  CX Z$ 'tXPPX &PA@&t'tXPPX PA@&t$ PA@X#3$#$#юppHЇ(%P$$P@VPA@P@'A@C0 B0P A@X :C0X &P C0CX $XHPPAB0bA@:#7C0L" P A@X :#7X &P "X $PA@,P$#C"X@'PA@x$P@'X$#ю(pHp(ЇX(X, B0&!4$C&C ##,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@)$ɠ.B0,&ӡɠ9B ɠ0B$ CP@)'tPX PPA&t!&&C<юp(p(ЇX,*X(C'X( %P(C #4'C  #3&"C' 0   C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb)'xX(P X@)PPPA@&x #3&"$P@A@ &tC*@dPX,PA@ #$##ю p,p(ЇX(X & C &X B'tP & PX PA@ &t$P P юp(p(ЇX,?X,$юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@ &t !$%C& & P P X&PX(#юp(X!$P@%X)!P@%XP@tXP@xp!P@%XP@XP@X|!P@%XP@XP@XCX #6A|P " X0Z$$#юp0p0Ї$PX0ZX.4Z.#4$C X&PZ0!3$#Cюp0p(Ї$Q@A@#юp(p(Їx#юp(C@"p(Ї@LPA@#$# #юp(p(ЇX(%Q C>'tP & PX PA@p&t'P  #%C & P X&P#юp(X)!P@H%XP@(XP@,X$!P@H%XP@4XP@8X0!$P@H%XP@@XPvPA&tC$CX#8X@''P@'X #юp0p0ЇAP @lPAPPATB06X@"'P@"'tAPX PPA&tC$CX#8X@''P@'X #юp0p,Ї X@"C0@oPA@$ PA@X@"&P@"@PAPPAB0"'t$PA@PPAV&tC X#8X@''P@'A #ю p,p<ЇAP@PXPAB0FX@"'P@"APALP@PXPAB0XCC<@PXP# @PA@юp(p(ЇX(XPX(XXAC0$X(XPX(XXA#3$#$#юp(p(ЇX(XPX(XXAB0 X(XPX(XXA#3$#$#юp(p(ЇX(XPX(XXA#3$#$#юp(p(ЇX(XPX@'pPA#юp(p(ЇX@'tP@PA@$#юp(p(Ї'tX(XPX(XPX@'|[@'QPA&t#юp(p(Ї'tX(XPX(XPX@'|[@'Q$#%#юp(pЇX@'PXPA@`CXP@bPA@$CXPXPXAX@'`@#4$CU@B@X@PA@DC@sPA@$CPX@P@X@'P$PXYC X[#$#X[P$PXPA@PCXP@PA@$CXC0 't$PXPXPA@0&t'tXPPXPA@&tCXP@PA@$C^XPA@x$X C . HC0@P  &PAC0)CC@P@ &Y 3XD X@)#:Y@)#&X@) [@)X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@ PB 'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X@"`X#X@"`ZP@"`"\P@"%X!$P@"%XP@"hXP@"l"d!P@"%#!P@"%$XP@"tXP@"x"p!P@"%XP@"XP@"X"|!P@"%XP@"XP@"X"!$P@"%XP@"XP@""!$P@"% X'PP!X'PP@"%XP@"XP@"X"!@PAB04A@C0>X@@P C02X@&P@@P:#;X@Y@LCCX@@P C0,X@@P C0X@@P B0X@&P@Y@LCCX@'P`X@@P.B0\$Q@@PAB0@PA@ CC&X`@P !;@PA@ CC@PA@ Ct$P@X@Y@LC0X@@P!+@1PA@ C$Q@CIT#:@7PA@ # @@PA@ X@Y@LC2X@&P@@P!+@"$P@dCC@P@&Y 3XD X@d#:Y@d#&X@d [@`X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@ B X@@P\!6$Q@#$Q@X@Y@L!$CFCX@&P@Y@L!$C&X@@P B0 A!3$#$#ю p,p(ЇX@@P/B0z$Q@X@&P@@P C0X@Y@L!$CBCX@@P B0 X@&P@Y@L!$#CCp$#юp(estructexterngloblbyteeventextdatabsscomm%s: cannot stat characterdirectory block special (%d/%d) cannot open executable pure executable separate executable old archive data c programdata c programfortranassembler programroff, nroff, or eqn inputassembler programroff, nroff, or eqn inputassembler programdata commandsprobably text with garbage with garbage 0123456789ABCDEFCDEFLOSXcdeflosx T ` AX@,ɰ/B0&U@0#$X@(# 'U@(#X@0P$PA!9Y@,!3ATCCX@0CX@,CAɰa!ɰz##A"X@(U@0B X@ X-  #4&CCNP@ !4$CL  U@(!U@0##A C,C@P@&Y 3X,X#3AC<юp0p(ЇX@@!:X@,P@@P@'tP@DPX@XPA@!H&t'P@T#%C\D,PX@PX0A&t#:@PAAvюp(p(ЇX@PA@ $P@t%P@%P@ @P@x$P@ A@!X@x&X@x& C' 0 C'xPX@xPA@ &xPA@ $PX@xPA@!P@X@8PA@ XX@8P@0P@(P@,X@8'P@4юp(p(ЇX@p#3AZA A|A !3ABPAA C0$ &X'P &CN$ & C0 &C4$ &C(CXC0X !3A4XCAP@ B0x$ &C$ &$ &$PA^!8A$ @ C0d&$Q CNAh]B0XXCb$ &&C@P@4&Y 3XC2$@A\ю p@p(ЇX(C0>X@$#4$CD &&#2" X@P@C,X,Y@(!4$CX,XPAz$P@X@$C0P@|PPACx !$P@%!X'PP@%XP@XP@ X!P@%TMP !=acdefgiklmpqrstvwF4T\j8r>Xft $'+-.p(p(ЇX,X(%Q CNX C06'tX & P & PX PA@t&t !$%C& & P P X&PX(#юp(XP@TXP@XXP!P@\%%s 0123456789ABCDEFCDEFLOSXcdeflosxNNNN $юp(p(Ї@ PA0@ PA"X(PA$ PA@юp(p(ЇX( PA@#3&" юp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ \$ɠ.B0,&ӡɠ9B ɠ0B$ CP@ `'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C #3&"C' 0  9C'@   ;C # [,!A& &!4'C$Q@H!5$Q@D B0r'$ P@L$#юp(p,Ї ȰDX@Ӽ  B0PPA\#7P@|$CB&B0$C.PPA,#7P@|$C&B0$#юp(p,Ї X,X0 &Cl &&"<$Cr&B0$C^ C0$CNP@$CB't$P P&PA2&t#6 C$C't$P P&PA&t#6 CV$C&P@ C>&P@ C,&#2"CX & !2"&CB't @#5$P#$P P&PAn&t#3C #'Y@C0PPA#4$C0B $C$AC/?^<PF $*.[\*h.vT@jj. r?/bin/shsh-t!/tmp/ed00000  0 '$$0 $$ ?X,CX(d#6X(D!6'- Cb d'xX(P X@ `PPPA@&x #3&"$P@ `CC@ P@ &Y 3XD X@ `#:Y@ `#&X@ ` [@ \X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@ <B X6C2'tXX@ HPXX@ 4PPA&tC\X &D!AC>X@ DP@ &&#8D!Al"D &&#2" ю p,p(ЇX(X,X0C &&D!A " #юp(p(ЇAbAA~!3AA8X@#B0 <- &$ &&CH C: C02\ & 0 & 0 &$Q@l#& #6 `B4,'xXP PA@,PA@Xp(Ї$Y(C&Z,XP@PA@&C$ PA@4$PA@юp(C@"p(Ї,X( C0ɠ%#8PA@4C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@`$ɠ.B0,&ӡɠ9B ɠ0B$ CP@d'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C' X 'xXP PA@,PA@dXp(Ї%Q(C \X,&P,X-B0@X,Xs!7$Q@ PCX,Xa!5$Q@ TCX(#@ P,$P(X('P(C06X,&P,X & #3&"P@ $A(CX@ XP@ RPA@lюp(p(Ї@ |P@ PA@C@ \PA$CX@ `CX@ Q@ XX@ TC0"'t@ PP@ gPA@l&t Cj$CdX@ Q@X C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@ x%XP@ LXP@ P H!P@ x%XP@ XXP@ \X T!P@ x%XP@ dXP@ h `!$P@ x%XP@ pXP@ tX l!P@ x% P @`n(.Total %d can't find%4d %s %4d %s can't open%4d %s name too long -- 0123456789ABCDEFCDEFLOSXcdeP & C0L & B0'$ P@PC,'B0"$PXPPA6X@ CX@t &Q@t #ю p,p(ЇX(X(!@PAA P@ Y@B0X@ V,P@  CY@ !7  CX,B0jX@ C0&'t@"P@PX@PA&t$P@ P@'t@!HP@PPAX&t C@X@ B&'t@"P@ PX@ PA&tP@   #юp(p(Ї't$PX(PX@PA@!x&t'tPX&C@  P@,& C0`PPA^PPARPPAFC8B.P@,&PPA(PPAPPA#A(юp(p(ЇX(X,'XC X P P&" юp(p(ЇX@X CX X&P$ &X &P &C)B0.XC @ P@'t  P@ P$PA@"&t#P@юp(C@"p@ h$p@ h$XX]P@X@X#X@ZP@P@%X!$P@%XP@XP@!P@%XP@P@!P@%#!P@%$XP@XP@!P@%XP@XP@X!P@%XP@XP@X!$P@%XP@XP@P@%XP@@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cbh'xX(P X@dPPPA@&x #3&"$P@dCC@P@&Y 3XD X@d#:Y@d#&X@d [@`X0B0 &# PA@4" C P&A@4"  &# PA@4" X(#юp(p,Ї X@DB C # [,'$$0 $$ ?X,CX(d#6X(D!6'- CbH'xX(P X@DPPPA@X&x #3&"$P@DCC@ hP X@ PPPA@@&x #3&"$P@ CC@P@&Y 3XD X@ #:Y@ #&X@  [@ X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@XB 'tP & PX PA@&t'P  #%C & P X&P#юp($PAX@ P@$'|X@$PX@P X@ PX@PX@PA&|X@P@ 'tX@ PX@PX@PA&tX@Z@ &P@(X@Z@$&P@8'xX@(P X@$PX@PX@ PA&xPX@ P@,XZ@(XPAX@(P@0X@ P@4X@Z@4&P@8PA P@X0PA#8@PAxX0PAhю p,p4Ї$X@$P$Y8B Z4XPXC0$PXZ'tP & PX PA@&t'P  #%C & P Xt0'xXP PA@,PA@TXp(ЇX(B &$P(X(X@#5$Q(" @P,$Y(CFX(C Z,XP@@PA@\Z,XPA&Cюp(p(Ї$PX(PA@XP@ X@ CX(P@DPA@\CXA@@ P$PA$AB#3&"'tA PP@TPA@\&tX@ PA@@юp(p(ЇX@ 'P@  !2B@iPA@\$CX@  !4$C~X@ & !&U@ BP@yPA@\$CNX@ B @PPAXP@ $2C X,"P@ &C #юp(p(Ї$$X@ & C >PPA<$CX!2&C&C #юp(p(Ї't$PX(PX@ PA@&t'tPX,PX@ PA@&tC0@X(P@PA@\'tX@ PP@PA@\&tA@Tюp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,& pX@PA@P@X@#8X@P@ # X@PA@P@ X@#7X@ !<@PA@ A@ p$P@$P@$P@ X@ P@@$P$PA@B0P$PA@X@C04'tX@PX@PX@8PA@h&t%Q@CX@'P@B0$P@X@#YBYB0.X C"PPA@ PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@ &tX@ D<P &<<P &<$ $P&&$P@ \FPA B PA &" P@ XP@ `PAn!6P@ $X@  !([@ &"  PA@" X(#юp(p,Ї X@ TB #9X@P@C@KPA#8AvP@Cl@QPA#8AVP@CL@XPAC0@^PA 8X@C0@`PA#6 C@gPA#6 C@mPAn#;X@&C &C,""" P@AP\ CBC@P@&Y 3XCX@P@PA@ A@ pю p,p(ЇX($T@C0a!z!#$T@C0A!Z!# PA юp(p(ЇX(X@@$Q@@X@&P@U@!AX@ P@@юp(p(Ї$X(@X@!7PA0Cl !7$Q@DC(X@DC  PA\%Q@D"PAX@ &P@ U@B$ PA($P@ $P@Dюp(p(ЇX($T@C0a!z!#$T!P@%    [.<(+!&]$*);^-/|,%_>?`:#@'="abcdefghijklmnopqr~stuvwxyz{ABCDEFGHI}JKLMNOPQR\STUVWXYZ01234567897-./% <=2&?'@O{[lP}M]\Nk`Kaz^L~no|JZ_myjС !"#$()*+, 01345689:;>ABCDEFGHIQRSTUVWXYbcdefghipqrstuvwx 'xXP PA@,PA@ Xp0Ї$PX0C tX4XP@ AC0&'t$P@ P$PA@ &tA@ X@ sC0LX@ @P@ PA@ @ PA@:X C0P@ PA@ @ PA@ |@ @ PA@ |C*$Q't$P@ P$PA@ &tC|$P@ PA@ P B\@ PA@ }@ 't$P$PX PA@ L&t't0P@ PX PA@ &t@ PA@ @ (P@ @ PP@  &P &P&$P@ d@ D#юp(p(Ї ( h &&#2" X(X$ ( && && &&&X(ʰX$ && && &&'X PPA'X dPPA'X dPPAv'X dPPA^&X(XPPAF@ (#юp(p(ЇX($!4n#m#юp(p(ЇX(&X, B$X,$$0 &# &X,$0 & #юp(%$XP@ XP@ X !P@ %,6/dev/dfix/dev/drem%s cannot open %s %l blocks %l inodes bad free count bad free block (%l) read error %d count = %d; errno = %d 0123456789ABCDEFCDEFLOSXcdeflosxn|n|ZP@C@sPAH#;X@P@CZ@yPA"#;X@P@C4@~PA#;X@P@C@PA#;X@P@CX@P@PA@ A@ p&C!9$T@#4hX@C0$PX@PA@$PA@юp8C@"XP@XP@!P@%XP@X!$P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@܀ 't$PXP@PA&&tCC!)!X@ dCtюXpxp(Ї$X(PA@ X,B8X, #5C X,$$C&X,&P,C%#юp(p(ЇX,C*X@B0dC4X@B0VC&X@B0HC'!)!X@ p'tX(PX,X@P@ PA@&tюp(p(ЇX0PX,PAXX,PX(PACA@A@xюp(p(ЇX('P(X(X,'P,X,&& B0 !4$C" #$#$#юp(p(Ї\!P@%XP@lXP@pXh!P@%XP@xXP@|Xt!P@%$b Illegal flag: %c Argc = %d %s%s Can't open %s 0123456789ABCDEFCDEFLOSXcdeflosxdp$Bdp$BPAX 'P X fPAX@$P@X@ C@P PACC:@PPAn@PXPAXX@'P@C,@PXPA0X@'P@C@P@$P@C@P PAX@$C0@P PACC@PXPAC@P@ &Y 3X Cj$PXfCbXZfX@XC02XZfX@XP@xPA@X&PCA@<юp<p,Ї $PXB X'xXP PA@BPA@Xp,Ї X,PX0'P0C0FX&XPA~XPX@ ,C0XX0PAvX&PCX,XPA:XPX@ ,C0XX0PA2$ PA(ю p,p,Ї X@ 4@ X @ 0PX@ 0&P@ 0C X@ 4&P@ 4$P@ 0X#ю p,pЇ$P@ ,@ PX&P$X&PXC 6X.X&PX.&P#3CX'P@ PX (C2X0h'xXP PA@,PA@(Xp,Ї X,C&'t$ P@P$PA@&tA@(%Q,X,Z0X &&#2" / @. &$ $Y,CdA@\B0D'|$P@P Z0XP@P@PA@0&|A@(PA@t&Cю p,C@"XP@P@!P@%#!P@%$!X'PP@%XP@XP@X!P@%arg count /bin/cpcp !$P@%XP@XP@X!P@%Usage: cp oldfile newfile Cannot open old file. Copying file to itself. Can't create new file. Read error Write error. A@A@xюp(p(ЇX(-B0X(!8X,$PCBX,PX(PA@B0$X(P@ PA@$PA@xюp(C@"p(Ї@ PPA@ (#юp(p(ЇX,$PX(PA@ P$P P  #%#$#юp(p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,X0XC0BX0XC0,X0XC0X0XB0X0XCX&PX0X&PX@&P@CX.0X&P X@&P@X'PClX0X&PCZX0X&PCHX0X&PX@&P@X'PCC@@P@X&Y 3XCX, B0X0X!9X,X0XX0X&PX@&P@ю p,p(ЇX(X@XC0X(X@XPA@'t@PA&t&PA@X(P@X@PX(X@XPA@X.&P"X.X&PCPX@\PAPX@`PAPX@dPAPX@hPAPX@lPAPX@pPA@ PPX'PC0X&PX@X.".PX@ ,C0fXXC0TXX$0PAXX$0PA PACFX@ ,#6$ PAAPxBX@\XX @`ZX @dZPXX@hXX @lZX @pZ PX@\XP X(\'xXP PA@,PA@xXpxЇX@ |P@@ }P@@ P@XxC *X|X-B0X|XC0$PTX.|X&PC0X|XCX@B0*$P@$XT'PTZ@X@CX@B0 $P@XT'PTZ@$CT$P@CHX|XP@ PA@A@xC1B BX@ XCX|&P|Xx'PxXxCXxP@ PA@A@x@PX|XPA"@PXX(C'X( %P(C #4'C  #3&"C' 0   C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@ &x #3&"$P@CC@ P@ &Y 3XD X@#:Y@#&X@ [@X0B0 &# PA@ " C P&A@ "  &# PA@ " X(#юp(p,Ї X@ PB X@Y@B0.'tP@ZP$PA@&t$|XPA$PA@ P@ PXP@PAC@P@PA#A@x't$PP@PA&tP@PAC 't$PXP@PA&t$C0PXPACT$PXPAXP@PAPC>P@PA4#A't$PP@PA&tP@PAC 't$PXP@PA&tC6$PXPA(XP@PAC 't$PP@PAx&tC$PPAP@PARCPA@ (&tC*@ PPX,PA@ $#$##ю p,p(ЇX(X & C &X B'tP & PX PA@ (&t$P P юp(p(ЇX,?X,$юp(p(ЇX(X 'P C>'tP & PX PA@ &t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@ (&t !$%C& & P P X&PX(#юp(X)!P@%XP@`XP@dP'xXP PA@,PA@4Xp<Ї$PA@ P@$PA@ P@($P X fCX $P@XX &P C$P$P P@@P@fPXC A@dPCbX fPAX &P X YBX fX@XC0xX fX@XP@tPA@X&PX fX@XPA@X f$P@XX fPAL@P@$P@CCA@dPX7B0rX fX@P  &#юp(p(ЇX('P@X@XPюp(C@"p(Ї@(PA@ #юp(p(Ї@PA@ P#$# #юp(p(Ї,X( C0ɠ%#8PA@ DC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$$ɠ.B0,&ӡɠ9B ɠ0B$ CP@('tPX PPA&t!&&C<юp(p(ЇX,LX(C'X( %P(C #4'C  #3&"C' 0   C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb,'xX(P X@(PPPA@ $&x #3&"$P@(CC@P@&Y 3XD X@(#:Y@(#&X@( [@$X0B0 &# PA@ D" C P&A@ D"  &# PA@ D" X(#юp(p,Ї X@(B 'tP & PX PA@ &t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@ &t !$%C& & P P X&PX(#юp(X@8X#X@8ZP@84P@T%X)!P@T%XP@@XP@DXC # [,'$$0 $$ ?X,CX(d#6X(D!6'- CbX'xX(P X@TPPPA@&x #3&"$P@TCC@ P@ <&P@PXH!P@T%  tJ%s %s }0123456789ABCDEFCDEFLOSXcdeflosx  ^ ^   ^ ^  $ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb 'xX(P X@ PPPA@@&x #3&"$P@ CC@P@@&Y 3XD X@ #:Y@ #&X@  [@ -!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb 'xX(P X@ PPPA@&x #3&"$P@ CC@ P@d&Y 3XD X@ #:Y@ #&X@ Bad file numberNo childrenNo more processesNot enough corePermission deniedError 14Block device requiredMount device busyFile existsCross-device linkNo such deviceNot a directoryIs a directoryInvalid argumentFile table overflowToo many open filesNot a typewriterText file busyFile too largeNo space left on deviceIllegal seekRead-only file systemToo many linksBroken Pipe 'xXP PA@,PA@Xp,Ї X,#@ tPA@A@X,C0X0XPAPXB~X B rX0XPA|BX'B P'tPXX@ P@ PA@&t@ P@ PA@'xP @ PPXPA&x$C P PA.CA@X0XPAB'B @ PA@P@ PA@@ PA@$ CB$ɰ#$ @ &"X@ P@ PA@XY 3XD X@T#:Y@T#&X@T [@PX0B0 &# PA@p" C P&A@p"  &# PA@p" X(#юp(p,Ї X@ B 'tP & PX PA@$&t'P  #%C & P X&P#юp(X)!P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@X!P@%%s %s differ: char %l, line %l %5l %3o %3o arg count cannot open %s [@ X0B0 &# PA@H" C P&A@H"  &# PA@H" X(#юp(p,Ї X@B 'tP & PX PA@&t'P  #%C & P X@ P@ PA@X@ P@ PA@'x@ P @ P@ P@ PA@&x'xHP @ PP &PAx&x'xHP @ PP &PAR&x'xHP @ PP &PA,&x$ɰC HP PAʰHC&C@ PA@A@@ PA@ю p,p(Ї$X( &C0$0!9#$$C$ C #юp(p(ЇX(X, 'C0&!6 @CX,& 'C0' !2" $ X(P@ PA@юp S M Tu W Th F S D H L P T X \ ` d h l p6RJanFebMarAprMayJunJulAugSepOctNovDecusage: cal [month] year %s %d %s %d %s %s %s %s %s %s Bad argument %s 0123456789ABCDEFCDEFLOSXcdeflosx4@4@@H&"@@@V@@WX@DP@\@AP@`X@ P@ PA@A>CaB BX@&C4@%#8@%&@%@%!7@%C08$P@&PX,XPA$P@&$Q,%Q(X(#A>X,XP@&X,& P#@ PA@AeP@&T't$P@&TPX@&DPA@h&tюp(p(Ї$PX@&PA@dP@&@X@&@#$C$P@&T't$P@&TPX@&@PA@&tX@&TeC0ZX@&TmB0,'tX@&PX@&P@PA@&tCX@&P@ PA@A$#юp(p(Ї'tX@PX@P@!PA@&tA<юp(p(ЇX@&P@!'PA@A юp(p(ЇX@& #9X@& PA@DX@&$#9X@&$PA@DX@&(#9X@&(PA@DA@Hюp(p(P@&,Z@&$P$#&C$#юp(p(ЇX@&PCX@&PX@&,PAC0$P@&P@%B0$P@&P@!jPA@lP@&$'xPX@&$PA@&xPA@$PX@&$PA@d #@!wPA@C.X@&DP@&HP@&DC'!)!X@<юp(p(ЇX(X, & B0&!3$#"$#юp(p(ЇX@&,P@!PA@юp(p(Ї@& C0>X(c!8@& C &'tX@&,PX(P@!PA@&tюp(p(ЇX(  P'xXP PA@,PA@Xp(ЇA@ l@$P$PA@ 4B0(:P$PA@ 4&P$PA@ 4X(C@PA@$PA@X('P(C0 X,&P,X,XP@ACюp(p(ЇAA<!8@ PAbA2C0cPAA" A4юp(p(Ї@dPX@PA@ \CP@%P@$Ct$PX@PA@ P@#@PAX@lP@X@dP@$PAX@Y@#8@$p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C  #3&"C' 0   C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@ &x #3& @&X('P@&X@%B06@&B0X@P@ /PA@AVjPAX@%AAA8юp(p(ЇX@%C0X@P@ NPA@AX(P@%юp(p(ЇAAC0"X@&P@ hPA@AnCAB0A6X@&#6AC0A C(X@&C0X@&,P@ uPA@Cr@&C00X@%PX@%PA@PU@%!(PA@C6rPA't$P%PX@&@PAp&tPA.C:cPA't$PX@&DPX@&@PA6&tCAnюp(p(ЇAЇ$Y@&C:Z@&XC0"Z@&XP@!:PA@&Cюp(p(Ї$Y@&CpZ@&XP@&,X@&,C0LZ@&$PaPAA  CX@&,P@!HPA@#PA&CA юp(p(Ї$C$PPA@&" X@&@PA@PX@&PA@P@&@X@&@CX@&P@!XPA@A2't$P$PX@&DPA@&t'tP@&TPX@&DPA@&tC &'tP@&TPX@&@PA@h&tCX@&(C0r't$P$PX@&LPA@#3&"U(C ' /!5$ " X(X( C0 /!3&&"  #юp(p(ЇA't@%P@%P@!PA@&tX@%P@!PA@X@%P@(X@(TPA@T't P &P@!PA@&tюp(p(Ї CX P&A " юp(p(ЇX(X&'BX &T@%!3&" X PA@юp(p(Ї'tX(PA&tPA#юp(p8ЇX8XPX8XP [@!PPA@(PA:XwP/PX PA$#юp(p(Ї #3&"A@ t' XB0 0  CP@PA@ P@#@PAX@PA@ $P@PA@ P@#@PA't$P@PX@PA@ &tюp(p(Ї'tX(P@PX@PA@ &tY(C0"X(#@8PAD@$PA6юp(p(Ї'tP@0PX@PA@ &t!4$C* !4$C  #@8PA@$PAюp(p(Ї$# @0 @H&" #$ "$P@CC@P@\&Y 3XD X@#:Y@#&X@ [@X0B0 &# PA@ " C P&A@ "  &# PA@ " X(#юp(p,Ї X@B YBYB0.X C"PPA@(PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@L&tX@%(x<P &<<P &<$ $P&&$P@(FPA B PA &" P@(P@(PAn!6P@!$X@! !([@!&" P@! &P &P&$P@(@(x#юp(p(Ї(\"$ &&#2" X(X$">(\ && && &&&X(ʰX$"T && && &&'X PPA'X dPPA'X dPPAv'X dPPA^&X(XPPAF@(\#юp(p(ЇX($!4n#m#юp(p(ЇX(&X, B$X,$!$P@%%XP@%`XP@%d%\P@%%XP@%lXP@%p%h!$P@%%XP@%x%t!$P@%%XP@%XP@%X%|!P@%%              %s in old archive format - to convert it type: arcv %s $Vr-w-s@x- r-w-sx-r-w-t....;binlibadmrmmailpublpdsys-include rat'sourcedocfextractgroupmesgmkdir mv newgrpnice nmnohupodoprpasswdprprofpsptxpwddrmcrmdirbshasizesleep_sortsplit]stty\su[syncteeYtimetrWttyuniqwcTwho"L.1(yyinit yyparse L10yyaccpt yyaccpt.orpp(Їюp(adcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfyyac$0 &# &X,$0 & #юp(XX#%!Q!Q$QC@"p(ЇX,#юp(ppЇPXp #3&"A@\'ӱɰXB0 0 CPXpPA@Bɰz!%C&ҽCXp#юPppp(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@($ɠ.B0,&ӡɠ9B ɠ0B$ CP@('tPX PPA&t!&&C<юp(p(ЇXx-DTd|mrxtdpuvnbaibad option `%c' one of [%s] must be specified only one of [%s] allowed creating %s cannot open %s %s cannot create /tmp/v2XXXXXcannot create third temp %s /tmp/vXXXXXcannot create temp file %s not in archive format usage: ar [%s][%s] archive files ... %s does not exist %s not found %s cannot open cannot create %s /tmp/v1XXXXXcannot create second temp phase error on %s %c - %s %3d/%1d%6d %-6.6s %-4.4s ../.e000170e000260ctm1actm2actm3actm3actm3a..2.memkmemnullttytty06tty1 mt07tty2mmt0$tty37rmt09tty44rmmt0:tty5df0dr05tty6>tty7rdf0rdr0)ttya%ttybswap4ttyc/ttyd;ttyeCttyfttygttyh6prSwrite]STTYRldgcc-39?@FLRAGMSByyparse.os:X`pЇp$P@%P@$P@$P@Pl@|P@X@C02'xX@P X@PX@P@PA@&xX@Xl&PlPX@X@&P@PX@X@PX&PXPP X CX@C00X@C&A@P@X@P@ PA@X@#A@P@#X@Y #4$QCtX P@X@P@%P@X@#5%Q@CX@C0X P@PA@XlX X@ PlX@X h&tC*@#PX,PA@d#$##ю p,p(ЇX,?X,$юp(XX]P@%p(ЇX,X(%Q CNX C06'tX & P & PX PA@h&t !$%C& & P P X&PX(#юp(X!$P@%%XP@%(XP@%,%$!P@%%XP@%4X%0!$P@%%XP@%update=wallxdetachxattachfdtabmtabpasswdttysutmpmkbootrc..3.-ar8stripfort*cat)chmod(cmpferrcomm%cpcpallcrypt"date!dd dfdiffdswduechoedexitfilefindgotogrepifkilllnloginlsmailemain.or8<p(ЇX,PX(PA@A@!4A@юp(iyadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfmainX@ P@X@XP@X PA@X X@X@PXXX.lYC0XX!$QCXXP@C$CRX@C$Q@@'PA@$P@XlBXlXX@PXXB0XXC0Z$QCX@C0.'tXlX@PXlXP@4PA@&t%Ql%Q@Cb$CXXP@CX@C0X@P@_PA@X@C0%P@C6C!)!X@C!)!X@юpp\tt6RL~Lstate %d, value %d, char %d character %d read reduce %d syntax errorerror recovery pops state %d, uncovers %d error recovery discards char %d  ) IYX)006L10001YBYB0.X C"PPA@PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@&tX@<P &<<P &<)adcladcr0r1r2r3r4r5r6r7r8r9 r10 %s, line %d, on input: %s \t \n $end %c yyyyyyyyadcladcr0r1r2eabort.ov8abort"alloc.o}(\0p(ЇX(&$X@d$T B0"X$T !6X P "    C XU@dCU@dBPA@ X@hP!4%CX@h& #:X@hXP P P@h@\X@hPX@hXPC:  P@dU@d#(X X@dPX@dP  &#юp(p(ЇX('P@dX@dXPюp(a]``$ &C #4 # #юp(atoi"crypt.o p,Ї X,P%Q0C0(X&XPA8XPX&PCX,XPAXPю p,p,Ї X@ @X @ PX@ &P@ #)$Q@ $P@ X#ю p,pЇ$P@ $P@ @xP@`@HP@d@P@h@P@lcrypt"csignal.o$ $P&&$P@FPA B PA &" P@P@PAn!6P@$X@ !([@&" P@ &P &P&$P@@#юp(p(Ї, &&#2" X(X$F && && &&&X(ʰX$\ && && &&'X PPA'X dPPA'X dPPAv'X dPPA^&X(XPPAF@#юp(p(Ї r11 r12 r13 r14r15sprfyydebug#yyv$yystate#yychar#yyline#yynerrs#yyerrfla#yyparse"L.1yypv L2>L3zyyval L4printf L5yypact yyact L6L8L9L10 yylex L11 L100r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfyyerror"L.1(L28printf yyline L3FL4'tP & PX PA@&t'ebrk.o`|4@X@8X#X@8ZP@84P@%9brk"end sbrk" errno chdir.o`$ XP@($!$P@% chdir"errno chmod.o`, XP@0XP@4o fstat.oa#( XP@,X(!$P@%fstat"errno getgid.oa5@/getgid"getpid.oaH@getpid"getuid.oaZ@getuid"gtty.oat(@ XP@DXP@HXP@LX P@P@!$P@%,profil"errno ptrace.oa8 XP@%Q@BX@&P@C@PPA@C%Q@BX@&P@$C@P$ PA@юp())puts"_iob@&t#юp(p8ЇX8A PP$P &#5$Q " 't@PXDp<ЇX@XD$P$Pӽ &CtXCӽ&ɰ%C0$P ɰ*#7X P &#ӽ&$Pɰ0B$ɰ9B X$ Pӽ&CX!5u0PɰlB0ӽ&ɰa!ɰz!#ʰCɰ[$PCX0[!4$P%Q4BP BJ @DTB0< #4ҽ&%Q BX&P#PA@CɰC0PPA@X<$P#X<$P C0 C0X0c#5$ &$#$#ю p,p(ЇX($ ^!3&&$C, #: @D @D# @D @D&C& ]C0: C0 @D @D&# @D @D& !4' #C #юp(YYy9i9 PA@&tP X, &P C %#X,#ю p,p(ЇX( B0JXC0BX C 6PP 'tPP PA@&t #7 юp(p(ЇU@#PA" юp(p(ЇX( C0.PA< PA@ #8X PA@$P  $P $#юp(writing )9I!6PA !9@PA@'|PX>>2Bscanf 9Y _sctab#D_doscan"_getccl"_error _innum"_filbuf _instr" ungetc atof fltused ftoa.o(fltused#(ftoa"doprnt.o3$pp(ЇX,X( C0ɐ%#6Ҝ&CC .'xX0P $P P@PA@&x$&ӑɐ-!3&&$ӝɐ9B ɐ0B$ &CP@$ɐ.B0,&ӑɐ9B ɐ0B$ _prfwidt$_prfprec$_doprnt"_strout _prf1"jprfhex#$ftoa fftoa.oW,p(ЇX,?X,$юp(ftoa"filbuf.oq,@p(ЇXYYi))9_flsbuf"_error P# XPA@ #7 #4 !3C-B0P$Q&X%QBX.X&P# XPA@%QCH+B0@%QX%QBX.X&P# XPA@%QB0!9C $ɰB0a!f#)ABFB |$Q ɰ!8XPC$ɰ B0XZP#XPP0!9!%Ca!f!$#QXCC.B0ɰ B0XC0$Q CCe#5EB0X B0~ɰ B0XC0X C0$Q &X%QBX.YYY0 p@Ї XH!$$CXH#$#XH&PXLf#6XLF!5$P #$P $P$/i@C XD&PD-+k@`@h@,i@C&h@0i@C h@l@4`@%QCh@8i@B h@m@<`@$QCX #5XQ$P/`XYChm@@`$QCh@h.m @D*`@h@Hi@!)h@L`@$QX C0rXCjXD&PD0XD&PD.X#X[P%PXYC XD&PD0%QC$PXYCxh@.PX0 CP@'|X0P@P PX PPAV&|!&&CC .'xX0P $P P@PA@&xюp(p(ЇX,X4ʠ X(C'X( %P(C #4'C #3&"C' 0  9C'@$  ;C # [,'$0 $B0X,CX(d#6X(D!6'- C`X4'xX(P X@PPPA@&x #3&"$P@CC@4P@x&Y 3XD X@#:Y@#&X@ [@#"$( !9@,PA@ @#4%CX B0N #: @P CPA@P !9  C  X P 't #5$P#PX P PA@&tP %Q C0X !8  # $P %CX&P#юp(Reading bad file )9write _iob gtty _sobuf malloc fflush"\_cleanup"_lastbuf fclose"close free fopen.o`p(ЇX, C0U@!$Cʰ" wB0PX(PA@Cr aB0P$PX(PA@CPX(PA@'t$P$PPA@&tC$PX(PA@ #$C8 r#8  #   #юX&P# XPA@+C0-#90BR9B J#CD&X%QBX.X&P# XPA@CFX#6 [PC0XPPA@X$P#X$PX#4$!4$Cp$ &XB0$X#8XXP#XXPC8XC0$PA@X`C$PA@X`$#юdpp,Ї X,X8X<$PX0cB0X4u0!4$P4$PX0s!4$P%Q BX&P#PA@ @DT#6ɰ#3C$PX0c!6YYyXD&PDX #4X#$YB0XD&PD.h@X/!`.+`@h@l@P`@$QC|X B0XC0XD&PDEXC [PXD&PD-dPXYC X$P"XC JX]0X.D&PDX]PX$PCXD$#ю p@AAAAAA AAA(X0#4 '| PX8P P PPA@&|X(#юp(0123456789ABCDEFCDEFLOSXcdeflosxTTTT9_filbuf"_error malloc read flsbuf.ozl p,Ї X0 !9@lPA@ C04X,'t$PP PA@&t$P CXB0B0B@xP$PA@!  C@P @P ClPA@ P !9  CB  $C(X C 'tPP p(h)9I9YIfopen"_iob _lastbuf creat open seek malloc.o`p(ЇX@B0X@P@X@P@@P@X@P@@P@@P@$Q@X(&$X@$T B0"X$T !6X P "    C XU@CU@BPA@ X@P!4%CX@& #:X@XP P P@@X@PX@XPC:  P@U@#(X X@PX@P  &#юp(p(ЇX('P@X@XPюp(error.oG0`Pp(ЇX(X@`#8PA@'tPA@PP$PA@&t~PA@юp()9I_error"_exit strlen write exit strlen.oW0p(ЇX($&#3&" #юp(strlen"strout.o  'xXP PA@,PA@Xp(Ї@ PA@P@P$PA@ P$PA@ P$PA@ %Q(C0X%P@P@X,&P,XPAlX@#)X@PA@ $X@#)X@PA@ $CA юp(p(ЇX@PA@ HA@юp(p(ЇX($PPA@ P@C&'t@ PP@ PA@@&tC4PX@PA@ XHC02X+C0&XIC0X,C0XJ#3 #&C$#юp8p4ЇX8$PXk'$'xXP PA@,PA@aXp(ЇX(C@PA@5V$PA@a@(PX,XPA@aLC@PA@5V$PA@aPX,X PA@iP@%C(X,X P@ PA@5V$PA@a$C"'tPP@0PA@e&t&C@X *B0,$Q PA@(!6X 4!8X(P(C4X(Y@0B X(BX !9@VPA@5VX(P@}PA&tX(P$C"C@tP@&Y 3X4$#юp(p(ЇX(XX #7X !B0HX XB08X B0&'tX0PX,PX PAl&t&Cz$XX@ `#9 PAb !8 & PAP C0:'tX0PX,P'tPA@A`&tPA&tX(P &#$#юp(p(ЇX(XX #7X !B0P@PA@e #8+PA@g !3AC !80PA@g CPPA P@PA@eCPACX P@PA@eCzC' !)!X@@PARCLX X !8 !3A:CBC!)!X@4@PAюp(p(Ї@PAюp(p(ЇX( #7  B0X P@PA@eC P@PA@eюpAF$Q@4B .@PPA@eX PA$ PA@g&CXP@UPA@eXHB X P@hPA@e&CXPP@qPA@e#Aю(pHp0ЇX0X4'C $P CpX Y B0X P@zPA$CVX Y C 6$Q X PX P XP X PX P XP &CX #3Cp$#юp0p(ЇX(PA<B0*XXB0XX#' ' !3 #$#юp(p(ЇX(PAC0$#3&"XPX Cz.P CLP C|-P A&tXP@*XP@*X P@*XP@*юp8p(ЇX@*X(B0X@* @ C0't$PPX@*PAJ&tX@* @&C02X@4&P@4P@*'t$PPX@*PA&tX@* @,!4$CNCF't$PX@* @,PX@*PA&tX@*#8X@*PA$#юp(p(ЇX(P@PA@eюp(p(Ї$Q@*A@a$X@%$P@%X@(P@PA@epX@PXjPX P X PP'tXDPX@PPA:&t#юp<p(ЇX(X !5$Q@*$Q@*'t$P@$PPA&tюp(p4ЇX8X4B0@PA@eT B0&# @PA@e#2$ CX 4B08X X#9X XB0X h .P P C8X ;B0,X XB0X X PP (p(ЇX(X,PPA8C X B0X,!# #юp(p(ЇX(!4$CX C< !4$ Cl$ CfX !4$CZX !4$CJ$CDC!)!X@tX !4%Q,X Y,!$##юp(p(ЇX(XX, B0*C0 C0#7#4!$#$CB0" C0#7#4!$#$Cb'#3#5!5!2$X B0" B0X0P!7!4$C !3$#$#юp(p(ЇX0X C0BX Y(B00X,CpKP Cd/P $ 'XPCHMP $ 'XPC,@PAC@P@&Y 3X PA@A` #юp(p0ЇX4X'tX0PX,P & PAF&tC0PAXP X B0tXB02ɰBjB ` P@PA@eC2B0ɰB0ɰB (İPA@5$ PA@gCBX #B02C0*C0"$PX PA@#\$ PA@g#CCX 3B0(X XB0X X/!`. #CCPX #6X !7h ` C0X 9B0 X XB0TX X/!`. #C@h `h`A@5$ PA@gC*C!)!X@@PA@5Vюp4p(ЇX,X(X0PA@(ɰe!3'xP PP@PA@e&xюp#4X #X  C0P@PA@eC&CX(P@PA.юp(p(ЇX(X (B00XXC0#B0XX #3$#$#юp(p(ЇX(XX@ `#3X X #6X !8$P@*e#$#юp(p(ЇX(PA#3 #$#юp(p(ЇX,X(PAfB0DX(XC &C.& C"C@P@&Y 3X0 #юp(p(ЇX(!$C:X(C$C,$C&$C C!)!X@#юp(pHЇ'xP X8#5$P#$PPX PAd&xC'tP@#HPX PA@&tX P0CDX CC@(P@@&Y 3XX PXX@ `C08X X:B0(XX:B0X X P XX PX C0$XX@ `C00X XB0 'xP X8PPPA&xC'tP@!LPPA@&tX PXX@ `!7=PC4XXP X #7X B0XX!5Q'tX8#5$P#$PXPPA &tюp0p(Ї$ PA@gX,C0 't@LPX0PC0@(LP@PA@eC@(LPA@(LP@ PA@eC'xX@*P PX@*P@ PA@e&x@ .PA@eCH@(LPAH@(PA@d'tP@(LP@ 6PA@e&tC@(PA@dP@ LPA@eC@ TPA@eC$Q@*$P@*$P@*P@*'x P X@*PX@*P@ aPA@e&x@ PA@eCd@(PA@dX@* 'tPX@*P@ PA@e&tC"@(PA@dP@ PA@eP@ PA@eC@(LP$P@P$$T#6@'P$X &P P,T,C0X!7$P$PX !B0$Q X,P,$T,C0,@'P$X@*&P@*Y@*#'X@*P@*$T,#6@!LP$$TC0NX$B0@$T,B06X +C0 X ,C0X I#6X J!6@'P$$T,C0"X PA@(2#9X$'#3X $T,#7XP(C.XX@ `!6X #XP(#XXP('tX(PX$PPAp&tPX$#8X$'B0$$T,C0BT,C0*XYC0'tPXPXPA@A`X(PX XX@ `#4$CX B0 B0X CX C0X PA@(#4$CX PB0(XXCX PA@-8C0X PA@-P XXPPA@% B ,X B0&X XYC0X X !4$C6XX P X XB0&X B0X XX- YC0'tX0P@#HPPA&tX P X P X(P$CC(!)!X@8CPA@-8!4$C~X,!L#7X,'!5Q0't%W0P@#HP'tPA@A`&tP(p(ЇsX([@*#a #@C #5@#@'xP PP@PA@e&xX(P@*юp(p(ЇX(Y,#$X(#X,#юp(p(ЇX(#4X !4$CX !4%CX #!4%CX :B0BPA@W#7X !%C^X X B0XX@ `#4%C6XX@ `C0X #6X !3$#$#X #юp(p(ЇX(X CX PACX #&X P# [ P@PA@eCX X, #"& B0^ B0R C&'t(XHXL B0XPP@PA@eCp$Q@4PPAfB0V P$'X [ P X C X$$Y B@#PA@eX C0(@,PA@eX PAr$ PA@g@5PA@eX PAJ'xX@4P XPPXPP@4PA@e&xAVX@4PA6$Q@4X P X Y B LX Y B0X P@>PA@e&CXPP@GPA@e$Q CCX@4&P@4P X@4&P@4PpX PXPX@4PX@4P XPX P@xPA@epAdX PPA&t#bPA@gX(P@PA@eюp(p8Ї'tXDP@!LP8PA@&tX8$XX@ `#5&X#=X@!4@X@*PX@*PX@*P XPA@WFP@(PA@dXPXPAPCBPA@WFP@(PA@dXP@(PA@dXPXPXX$ X$P XP &C@(PA@d't@(PA@d&tPA@W P &C@(PA@d@(PA@d@(PA@d !3 #B06 C0'tPA@W P$P:PA@V&tP &C$ PA@WFPXPX$PPPA@eXPA@"X PA@" B& B0:X XB0*XXC0X X P P @P X XB0^XXB0N$PX PA@&: #)X X$B0$XXB XX!X$PX PAP'tX PA@"&tPA@"h$P'tX PA@"&tPA@"h CXXB0.XXB0"MP %W XPPA CXXB0$XXYB0NP PAC$ P CX PA`C0XX!5X CvC$$ P CdPPA@"hP CNXXB0XXX@ PA@"P'tX PA&tPA@"hP  #юp(p(ЇX(X CPAP $P X X$X X'XXP X P X P X $ P X P X P PX'xXXPAJP X XPA6P$P$ PA&xpP P$P$ PApPAJC2C@ P@ ,&Y 3X,@ PA@5V #юp(pЇl$$XX PPA@(P 'tPPXPA&t'@X B0dӞ C ZXXB0JX@X !;@ PA@5VC??#B??#B # # ?## #?#.# #T?$$$ # # ?#.$ $@ $F ?$P # # ?$\$h$r $ $?$ ?$p0Ї$X0 -!6$$Q0#+!4$Q0h@$` X0&P09B ,0B$h l@$` hA&t!&&C<юp(p(ЇX,+ X(C'X( %P(C #4'C #3&"C' 0  9C'@%  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb*'xX(P X@*PPPA@a&x #3&"$P@*CC@%P@%\&Y 3XD X@*#:Y@*#&X@* [@*X0B0 &# PA@g" C P&A@g"  &# PA@g" X(#юp(p,Ї X@%B &tP 'tX PX P;PA&tP X P PACrC@ @P@ p&Y 3X0C/P XX P XP X-P$X X'X PPAPC.P $P X P X /PXXPX P$X X X'X X PPACX $!5X CC X #!5X CzX B0* B0X P  X   CDX X ( # XPPA@"hPP X B0`X *!8PA"CHX (B0'tP & PX PA@jD&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@jt&t !$%C& & P P X&PX(#юp(X@'X#X@'ZP@''P@'%X!$!4$P  C$ P '|X P$P;PA&|PAP *P C`X PAC0,(P X!9XP# [PCC@ XP@ h&Y 3XXX@ `C0X X !7PAfC\@C0XPAX !3P C4X B0XX:B0~XX X!9XX XCXX XB0H$P XXX PP 'tX P$P;PA6&tP PAC7P 'tX PXXP&PA&tP X PAP X PAP C0X PB0X B0 B0XXB0*XXQ  X P X   CXX#B0>XX C0(XX & X  X P  CCXX@ `C0X@PCX !4$P X Y !5X CFX :B0&X P X XP:P $P C8X %B0X B0"X P X P  CX B0X P  CX !9 [ P  CC@ P@ &Y 3X,X B0FX C$ [ P  C^%W P  CNC%!)!XXXX-X"]C0FXXXX,X"]!4&P &C C  #PX P&CXC0X.<'Z?DEBC=EDCB'!*.GHLadhn<<,4b "#ABCDGHIJKMPQTXZ*\`$hFGHKLMNOPU***nn !tn!tn$Arg countMissing temp fileCan't create %sr%d equ %d sp equ 7 rf equ 15 align adc extrn fltused dc fltused Missing temp file end sta r%d,%d(sp) st%c r%d,%d(sp) st%c r%d,%d(r14) Illegal operation on str db db bss entry %s extrn %s lm r8,L.%d-%d(r14) aai sp,L.%d br rf %s comn ds %d ends ds %d align adc sai sp,L.%d stm r8,L.%d-%d(sp) ldar r14,sp L.%d equ %d la r1,L%d bal rf,mcount bss L%d das 1 pure * %s = L%d * %s = %d * %s = r%d Expression input botch*@%d %s equ * title %s %s equ * Binary expression botch pure impur )B$AB0B*+,-.7HIJKLRSTVWXZdd selectint->ptrptr->intlong->ptrfield assign>>>>nameshort constantstringfloatdoublelong constantlong constant*r++*--r++pre--pre++post--post!un&*-~.+-*/%>><<&|^->int->doubledouble->int&&||&~double->longlong->doubleinteger->longlong->integer==!=<=<>=>p>=p=+=-=*=/=%=>>=<<=&=|=^=& for tests*/%=& ~=*=/=%?<<=<<\/\//\/\callcallcallgotojump condbranch condset nregsload valueint->charforce register@B darf,I Df,B tCf,#(J) GRCf,#(I) Q-taf,Q Df,B tCf,#(I) da,Q+ Pr*,I* C*,A GJPr*,I* C*,#(J) GRPr*,I* C*,#(I) GIPr*,I* Pr*,J* GCPr,I a,Q+ GCPr*,I* P*,Q+ cs,1 C,A GJcs,1 C,#(J) GAai,-1 GAD*,B GAKJD*,"(J) GAKIPr*,J* KCGAP*,Q+ GADf,B ar-,rf GAD-,B GAKJa-,"(J) GAKIar-,J KCGAa-,Q+ GADf,B Tar-,rf GATD-,B GAKJTa-,"(J) GAKITar-,J KCGATa-,Q+ GA,B GA,0(B) GAKI,0(J) KCGAdaf,Q+ ,0(rf) GA,A aif,Z ar,rf tC,A GJC,#(J) ai,Z D,B tC,#(J) KAGJCf,#(J) aif,Z ar,rf tC,#(J) ^\^\%^\&^\(^\)^\-^\.^\/^@0^\3^\4^\1^\<]\=]\>]\?]\@]\A]\B]\C]\D]\E]\F^\G^\M^\N^\O^\P^j^]\]\]\]\]\ ]\ ]\ ]\ ]\ ]\GAD,B dar,A D,B 'D,B KRD,"(I) KR'D,"(I) KAar,I GAGRdjt8('xXP PA@,PA@c8Xp,Ї X,C@"PA@$L$PA@c8$PX0XPA@hP@GhC(X0XP@,PA@$L$PA@c8@BPX0XPA@c@B"@DPX0X PA@c@C@:PA@$L$PA@c8X,C XX0X-B0BX0Xp!7$Q@BCm!6$Q@B#C$Q0%Q,C$XC08$ #6 &",$$@&C$PA@h8P@BP@BP@BX@B!5A@)8uctureNo code table for op: %sNo code table for op %d impur L%d dc y'%x' pure impur L%d dc y'%x' pure . %sRegister overflow: simplify expressionr%d%d(sp)%d(r14) lis r%d,0 ldar r%d,r%d sraa r%d,31 db dc x'%x' Illegal initialization l%cr r%d,r%d isaihi %c%s sp,%d $$$$$$$$$$$##r%F##r%F%F%F%F%F%F%F%F%F%F%&X&n&&h&n&h&&h&h&&&&&&&h*+,HIJ[\EEEF6F6EEEFTFTEEEEFTFTExExExExExExEEF$%&()/017:GGHnHnHJHJHJHJHJHJHBH "#$%&3;mHIJIvIJJGVGGKKK !FGNOPULLLLLLLLL8LM8(*+,-./017SpSSSST8TNSSSTdT*+,HIJXZXZD F!H#J%O&Q(S)U*W+Y,[-].b/gi0k1m<oq=tv>y{?~@ABCDEFGHIJKLMNOPbcfjD,B dar,I GAKJD,"(J) dar,I GAKIar,J dar,I KCGAa,Q+ dar,I GAD*,B tC*,A GAKJD*,"(J) tC*,A GAKIPr*,J* tC*,A KCGAP*,Q+ tC*,A GJC*,#(J) D*,B tC*,#(J) GBKIdarf,I C*,#(rf) Pr*,J* tC*,#(rf) KCGJC*,#(J) P*,Q+ tC*,#(J) KCGBdarf,I C,#(rf) a,Q+ tC,#(rf) GADf,B ar-,rf dar,I GAD-,B dar,I GAKIar-,J dar,I KCGAa-,Q+ dar,I GADf,B ar-,rf tC,A GAD-,B tC,A GAKIar-,J tC,A KCGAa-,Q+ tC,A GJC,#(J) D-,B ta,#(I) GAdar,I GA'D,B GAKJ'D,"(J) D,B KRD,"(I) HAHA'D,B KAC,A HAHA^p^ ^p!^F^pG^K_L_M^N^O^P_D,B KRD,"(I) KAar,I KACm,A Cm,A GRDf,B Cmf,#(I) GRCm,#(I) KAGJCm,#(J) GRKICm,#(I) GRCf,#(I) Df,B tCf,#(I) ,B ,0(B) KQ,0(I) KAdar,I KAtC,A GRDf,B tCf,#(I) tC,A GRtC,#(I) j_XGAtP,Q tP,Q AAAA$"$P@LPA@a$Q@B@PX<$CdXC0JX B08X B0('tXPP@NPA@a&t$QCX@BC0&'t@TPP@QPA@a&t$P@[PA@a@BPA@f@DPA@fX@B!5$P#$PA@c8ю p,p,Ї $PC &Q" X,$ C0A#5Cʰ C0FC &&!9" P@BC$<$!CX@&P@,B)D)D)D)D)D)D)D)D)D)8)8)n)))))))) bp L%d ldar r1,r0 bm L%d slaa r1,ladc lda r1,L%d(r1) br r1 ldai r1,L%d-adc sta r0,L%d-adc L%d ais r1,adc ca r0,0(r1) bne L%d lda r1,L%d-L%d(r1) br r1 *hash switch?? *+,HIJ------..*"56:a/./:0>00d=??AA=AA??<=BCDE=??@A=A?<=<= giopqrXZXfXfXfXUnimplemented field operatorDivide checkC error: constToo many termsToo many termsOut of space-- c1<<888888888<0A04A44,1,1 qqq<0$$((((((((0444,1AAA     <= >?@ A#&B*.C14D8<E?BFIMQTX[^bf il pt wz ~ dasasldaisxasmddsralslalntoxcclcclcclcclcclcclclclclclclclclclasmddsralslalnoxstbalbalblcclcclcclccC,#(J) KCGJC,#(J) a-,Q+ tC,#(J) KCGBdarf,I C,#(rf) a-,Q+ tC,#(rf) GBdar,I C,#(J) D-,B tC,#(J) KCGBdarf,I C,#(rf) a-,Q+ tC,#(rf) GATDf,B ar-,rf dar,I: GATD-,B dar,I: KCGATa-,Q+ dar,I: GATDf,B ar-,rf tC:,A GATD-,B tC:,A KCGATa-,Q+ tC:,A KCGBdarf,I C,#(rf) Ta-,Q+ tC:,#(rf) GBdarf,I C,#(rf) TD-,B tC:,#(rf) KCGBdarf,I C,#(rf) Ta-,Q+ tC:,#(rf) GA,B dar,I GA,0(B) dar,I GAKI,0(J) dar,I KCGAdaAAAAAA AAA$0123456789ABCDEFCDEFLOSXcdeflosxf.fffffPf<fhf.fffffPf<fhf@]PA@$L$PA@c8$ $P $P $P $P $P X@Gd ʰC &&" P@B#ю p,p0Ї@P X PX $XC08X & B0 &!9X P@B$CC&CXX $#юp0p(ЇX@B"X@%P@!5$P@B CzX@B#:X@B$P@BCX@B#4$CRA@c @ CAC0@sPA@$L CX@BX@B@ ~!9A@cP@BCX@B"B0*"PA!&" $7>t<$<==,;(???>?^?77778r8788.89:;P9:V:?9V68?$L%dL.%d%d(r14)L.%d+%d(r14)%d(r%d)r%dCompiler error: pnamepname called illegallyIllegal use of registerL%d%.8s%sNo match' for op %d b L%d * dirsw sai r0, cai r0, dc L%d dc L%d dc ds adc L%d equ * dc L%d dc L%d Duplicate case (%d)pow2 botch L%d L%d equ * %d: %cy'%x'Stack botchIntermediate file error dc A<<,39@N\aflry  "%(+/369<>JLNPUX[^`cgjmpsx}:,fiellcclcclcclcclcclcclbebnebnebebnpbpblbnlbnlblbpbnpbnpbpblbnlbnlblbpbnpbebnebnebebnpbpbmbnmbnmbmbpbnpbnpbpbmbnmbnmbmbpbnpY]0ZLZL X!X#]%X&Y0(YL)YL*Y+Y,Y-Z(.Z(/YL0YL1YL3\4\FZLGZLHZI[J[K\L\MZLNZLOZLP\tb\c\f\j\GAD,B GAdarf,I Df,B tCf,A GJC,#(J)f,Q+ ,0(rf) dar,I GA,B tC,A GA,0(B) tC,A GAKI,0(J) tC,A KCGAdaf,Q+ ,0(rf) tC,A GBdarf,I C,#(rf) ,B tC,#(rf) GBdarf,I C,#(rf) ,0(B) tC,#(rf) GBKIdarf,I C,#(rf) ,0(J) tC,#(rf) KCGBdarf,I C,#(rf) da,Q+ ,0(J) tC,#(rf) KAdar,I KAtC*,A KAGJtC*,#(J) KCGBdarf,I P*,Q+ tC*,#(rf) GAlr*,I GAxr,I* f,A GRf,#(I) GArf,I GRͣ(I) C*,A GRC*,#(I) ,A GAai,Z D,B tC,A GAKJai,Z D,"(J) tC,A KACf+  &CX@B #9@}PA@$L$P@BA@c #6X@B!2" P@ACr$P@BA@cCX@B!5$Q@$P@BA@cC$Q@B$C,'tP(PPA&tC 'tP'x2P)P>PA`&xPPAR&tCA@_Z$P@B=!5B0:A@_Z #; @ P@PCx$P@BP?P=PA&tC't$P$PPA&t#5-Cx't@PAP=PA&tCT't=P"P=PA&tC0't$P$P/PA&t#5]CC't$P$P\PAf&t#5_C't$P$P*PA>&t#5+CA@_ZC06$P@B*B0"A@_Z/B0$P@BA@cC,C$Q@B@PA@$L$CTP@BATCFX@&P@P@BC(AC  @ {#8 @ |B0#&A@cC#$ &"X@BC0@ $*%+ &,!'-"(.#)/06<B17=C28>D39?E4:@F5;AGHNTZIOU[JPVPA@D($#ю`ppTЇ4XTX@BX@BX@<$PX@BP@BP P PA@D$ $ 'xP $PP PA@J&xP@BP@BXP@<$$ P  #ю4pTp(ЇX(&PA@&FF &&#2"  #юp(pHЇ(XHB0(PA$PHXHX@HP$TC00'tX@<$'P@<$XPA&tPA4X P$X@<$'P@<$XXH[B0.'tPA@]>&tPA X@<$&P@<$PCXH#C0PA8XHd#6PAX$P #$P$PX#5XP$PCXHC0XH]#7XH_B08!Y$!4$PXHC0#X$!$QHC$TC0zXH>BTCFX$C:#7X$B0.X C0 X C0X #6X !4$QHX#6X!4$PXB04$PXH)B0$P $Q CY$!4 #4$PXC0PA@\PA@\P$XC0XB0Y$#:@PACTXC0*'xX$P XPX PPA&xC"'xP XPX PPA&x$T#4$P X $P X(P  #юp(p(ЇPA4P X(P $P $P X,P  #юp(p(ЇX@BX@BZ(P@BU@BB:PA@h8B0@cPA$PA@c8Q@B #юp(p(ЇX(X !3XX C0X $#8@pPATюp(p(ЇX,X #4$CX(ZB0lX0XXB0RX0XXB0>X #8X0XX#X0XXPX@<$&P@<$P$CB$CP $XL B0 X!6X!9@ PA@$LXC0fX@$P@BP@BA !9X@B[!3[ C't5P/P&PA&tCf't6P0P|PA&tCB@PA@$LA@cCC@P@X&Y 3XX @ #юp(p8Ї@P$P@B$F$P P$PA@_Z0!2$&0!9C $ɰB0a!f#)ABFB ɰ!:X@BP@BC.ɰ B0X@BZ@BP@B#X@BP@B0!9!%Ca!f!$#Q@B$Q C.B0*ɰ#6X!8XPA@$LPCp(pЇ`X@BP@B P\P P@<$X\PX$P$A C`X@B C0 B0X B0zA@_*(B0$ P CZ$ 'tX@BP P@PA@$L&tX@BC0$ @1PA@$L%Q@BPA@%nX@<$&P@<$PCX@BPAP$PA@%X@<$&P@<$PCPA@&FP $P X@BP X@<$&P@<$PCX@BPA@%X@<$&P@<$PCv$PX@BPA$PA@&F$ X@BP '|P$P @B$P XHC #7 !8@PA8CX@<$&P@<$PC*X #8@PA'tPPZPA&tB0X$P pPP$P $PX PXHPAdpX@<$&P@<$PC$CB #8@PAvpPPX P X PPA@XPdPApX@<$&P@<$PC2X #B0X X@<$&P@<$PC  !8@PA'|PX P X PPA@XP$PAd&|X@<$&P@<$PCX $B0X X@<$&P@<$PC~X !4$P X #6X !4$P XH B0lX P X P X P X B04X B0('|P$P $P$PmPA&|X@<$&P@<$PC'tPPXHPAp&tB0`X#3 # PpPPXX P XXPX PXHPApX@<$&P@<$PX C0X C0PX@<$'P@<$X'xX PA@\P $P$PPA &xX@<$&P@<$Pю(pHp(ЇX0@X@HC0TX4!8@-PApX4PAPX(P$P $PX,PPA(pC*'| C CCCC C% CCC #3$#$Ct !3$#$Cd !$#$CT !#$#$CD ##$#$C4 #$#$C$$C:C% ) X@ PX@<$&P@<$P$#юp(p(Ї$Q@BA@C0X #8@PA8%Q@BX@BP@BX #юp(pXЇ8A@C0LC0DP@$P4$P@GdP4PA@DB0$ P4X@B0$P0X4!7$Q0$ P4X4 C0&X4 C0X4 #9@dPPA@XP $Q X B0$XHB0XDP@ +PA@$LPA@]>PX $]XP $PA@P@B0X!6X #8%P@$Q$A@PC0XP@XB0fXB0ZXL !9@ >PA@$L%P@XH#6'P#P$PA@ TZ@BA@PCCVX B0XLPPAC6X #8X@B0'tXLP$PPA&tC$Q@BA@P$P@B #9@ VPA@$LPA@%nX@<$&P@<$PXX@<$&P@<$PPPA@XX !7'PCe#5EB0ZXB0R$QPɰ!8XPA@$LA@c&+C0-#90B9B Cpx#5XB00ɰB0X@B!6X#8XPA@$LȰC2l#5LB0"XB0A@cPC##A@cC P@BXB0$ @ FP@B# X@BP@BX#юp8p(ЇA@_ZY(#4X,#$P@BX0#юp(p(Ї$P@BX,X(C0<$Q@B'xP X(PpP@PA@a&x'CP@PA@a"PAB2X@B PPPA@$&|X@<$&P@<$PX@<$B@@PA@$L$PA@c8 B0$CX\XB0z B0tP@'t$PA@&F&tPA|X@<$&P@<$PA`B02$%Q\%QX\X[B0$XdPCbC #2&C B0C !3%$C #4$C/!4##$C C0A!4e#P@d$C C0Cz$Q@BCf B0>X\X(B.X\X1B X\'P\X%QC*CC@HP@&Y 3XT C0$X@H?PX@BC0$ B0J'|PX P X PPA@XPXHPA&|X@<$&P@<$PC(@PA CX@<$&P@<$P#PAX@<$'P@<$XX B0X C0&@PAX@<$&P@<$PCX$B0X#4$P$X$PA@XP %PPA'tPX PPA&tpXXPAPPX P X PX P(PApX@<$&P@<$P$PAzXC0ZpXX PX@<$'P@<$XP$P $P$P$ PA:pX@<$&P@<$PCzX(P$P $PX,PPA&|#юp(p(ЇX(X,X0X P X P PX #!9PA@XC"X $!8PA@X#X (!5XCюp(p(ЇX(X B0@X C04'|PX P X PPA@XP#PA&|# #юp(p(ЇX(X B0&X B0X #6X !4 CZ$Q X@<$&P@<$P'tPPA@XPPA&t#PAdX@<$'P@<$X#юp(p(ЇX(XC04C,C0$C0C0YA@$L$P@B$P@B$P@BX4 B0('x$P $PP$ PA@J&xC'x$P $PP$ PA@J&xX@BC08P@BX B0A@P@C00X@C0"X@B0tX@B B0`X PA@XP@PA'tX4 !7 P#@}PP@zPA@a&tAC~X@B#9@~PA@$LC A@ #5B0P@PA@]>&X4 B0\PAPpPP PqPP @PP@PA@apCX0C0X@BB0\L #7XLB0 X@<$'P@<$XPA@YNCNpX@<$'P@<$XXP$P $PX PhPA@$pPA@YN&A@P B0 BXB0XHB0X#6X#6XP@ C8XL C0,'t \ PP@ nPA@a&tC> C 8XHC0 !8XP@CXDP@ qPA@$LX P@BP@B\ #ю$pDp(ЇX(X X!<|@ PA@$L$A@!3&#P@A@C0P@X B04@ PA@$L'tX,P$P@ PAT&tC C"$Q@B P@PA@aCX@B C$Q@B@PA@a@PA@a$P@Bюp(p(Ї$P@B$'PAJB &#X@B P@BC#)@PA@$L#юp(p(ЇX(X@x#6$P@x#A@c !4%C C@PA@$LP@B%CA@c C$ C$ C$C$ C$$&B &0B7B  A@cCP@x Cj$ CdX@B!5$Q@$P@BA@cCDC@P@&Y 3X<C@(P@8&Y 3X #юC0B0X\XZ#4$PXXPXYB XYB0X@HC0 C%PC$$PC@P@&Y 3XX\XB@TPA@$L$PA@c8X\&P\PXX&PPCx%QX\'P\XPCP@$PA@X@<$'P@<$XCX\Xd#5aPCB0XPA@CX@<$&P@<$$PdPCf$PA@%X@<$&P@<$PCBB0LCB0@$PA@CC@ P@L&Y 3X,XPA@C0@hPA@$LC@xP@&Y 3X8$T#5PAT#8$PPA T#8$PPAj$TB0zXH3!3$#XH4!2$'t$PPXHPA&tB0<'|PX P X PPXHPAV&|X@<$&P@<$PC$P#7X$B0@PAd$P$X$PAPPAZ@PXPXPX#4X$# P X C0X #7X B0#6X$!4$P $T!7XH B0zP XHP#7XH B0HX#6X!8$PPC&X B0X!5$P,#8@@PAZ#юp(p(ЇX(C$C,$C&$C $CC ' X@юp(p(Ї$Q@B@C0@P@XPA@cX@P@\PA@cpX@PXX@X@B#5$P#$PXPAX@P $P@B !@ zPA@$LX@BCXP@X!4$C #$ B0X@Gd!4#$ X C0 !3$# @ PA@$L C0$!4$C !3$# @ PA@$LXC0  !4$C#9@ PA@$LXP8A@P@B0$P8%P@A@(PD'tXDPXpPX4PA&tPPA@a X,XPXB0X,PA@]>!$$PXC0.XC0"XC0X#7TC0X!'X@F #%# X@F'P@F#ю p,p(ЇX(B0@ dPA@$L C #юp(p(ЇX(X(#юp(p(ЇX(PA'|X@PX0P X,PgP@ xPAD&|юp(p(ЇX(X hB0XXB0vX B0.'tXXPP@ }PA&tClCX@X@BhPX@Bh&P@BhPX@&P@PA@\CX@BpX@&P@P@BpA,P%PXPA@#pXP$P $P$PnPA@$pPA@YNA2P@BpCX@Bh!9@ 2PA@$LX@Bx#9@ HPA@$LA@B0X@&P@P@BxPA@\CX@BlX@BpX@&P@P@BlX@&P@P@BpApB0HX@BpPA@\P@BlP@BpC@@ ^PA@$LAnC(C !)!X@@ sPA@$LCA@A@DXY@FC0&'tX@FPiP@ PA@a&tюp(p,Ї %Q@Gd #8<#$" P C0 Y@GdC  C0n @#6X@GdB0Z B0 P@ PA@$LXB0$ %Q@  #PPA@SC$ɰC  @&" A@X@B C0<$ %Q@ӼPPA@S     B  C  !6 ' <#$ #@YB0ю p,p(ЇX( C C0C(C CFC' A$#юp<p(ЇX($B0:$&$P@BA@P@B0X,PA@]>Y0##P0'x$P  #5$P#X0PX,PPAp&x C0&'t$PP$PA&t Y0##P0#Q0A@ C0C0!4#5PAX0#юp(phЇHXhXl$P@ #3$#$P@B$PA@P@#7X@!7Xt!4$CRX@B0P B0H%P@A@(PD'tXDPXpPX PA&tP8XDQ@FX8CXtPPAPDXD!4$CX C0dX P4$P<T4C0CRpPA@^DPPX@&P@P pPP@ @PA@apP@ FPA@aC*B0"XC0't$P$PPA@/.&tPA@CX8#юHphp(ЇX(PA@&FX@BP@BP@BPPA6$  $P $P X@Gd Pюp(p(ЇX(X,  X P X P X P X P  X P юp(p,Ї X@BX,$PA@ CBX0PPAPX!5XCB`T#6A>$PXC X0#8A@_*PA&tC,PA.'tX@PP@ PAn&tюp(p(ЇX(B0P@ PA:C.X C X !9@ PA@$L'xX P !5$ P# PP@ PA&x B0 P@ PACX P@ PAC'xX P X PX P@ PAl&xC^'xX P X PX P@ PA>&xC0'xX P X PX P@ PA&xC'|X PX P $ PP@ PA&|CX PAh'|XXPXXP X PX A@fdXV@tPCPX P&A@fdXV@tPCP #$P X&X 'P C0& C0P P&A@gCP$PA@gXV@tPC(P$PA@fdXV@tPCP$PA@fdXV@tPCXC0@ PA@$L$PA@c8C2@4PA@$LC@ P@ @&Y 3X Cюp0C@"p(ЇPX(PA@h`BX,P$X,PX,P #юp(p(Ї@GhPA@g,#$# #юp(p(Ї,X( C0ɠ%_*:B0$P@BX@B C , B0PA@R$P # P@BA@WC$ P  @ X B0X@&P@P X PA@\CC@P@&Y 3XP@A@PA@YNA@C0@ PA@$LPAVюp8p4ЇA@#4 CA@C0*P@A@PA@YNA@#4 CZX@BlPA@\A@C0>P@'t$PX@BpPA@PA@X&tA@#4 CA@P@B0"%P@AbX@BlPA@\$CX@BlX@&P@P ' X@T'xX P  PP@ PA@a&xюp(p(ЇX(#&A@"P@юp(pLЇ,$XLPLPARC0&'tPPXLPAV&tPLC't$PP$PAd&t #ю,pLp<Ї$P$P$P X@$PX@$P X@$P%X C8X@BXX@BXX.@PX@BX X.@P $QCX!5X@B#%C C0:Y@BC00B0X@BJX4B0,X<&P<ZXX.&P". PX4P4CX P4TDC0:`T4#8A$PDP4X4XDP4XDPDCX4XP4Xt#6XtP@BX@B Y@Gd#PAX!6$P CXPA@&FPX@BP@B$PX@GdB0>$Q@GdX@B't$P@PPAV&tP@B%Q@Gd# A@B0*`T#6A2$PXPCtX B@ HPA@$L$P A@C0,P@A@(P@BP@BA@B0CX #9@ WPA@$L$P@BX@BX&P P`T#6Av$PXPCC'!)!X@ P@XC*C@ $P@ 4&YP@ PA&|C@ PA@$LCpX PA XX@H#7X PA'tX PX P@ PA.&tC C' B BX@ юp(p(Ї'tX(PoP@ PA&tюp(p(Ї'tX(PpP@ PA&tюp(p(ЇX( #6X!4$CPAfP PAP #юp(p,Ї X,X$$P B0*PAX.&P"Z+X"C !4$C! C CV Cx Cr Cj Cb CZ#8PA@aHC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@It$ɠ.B0,&ӡɠ9B ɠ0B$ CP@Ix'tPX PPA&t!&&C<юp(p(ЇX,IX(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- CbI|'xX(P X@IxPPPA@g&x #3&"$P@IxCC@P@&Y 3XD X@Ix#:Y@Ix#&X@Ix [@ItX0B0 &# PA@aH" C P&A@aH"  &# PA@aH" X(#юp(p(Ї$C"X,P(PA@g&C$#юp(p(ЇX(X & C &X B'tP & PX PA@h&t$P P юp(p(ЇX,?X,$юp(p(ЇX(%Q C>'tP & PX PA@h&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX ileelseswitchcasebreakcontinuedodefaultforsizeoftypedefArg countCan't find %sCan't create tempBBSBSmcountBSymbol table overflowIllegal #Illegal #Warning: =%c operator assumedNonterminated commentUnknown characterNumber syntaxBNBB1N100Long character constantNonterminated string%.8s undefined; func. %.8s(Warning only)Expression overflowexpression overflowExpression syntax "#$'256Zadn(Dvnn0laredBad func. storage classWarning: structure redeclarationToo many structure membersBBNBBBNBNBRank too largeNull dimensionType is too complicatedField too longBad type for fieldDeclaration syntax%.8s redeclared[\[\\\\\\\ZX[ [|[N\Z]]]]]]]]01BFNSbbbabab(bIllegal indirectionBNNNB1N0BNBNBIllegal use of type nameBNNSNBNNNBNNBNFBNNNBNNNIllegal use of typeBNBNBNUkrkdumpjtcitmferrfortv@m6fbasic#rc!ratinc,arcv+cal'col&comm$cpall#cryptdifffindgrepmesg nice nohupprofptxepwd`sleep^splitZteeXtrVuniqUwc&quizunitsX X@8X#$$X@"V@"#8  B0pɰ#7CPAA@!DC0#7XPA PX@AA@!DC0#7XPAA@4C~X@"!5X@"#7IPAX@"#юp(p(Ї$P@"X@"#7X@"#(%P@"A0#$P@"'t$P$P$PA@;&tюp(p(ЇX@"&P@"Y@"!$Cr$PA@:H$PX@"Z@"XPA@:C02X@"Z@"XP@PA@5$PA@5$P@"$#юp(p(ЇX@"C &X@"Z@TP@`&Y 3X юp(p(ЇX@"C04X(C(X,B X@"B0^X@"BTX@"?B FX@"C08888888888<0A04A44,1,1 qqq<0$$((((((((8"A"A"A"A<<usortmctpij"XP@(PA@5'tX(PX@"P@-PA@5&t$Q@"юp(p(ЇX(PAt$P@A@8юp(p(Ї$PA@0fA@0X(PA$AP@"$PX(V@"V@"PA@/юp(p(ЇX@"!#$#AH$PA@0fA@0X(PAAR#(XPA@X@"C0(X@"!X@"#(HPA@'tPPX(PAV&tюp(p(ЇX@"!#$#A$PA@0fA@0X(PAA#(XPA@X@"C0lX@"B0bX@"B X@"C X(8 C0 B0X@"BXX@"B J$P X@"V@"PA@/X@"B0$PA$Q@"C C0dX@"CZX@"BL$P X@" [@"PA@/X@"B0$PA$Q@"CV#&CX@"#6$PA~$PX(V@"V@"PA@/X@"PX@"PA@/юp(p(ЇX,# [,P,#Q($PX(X,PA@/X@"C0X@"PX@"PA@3юp(p(Ї$P@"A@%XA@(pA@!D C0>X(C|   [ "()+/0?APuvwxyz{|}~jPx  >td2 P | ^ PF^ b 01234567bf:;05,5<5@5;<CCCCIllegal storage classBSInappropriate parametersBSBBSBNBBSBSBNBSNBSBBSBToo many }'sExternal definition syntaxBBSBBNCompound statement requiredBNBBNNo auto. aggregate initialization0-length row: %.8sNo strings in automaticNo field initializationBNToo many initializers: %.8sUndefined structure initializationToo many structure initializersBBNB%s multiparD 3:9 4;8w~}~~"zv,/y*( )x+||||||||||?PAZ{{{{{{{{{{{{{{{{{{{{{{{{{{u1{{{{{{{{{{{{{{{{{{{{{{{{{{{0&0123456789ABCDEFCDEFLOSXcdeflosxde(e~e~e4dde de(e~e~e4dde dI<\'xXP PA@,PA@5Xp(Ї%Q(C X,&P,X-B0X,XC$Q@"C$Q@"C$Q@"C%Q(C0X,&P,X-B0@PA@5$PA@5X,XP@|CLX,X0!6$P@#1!5%P@CCl !)!X@CX(P@"C@PA@5$PA@5X,P@"A@%AVX@"#9X@"PA@5$Q@"A@|A,X@"#9X@"PA@5PX@|PA@:`P@"C&XBTX@"B FB >X@"C 4'tPPX(PA&tX@"!5$Q@"CNX@"#6$PA*$PX(V@"V@"PA@/X@"PX@"PA@.юp(p(ЇX@"!#$#Av$PA@0fA@0X(PAA$PX(V@"V@"PA@/PPAюp(p(Ї$PA@0fA@0AP@"$PX(V@"PA@/юp(p(Ї$PA@0fA@0A#8XPA@X@"X@"[X@"!4[@X@"C0(X@"Y@"!7!#(BPA@W]LRX^MS_`flragmsbhntcioudjpvekqwx~y nrtz44444444(."t \"&')*/2P[::F<r2DDP !dHH<<Hl  !de|XXXX6intcharfloatdoublestructlongunsignedunionshortautoexternstaticregistergotoreturnifwhly definedUnexpected EOFBNMissing '}'Case not in switchSwitch table overflowDefault not in switchMore than 1 'default'Inappropriate 'else'Unknown keywordStatement syntaxStatement syntaxBNNNN0Not an argument: %.8sBNBN%.8s undefinedBSNFjFjFjFjF4FFF F$EFEEEETUTf*STLST(VVVVVVConflict in storage classType clashMisplaced 'unsigned'Misplaced 'long'Misplaced 'short'Bad structure/union name%.8s redec...;.stripsymbannersnonroffneqneqntblcrpostupostcrefindex~yacc}em|tp{ddthxlibyalfortwbeepvbsucvtcvoscvtaskrdcopyqdfipexportoimportnlogchesslpress@|P@PA@5$PA@5$Q@"$P@"A@,AX@"C0@dPA@1V@PPA@1VX@"C0\$P@"$P@"$PA@:P@T$P$PA@;0B0@&\P$PA@;0A&A@5A@&\X@"PA@5юp(p(ЇAA@A@,t$P@"P@"X@P@"A@8A@ hC0vX@"#9EPAC^$P@P@X@$P@"C2$P@"C&%P@"CC!)!X@xюp(p(ЇA@0X( B X(C$A@(p!8UPA@X@0C(A@$!9SPA@#$PA@'X(C #3$#$C !3$#$Cv !#$#$Cf ##$#$CV !$#$CF #$#$C6#3$#$C$CC !)!X@ #5X@"#5$Q@"$Q@"CX( #5$P@X(CX@"!8IPA@X@"!($[@"P@"CX@"!8IP$PA@: P@@P@HX@HP@DPA@:@ C00 &PAX X@8P X X@8PCюp(p(Ї't$PX@LPX@"PA@;&tX@@U@HCrX C"$P C0X@Q X@Q C'!)!X@'tP &PX@"PA@;X&tCюp(p(ЇX@$Z@($%pX C0hX Y@$B0PX Y@(B0BX(#7U@@B2#U@@C& C0X P X P PP@8$C|XCX(C bX@HX@HP@HU@DC X@Xюp(p(ЇX(X@"dC0P#8DPA@2QX@"C0LX$ 'C04ɠ!PPA$ @  $&&CPC*X@"C0 $ 'C0 @PA@4.&"юp(p(ЇX,!6X,P#X,PH(PAX,PH*PA юp(p(ЇX@"PC0d#8DPA@2$Q X@"C0:X!PA$ &P X( @X, @X@"#8X(PA@3юp(p(ЇX@"dC0P#8DPA@2$Q X@"C00Xɠ%#8PA@8hC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@($ɠ.B0,&ӡɠ9B ɠ0B$ CP@('tPX PPA&t!&&C<юp(p(ЇX,(X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb('xX(P X@(PPPA@9\&x #3&"$P@(CC@P@ &Y 3Xdo7squezGnosqzWnorx3gifz ifnzifp)ifnp9ifmIifnmYifeiifoyifuifdelseendcifendaZableaejaer*ahJahiahmaaiais&alamQar atldbalAAPA@2X@0#$VPA@X(!3#X( !2X@"X PA@0CA@(p#8APA@X@0#$VPA@$PA@0fA@0$PPA@/$P$PA@/$P$PA@.X@"X-" PA@0C A@0A@(p C>@PP@"CJY@"C0@RPA@$@dP@"C C'B BX@ P@"X@0PA@0CX@"#8IPA@2X@A@P@C,X@DP@DPA@:X@$P X@(P X P  P@8P $#юp(p(ЇX($C @$#2&&" $PAюp(p(ЇAX@(X@(X@(A@!DB A'tPX@(PPA&tT@( CbZ@(Cp[@(Cf\@(CXX@(#:]@(#ZPA@C,T@(C"V@(C'!)!X@CFP@P@0P@4ɰB0X@"#(UPA@ P@,#юp(p(Ї$$A@!DC "$AX@,P@(X@0A@!D #8XPA@2!PAj$X(  $&Pюp(p(ЇX@"#4A@3NX@~H DRRRLRRRD$V4:$`` ".@  6   !"#$%&'()CFHXYcfhxy!!!!!!!!!!!AZaz"\"b"\"b"h"#N#N#N#NC06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@ `%X)!P@ `%#!P@ `%$XP@ @XP@ D PA@ P'tP@'0PPA@!&tPA@ 8P@"KPA@ P#@"XPA@A@('tPX@/0PPA@!&tPA@ 8X@/@C06PX@/@h@l@"`@h j@` h@/4j@`@/40PA`@h j@` h@/8j@`@/88PA`@h j@` h@/'tP & PX PA@ &t'P  #%C & P X&P#юp(XX]P@&p(ЇX,X(%Q CNX C06'tX & P & PX PA@!&t !$%C& & P P 10$QXDXPA4P$QD%Q@XC X@&@YB XP@ (PA@CXZ@&X@B0XP@ 9PA@C\XZ@&X@B0XP@ HPA@C&XP &CX#8X@-(!4A@X@&$PX@&@YBX@-(C0|$PXX@-(C0XX@-(YC0R$QCX P&X!4$PX'PC0$P@(PACC8X P&XP@-XC0XC0XPAP@-X@-B~%Q$P@&PAC0Lh,i0B0@"P@"PA@C"h@"l,m0`@"PA@юp(pdЇDX@'$C0X@/@#<@"PA@A@(X@'$#6XdP@/@$PXdPA@ CXdP@"PA@C't0PPPA@ &t0B0ȾžC(ӫĠ C0ɠ !ɠ!? &CX@' C04 PA'tPP@"PA@&tChB0TӮĠ$Q@'08PA` 0PApj YBYB0.X C"PPA@PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(&PD-dPXYC X$P"XC JX]0X.D&PDX]PX$PCXD$#ю p@p(Ї@/PA@#$# #юp(p(Ї,X( C0ɠ%#8PA@TC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@1$ɠ.B0,&ӡɠ9B ɠ0B$ CP@1'tPX PPA&t!&&C<юp(p(ЇX,1X(C'X( %P(C #4'C #3&"X&PX(#юp(X@&X#X@&ZP@&&P@&%X!$P@&%XP@&XP@&&!P@&%X)!P@&%XP@&XP@&&!P@&%XP@&XP@&X&!P@&%XP@&XP@&&P@&%XP@&XP@&X&!P@&%0123456789abcjlmnrstuv `'xXP PA@,PA@Xp@Ї @P@$X@B0&@PD$P@X@X@#5$Q@" %Q@$QDXDXPXC0X&PCr@PA@A@X@PC$Q@-CC$Q@-C$QD%Q@XDXP@$Cz$Q@-CnC@P@@&Y 3X$CLA$P@&PAp&X P@&&&X P@,&X P@,&X P@,&X P@-&X P@&X@&P$PAPX PA@P@&X@&X&X'PC0$P@(PA:P B0X #X P'tXP@(PX@-PA@&tXU #& ' X [P ClX@-PA@X P@-PA@ P@-PA@$QCA@Cr!)!X@hю p@p,Ї X, T B0$ B X C0T C0P X PAhȰ BXC0zB0^PXPA*PXB2XXC0XXPA%QCXPAv'Cj X PA^'Cю p,p(ЇX( T B0$C $P &" X,B ,$Y,CA P &" X P C$C$P&" $X,Bɰ!(A P ɰ!AP$CA@P@(&" ɰC @(P X PA:C@(PXPAQ,&CZX,C0ɰ!(AV P ɰ!ABP$Y,CAP@(&" C$P@(&" ɰC @(P X PAC@(PXPA^ɰP@ PA@&tX@-!4A@$CZ($P&" юp(p(Ї$X(&P(C0 0 9B $ C #юp(p(Ї'tPX,PX(PA@&tX@$#2& #юp(p(Ї$PX@$PA@TP@&X@&C X@$P@ PA@A@X@-C0"X@$&#2" @& @юp(p(Ї@-PX(PAX@-C0n@-P@ PA@A@x!4A@ !4%CRy!9A@ C0A@ #7 !4A@" CX(XPPAF@.#юp(p(ЇX($!4n#m#юp(p(ЇX(&X, B$X,$$0 &# &X,$0 & #юp(XX#%!Q!Q$QC@"p(Ї@/PA@l#$# #юp(XX]p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@1$ɠ.B0,&ӡɠ9B ɠ0B$ CP@1'tPX PPA&tst chance before scribbling on %s %l files not restored - small ilist %l not in range %l not dumped %l does not exist the epoch disk read error %l ino=%l disk write error %l ino=%l checksum error ino=%l change tapes skip %d tapes tape read error %l ino=%l can not open %s %s bad freeblock out of freelist !t!xM:/ESTEDTDay Mon 00 00:00:00 1900 SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec0123456789AB\$r'xXP PA@,PA@ Xp(Ї$PA@ P@~dX(B0(\X C0X P&A" X@~`C%Q(C0$Q,X,X-B0X,XCr$Q@4C$Q@4CpC,X,XPAC0P&$Q,%Q(C%P &Ch@PAC@P@&Y 3XX,XPAC(X@~`#юp(p(Ї$PX(PA@ P@4X@4CX(P@"PAC X(P@2PAA@$'tP@P$PAA@ юp(p(Ї't$PX(PX@4PA@ &t'tPX,PX@4PA@,&tC0X(P@PAVA@ юp(p(ЇX($&0B9B $ C #юp(p(ЇA@ $P@D'tX0PX,PX(PA@ D&tX@~dP@DA@ юp(C@"p(Ї@DPA@ p#юp(p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@l$ɠ.B0,&ӡɠ9B ɠ0B$BPX (PABX P юp(p(ЇA|$P@*PA@*PPA #юp(p(ЇX(XB0X(X!;@ [PA@C'tX(PA@&tPA@юp(p(Ї't$PX(PX@-PA@&t'tPX,PX@-PA@&tC0,'tX@-PX(P@ fPA@&tA@юp(p(Ї't$PX(PX@-PA@&t'tPX,PX@-PA@&tC0,'tX@-PX(P@ PA@&tA@юp(p(ЇX,PX(PP@-PA@( #юp(p(Ї't$ PX(P$PA@&tC0X,PPAP,'t$ PX(P$PA@&t0X,&P,X,$X,#юp(p(ЇX@$'P@$ !2!@!PA@A@X@$ !<@!PA@A@X@$B @@*PPAX@*P@$$2CX@*,"P@$&" #юp(p(ЇX@$2BLX@$P@*$2CX@$-"P@*&"$P@$@*PX(PAX(X@$&P@$P@$юp(p(Ї!&&C<юp(p(ЇX,18X(C'X( %P(C #4'C #3&"C' 0  9C'@!  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb1'xX(P X@1PPPA@@&x #3&"$P@1CC@!P@"(&Y 3XD X@1#:Y@1#&X@1 [@1X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@"pB YBYB0.X C"PPA@PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@&tX@$.<P &"'t$PPX@"pPA@&tC*@"pPX,PA@#$##ю p,p(ЇX,?X,$юp(p(ЇX(%Q C>'tP & PX PA@&t'P  #%C & P X&P#юp(XX]P@$p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X@$X#X@$ZP@$$|P@$%XP@$XP@$$!$P@$18Ctю p,p(ЇX(XC0X(X`@B0$PX(PA@C0 C0X@4!8PAB0pX B X #3&" p#&X B0P@7PA@ D$PX@~\PAp &P@;PA@ DCNюp(p(ЇX( .B0" C0 .B0 !3$#$#юp(p(ЇX(C0z$PX(PAr!;@CPA@ DCPX, #+@GPA@ DC2X,&P,PX PA &P@KPA@ Dюp(p(ЇX(p(p,Ї X@DB 'tP & PX PA@ &t'P  #%C & P X&P#юp(XX]P@Xp(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@\%XP@ XP@$!P@\%  !ɠ!$#$ @ C0$  #6*P# PA@ C$C PA@ &" &C>$ PA@ $QCP,B0ю p,p(Ї'tX(PA&tPA#юp(p8ЇX8XPX8XP [@PPA@ TPA:XwP/PX J#7X KB0 XX@PXX@PXPPAPXPPAvPX@C0ZYB YB0JX B>YBYB0.X C"PPA@ TPAj$Q  #юp8p(Ї$XP@dXP@h`!P@%XP@pXP@tXl!P@%XP@|XP@Xx!$P@%XP@XP@P@%XP@X!$P@% X'PPXP@!$P@%XP@XP@X!P@%/usr/lpd/usr/lpd/lock/dev/prG008016024032040048056064072080088096104112120128 BFLMSUZZ4""========== University of Wol 0 main",exit" t_exit""lpd#(lock#4printer#Dstabs#Lcmdbuf$prbuf$lbuf$dbuf$ttymode#signal"pcreat" fork" close" open" dexit"read"sttyZ`Lx>`Lx*P@P$PA@&tB0l@@C0@dB0@fB0@PA@PA@'t$P$P$PA@@&tCj't$P@P$PA@&tA юp(p(Ї@4PA@$PA@ tюp(p(Ї@PX(PA@ |Bd@PA@ L CX@PA@ C8@PA4C @@@PAATC@PA$P@PA@ Br'tP@PPA@&tC &'tP@P$PA@&t !3CɰFB0 't$P &&&X(ʰX$ && && &&'X PPA'X dPPA'X dPPAv'X dPPA^&X(XPPAF@#юp(p(ЇX($!4n#m#юp(p(ЇX(&X, B$X,$$0 &# &X,$0 & #юp(XX#%!Q!Q$QC@"p(ЇX,$PX(PA@ P$P P  #%#$#юp(p,Ї X@@B 'tP & PX PA@&t'P  #%C & P X&P#юp(XX]P@p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(XP@PL!$P@%X!$P@%XP@XXP@\T!P@%#!P@%ESTEDTDay Mon 00 00:00:00 1900 SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec@P@PA@`&tA@@ PA@ #2" A't$P@P@PA@`&tA@C@ ,P@ 8&Y 3X $P@PA@P@ AC0xX@ 0": CXX Y@ #5X B0>B6XX P PX P X P X@ P X@ &#&CC~X@ PA@ C0 #PA&" CX #8X !5PAB&C@ PA@ CX !9PAPA&CCюp(p(Ї #PA&" юp(p(ЇX(X C0PA\$ PX PA@$P $P юp(p(Ї't$P@ PX@ PA@&t!7@ #4$C(@ P@ @ P@ @ P@ $#юp(p(ЇX(A@ B0$P$PA@T JX  $PPA@PPA@$PPA@$PA@H'x$P  &P@P@ TPA@`&xA@Pюp(p(Ї$P@ PA@ B`X(Xa!'t$PPPA@$&t'tP@ PPA@&tPA@$Nh'xXP PA@,PA@ Xp(ЇX(B0.X C0X P&A" X@$ PA@ %Q(C0$Q,X,X-B0X,XCh$Q@#CC,X,XPAHC0P&$Q,%Q(C%P &Ct@XPA@ C@P@$&Y 3X X,XPAC2X@$ PA@ юp(p(ЇX@##5$P#$PX(PA@P@#X@#C,X(P@bPA@ X@$ P@$ C$X(P@rPA@ $P@@cPA@ &x$Q@$H@$ @@$$X@C0@X@ B0*'xX,P X@$PP@PA@ &x&C$#юp(p(ЇX@!'P@! !2B@PA@ $CnX@! !4$CZX@!B L'tP@PPA>&tX@P@!$2CX@,"P@!&" #юp(p(Ї't$PX(PX@#PA@x&t'tX0PX,PX@#PA@H&tY0C0lX(P@PA@ 'tPX@P@PA@ &tX@##9@PA@ X,X, #&X&PX(#юp(X!$P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@X!$P@%$XP@XP@X!P@%4=FObs/dev/df0/dev/dr0/dev/df1/dev/dr1Bad flag cannot open %s %s: free%d dups in free missing%5d spcl %6d files %6d large %6d huge %6d direc %6d indir %6d indirC B0"$P@`PA@8bCF' /B04$ $P !7@cP#PA@8 &#C C&'t$ P@eP$PA@&tA@X@P'tP@PPA@d&tB0TX@C0P@PAdC0.@PPAX@&P@P$Q@CPA@XPA ю p,p(ЇX(X@' C @&U@C,X PX PA#)XX P PC&Cюp(p(ЇX,X(PPA@ X@B0"P'@sP PX PA@ X@t0'xXP PA@,PA@Xp(Ї$P$PA@$P$PA@0X(#'X,XtTCX #4" T!tX @X @X P@X @X @@P$PA@X PAX@P$PA@AC0#@@@X P@X@#9X@P@X@#9X@P@X@#9X@P@@P$PA@'x$P @P@P@PA@&x$PA@XCюp(p(P@ PA@ BdX(X@ @ PA@|'t$P$PPA@$&t'tP@ PPA@&tPA@юp(p(ЇA@@#юp(C@"p@ $p@ $XP@ dXP@ h `!$P@ %XP@ pXP@ t l!$P@ %X!$P@ %XP@ |XP@ x!P@ %&X)!P@ %XP@ P@ !P@ %#!P@ %$XP@ X !P@ %XP@ XP@ #$P@#$P@#$P@#$P@#$P@#$P@#$P@#$P@$$P@$$d#$P &"A@'tP@!P$PA&tX@!P@#$X@$Y@#Cb'tP@P &PA|&t$ɰ C0X@$Y@#C $Q@$ PA&C&C$P@$A@'tP@!P$PA&tX@##5A>CADC0"@wPPA!7$Q@$CX@$C0*X@$P@|PA@ X@$ P@$ $$dCX& #6 #'""X@![@!'  #;P@PA@ X@#P$P &" юp(p(ЇX@!2BLX@!P@$2CX@!-"P@&"$P@!@PX(PA&X(X@!&P@!P@!юp(p(Ї't$PX(PX@#PA@x&t'tPX,PX@#PA@&tC0:X(P@PA@ 'tPX@P@PA@ &tюp(p(ЇX($&0B9B $ C #юp(p(Ї$P@!$P@"$@#t$@#u$@#v$PAVX@!'X@!& B ,$D@$!5PA'C2%6d used %6d free %6d indirectdata (large)indirect2nd indirectdata (very large)data (small)%d bad; inode=%d, class=%s %d dup; inode=%d, class=%s %d arg; inode=%d, class=%s bad freeblock read error %d err %x count %d No update write error %d err %x count %d 0123456789ABCDEFCDEFLOSXcdeflosx 2 T @ l 2 T @ l !3A юp(p(Ї'tP@{P$PA@&tA@юp(p(ЇX(.B0X,.#4$CX,PX(PA #юp(p8ЇX8X< &#6İ!3Ȱ P&C$P P &PC0pX]B0 X #9PPAC$CC@X-B0"X B  P& !$Q CXP !4$Q C$CfX #4$CX #9PPACD$C>P'PA:C, #3$#$CC@P@&Y 3Xюp8p(ЇX,!4$C:X(Ї$P@$P@$P@'t$P@ P$PA@&t!'$PA@@ !4$C't$P@ P$PA@D&taBz!'$Q@CDABZ!)$Q@ C&#B0#"'C#@!5#& #9 #6C "'$ B0,'t$P@P$PA@D&t$Q@C 't$P@P$PA@D&t$#юp(p(ЇX( C0 't$PP&$PA@D&tCюp(C@"XP@P@!P@%XP@XP@X !P@ %XP@ XP@ X !P@ %XP@ XP@ X !$P@ %XP@ XP@ P@ % X'PP!X'PP@ %XP@ XP@ X !P@ %/bin/sh-/etc/rc/etc/init/etc/ttys/etc/utmp/usr/adm/wtmp/dev/tty d//dev/ttyxetc/getty %0@PA@ X@#P@PA@ X@#P@PA@ X@#C0X@#P@PA@ X@#P@PA@ X@#P@PA@ X@#C0X@#P@PA@ X@#P@PA@ X@$P@PA@ X@#PA@юp(p(ЇX(T C0* T #7$Q@#CX `@!6$Q@##$Q@#T C0$Q@#$C X C0$Q@#@P X PAB0b'tP@P X PAf&t$C0X@C0@P@!P$PAX@#PA@A@#юp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@d$ɠ.B0,&ӡɠ9B ɠ0B$ CP@d'tPX PPA&t!&&C<юp(p(ЇX,d8X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- CbC0(X,PX(&P(PA#3$#C$#юp(p(ЇX(X, & B0&!4$CC'  #юp(p(ЇX@X( &C0*##A`İ !7/ &#Ҽ&CX,##A2ӽ&Ҽ& =X@P@ #юp(C@"X!$P@%XP@XP@!P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@X!P@%!P@%XP@XP@P@%XP@X!$P@%XP@XP@X!P@%01T12^23 h34 r45 |56 60 -- login: login: login: login: login: login: login: login: /bin/loginlogin 0X@PAL&C&CXX (C0$Q@#@PX (PAB0 'tP@PX (PA&t$CX@C0$Q@#@PX@PAB0b'tP@PX@PAn&t$C0X@C0@(PX@PAT&C&CXC:$C0 X C0@:P X PA&Cюp(p(ЇX(X@$#5$Q@#X@!& !&U@!B0'xX,P X@$PP@GPA@ &x$C$H@$C02'xX,P X@$PPd'xX(P X@dPPPA@L&x #3&"$P@dCC@P@L&Y 3XD X@d#:Y@d#&X@d [@dX0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@B /Z>@ XHXZ#6$QCX@)X>/P@ X@)X>/P@!'t$P$PX PA@&t'tP@ PX PA@T&t@PA@8@)PA ю$pDp(ЇX(XB0X(X!;@PA@8C'tX(PA@<&tPA@8юp(p(Ї#X(PAJX(< C X X@8PXX@YBYB0.X C"PPA@PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@&tX@*,<P &<<P &<$ $P&&$P@*DFPA B PA &" P@*@P@*HPAPX PA@T&t !$%C& & P P X&PX(#юp(X@X#X@ZP@P@%X!$P@%XP@XP@!P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@X!$P@%$ X'PPXP@XP@X!P@% J8-0abcdfhisuzH  &,C,'tP@TPPA&t T#юp(p(Ї't$PX(PX@RlPA@ &t'tX0PX,PX@RlPA@ &tY0C0X(P@ _PA@hA@`юp(p(Ї't$PX(PX@RlPA@ &t'tPX,PX@RlPA@ &tC0X(P@ nPA@hA@`юp(p(ЇX($&0B9B $ C #юp(C@"p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@V$.XU@)#%%Q@)X@)[P@)%QCCC@P@&Y 3X0CfXD!,@5PA@8A@0X@*C0$PX@PA@P X B'tP@ PX PA@&tX PA@h$PX C`XHXPX PAC0,XX@ P@)XX@!P@)$QCXHXP@OPA@8$PXHXPA@P@!X@!C"XHXP@TPA@8A@0@dPA@8@)PAA@8@P$PA'xX@P$PA<&x P &&" @#PANX(X C0X,#9@PA@8CrX(&X(, C &X C0X(XC0@%PX PA:%'CX C0X(( B0f@'PX PA')CYBYB0.X C"PPA@ PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@ &tX@T<P &<<P &<$ $P&&$P@lFPA B PA &" P@hP@pPAn!6P@$X@ !([@&" P@ &P 0 main",exit" _exit""crontab#crontmp#aend$$itime$(loct$0flag$4fork" setexit" Dreset" Nsignal" time"'tP & PX PA@ &t'P  #%C & P X&P#юp(XX]P@X@X#X@ZP@P@ %X!$P@ %XP@XP@!P@ %XP@P@!P@ %#!P@ %$XP@XP@!P@ %XP@XP@l'xXP PA@,PA@Xp(ЇX(C0@PA@$PA@$PX,XPA@C(X,XP@PA@$PA@X,XPA@$'C@*PA@$PA@'t$P PPA@&t't@P@ PPA@&tюp(p(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(C@"p(Ї,X( C0ɠ%#8PA@DC$&ӡɠ-!3A@"  &# PA@" X(#юp(p,Ї X@ B 'tP & PX PA@4&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(XP@XP@!'-3"(.4#) X0B.9B &X$ P8PA@ XCXBnXdB b #5 B0TX &&C C0( C 6%!2$&8PA@ XC$ &$ &CX C0V B $Q@C%Q(C X,&P,XP@C$Q@CC@HP@X&Y 3XCfX(P@X,P@@PX@PA@|CX@P@PA@ C,$ɰC"@PA@Bv&&C$$ɰCV@,0!9C a!z#(ABZ!& B0&C #3 !7&$ @,##&CA8Cd$@,~@4@X@ !([@&" $'t &PX@P@$PA@ &tюp0p,Ї X,X! /`# /l@#ю p,C@"p(ЇX,$PX(PA@P$P P  #%#$#юp(p@Ї XH!$$CXH#$#XH&PXLf#6XLF!5$P #$P $P$/i@C XD&PD-+k@`@h@0i@C&h@4i@C h@l@8`@%QCh@Kap!Error 0Not super-userNo such file or directoryNo such processInterrupted system callI/O errorNo such device or addressArg list too longExec format errorBad file numberNo childrenNo more processesNot enough corePermission deniedError 14Block device requiredMount device busyFile existsCross-device linkNo such deviceNot a directoryIs a directoryInvalid argumentFile table overfl8PA@tAAюp(p(Ї@5B0X@@B0@h@'tP & PX PA@$&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(XP@XP@|!$P@%owToo many open filesNot a typewriterText file busyFile too largeNo space left on deviceIllegal seekRead-only file systemToo many linksBroken PipeAfC0X$h!@L`.hi@#'h j` X@C0VX$h!@Li @C >'tX$h!@Lm @`'X$DP@ PA@ &t$QCNh i@C "Ah m@`@PA@ юp4p(ЇCX(PPA&"юp(p<ЇX@#7h@` #h@<` X'tP & PX PA@D&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$PV\bQW]cRX^dSY_eTZ`fU$V'xXP PA@,PA@Xp,Ї $P$PA@#(B0fP$PA@#(X,!7$PA@X0&$Y,CB$P@Q(X& -B0 C&Y,B@ P$PAX P&A^PX!:X@XPACC$Q@QC$Q@QC$Q@Q $Q@QC$Q@Q$Q@QC$Q@QC|$Q@QCp$Q@Q Cd&Y,B@*P$PAX P@Q\&C6C@(P@T&Y 3X,PAX@Q$PA@"$&CAA$X0&@ L\U@CX CX@QXP@QXX@QB08X B00X !9@`PA@$Q P@lPA@CdC`X@Q@Q CRX@QDQ CDX@QHQ C6$P XQ C"C B BX@C,X@Q!5X@Q#5$P@Q8Q@Q4X@Q8P@Q<юp0p(ЇX@Q\C0<PX@Q\PA@"4X C0>XLTC &&!4" C&I(!>,C #ю p,p(Ї@LPX(PA P@T$P@XA$#юp(p(ЇX@>,B@YP$PAP@LPAxX@TP X@XP Q@ #юp(p(ЇX@TC8X@QLQ@XCXX@QPQ@XCHX@QTQ@XC8C4C@P@&Y 3X  T@T#6!P@Tюp(p(ЇX@Q(C0PX@Q(P@oPA@@ C0@ P@rPA@@yPA@X,P@|PX(#юp(XP@`XP@d\!$P@%X!$P@%XP@lXP@ph!P@%XP@xXP@|t!$P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@X!$P@%XP@XP@P@%XP@!$P@%XP@XP@X!P@%x'xXP PA@,PA@Xp,Ї $X,#@PAX,C X0X@D$PA@@HxB0 $PA@@Hx!5$@H$P@PA@#@PAD'tP@PPA@&tB0@@HB02C C0 &&C@D#9@@DB0|X0X !4&&"C B0H B0>@@C.@!8@$PAZ@!9?@@$P@A$CX@ 0Z@ 4Q<'xX@ b*  LP^lz(2<F "#$(JBad 'use'No output filenameNo relocation bitsetextedataendUndefined: %.8s Can't create -o filel.outCan't create l.outCan't create tempinternal error: symbol not foundLocal symbol PA@P@LB(@PX@LPA@!$T@!8@3PA@FPX@LPA@PX@LPA@YPX@LPAdP$PA@L't$PP$PA@&tB0~C6$CJ C0At@_P$PACC$A$C@P@&Y 3X't$PPX@LPA@&tC\Aю p,p,Ї $P$PA@LA@B0N$P$PA@L'x$P @mP@jP@bPA@&x@pPAdPA@tP$PA@Lю p,pt\U@CdX  B0PX B0HY@QC0>Y@PC04Y@PC0*$Q@Q $P@Q$P@Q$P@Q $P@Q#C$X@Q!6X@Q B0\U@C0X  B0X C0&P %P  CX@PC00X@PX B0X@P"PX@Q,X@PP X@PC00X@PX B0X@P#PX@Q0X@PP X@QC00X@QX B0X@Q$PX@Q4X@QP X@Q!5X@Q #;X@Q,P@Q,X@Q,P@QDX@QC0X@Q,P@QDX@Q #5$P@QDX@QDZ@Q0PX P@QH$P PAC'xX@ 0P X,PX(P@ PA&x'xX@ 0P X@ 0Z@ 4$Z,PX(P@ PA&x'x@UxP @Q`PX@QLPPAL&x$T@ 0C0(@Q`P$PA@UxP$PA'xX@ 4P X@ 0$Z,PX(P@ PA@&x'xX@ 4P X@ 4$Z@ 0Z,PX(P@ PA&x'x@WP @SlPX@QPPPAp&x$T@ 4C0(@SlP$PA@WP$PAX@ 0&Q@Q@X@ 4&Q@QDX@ 8Q@QHюp(p(Ї%Q@ A@ &' ;юp(p(ЇX,X0X(PH P&AR' <юp(p,Ї X,X4Z0X4P4X%QX  C0X  C0X #8X B0X@B0X@!;X@Y@#P't$PPX@Q$PA@"&t'tP & PX@Q$PA@"&tP#$PXP C@0P$PA:$Q PPX4 & P X8#6X8P X [4P !$$P ю p,p(ЇX(%Q C('x%P $PX &PPAz&x%Q %Q B 8X C@P$PA@ `C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@[$ɠ.B0,&ӡɠ9B ɠ0B$ CP@['tPX PPA&t!&&C<юp(p(ЇX,[X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb['xX(P X@[PPPA@!@&x #3&"$P@[CC@P@&Y 3XD overflow%.8s: Multiply definedRelocation errora.outl.outa.outl.outa.outNo pages/lib/libXXXXXXXXXXXcannot openSymbol table overflow%s(%.8s): %s Local symbol botchOld format archiveBad format0123456789ABCDEFCDEFLOSXcdeflosx$zz0$zz0(Ї@PX@LPA\$PA@юp(p(ЇX(P$PA*@P$PA$PA@юp(p(Ї$X, #4&&"'tPX,PX(PA@&tюp(C@"ppЇPPXpPA@B$P@PA@#xCX 'tPPPA@&tB0VȾ   B0< tB00 tB0$ yB0 C0 !4 #Cx#юPppXP@P@!P@%#!P@%$XP@X!$P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@P@%!X'PP@%XP@XP@X!P@%Usage: write user [ttyno]/etc/utmp/dev/tty !Can't open utmpNot logged in.Permission denied. Message from ... ! /bin/shsh-tCan't exec shell.EOT /dev 0  && && &&&X(ʰX$ && && &&'X PPA'X dPPA'X dPPAv'X dPPA^&X(XPPAF@#юp(p(ЇX($!4n#m#юp(p(ЇX(&X, B$X,$$0 &# &X,$0 & #юp(XX#%!Q!Q$QC@"p(Ї@ PA@ $#юp(p,Ї X@ B 'tP & PX PA@ &t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@ &t !$%C& & P P X&PX(#юp(X!$P@%XP@XP@!P@%X)!P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@X!P@% ('xXP PA@,PA@XpDЇ$@ P XD!7XHXP $PX PA@ xPXCP@ PA@ A@$PA@ 8P@ $PA@ XD!9$PA@LP 'tP@(PXPA@ &tPXB0YBYB0.X C"PPA@tPA !$%C& & P P X&PX(#юp(X!$P@$%X)!P@$%XP@ X !$P@$%XP@XP@ !P@$%XP@ XP@X!P@$%XP@XP@X!P@$%/etc/utmpcannot open wtmp Nobody. tty M:/ESTEDTDay Mon 00 00:00:00 1900 SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec@ PA@pX@ ,Z@ (P@ ,X@ $Z@ P@ $X &P X Y0BX0C TX@ ,PAP@2PA@|X@ $PAzP@7PA@|@C # [,'$$0 $$ ?X,CX(j$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@ |&tX@ $<P &<<P &<$ $P&&$P@<FPA B PA &" P@8P@@PAn!6P@ 4$X@ 0 !([@ 0&" P@ 4 &P &P&$P@D@$#юp(p(Ї &&#2" X(X$ &CP@ `$ɠ.B0,&ӡɠ9B ɠ0B$ CP@ d'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C  #3&"C' 0   C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb h'xX(P X@ dPPPA@&x #3&"$P@ dCC@TP@&Y 3XD X@ d#:Y@ d#&X@ d [@ `X0B0 &#  $ 'xXP PA@,PA@Xp,Ї X,C X0X-B0ZX0X9B X0X&PAP@# X0XP@ X,'P,X0&P0CX0X+B00X0X&PAP@ X,'P,X0&P0C>$PX0XPA@ TPXC"X0XP@ PA@4A@XP@# $PA@ 'tP & PX PA@ h&t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@ &t !$%C& & P P X&PX(#юp(X!$P@ <%X)!P@ <%XP@ (XP@ ,X $!P@ <%XP@ 4XP@ 8X 0!P@ <%cdA:X@ P@=PA"X@ P@BPA юp8p(ЇX,X(P@GPA@\~@P PA~@pP:PAdpdP:PA6dP.PA$ PA@юp(p(ЇX(PA@X,$0PA@X,$0PA@юp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,& 0+ X@ C0s0Bad string ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C #3&"C' 0  9C'@L  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb 'xX(P X@ PPPA@&x #3&"$P@ CC@\P@&Y 3XD X@ #:Y@ #&X@  [@ X0B0 &# PA@" C P&A@"  &#d'xXP PA@,PA@0XppЇPP$PA@dX` #3$#$P@@Xp'PpC |PXtXPA@8X@<&P@<P@PXtXPA@BX` !8X@@&P@@Xt&PtCp$$ɰC^ BDX@@#$ B J'tP@P$PA@&t$ !'PA.C @ @&&CPACюPppp4ЇX@@#3$ #X4P$P X Y4C~$PXY@'tP & PX PA@ &t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@ @&t !$%C& & P P X&PX(#юp(X!$P@8%XP@P@!P@8%XP@X!$P@8%XP@XP@ !P@8%XP@XP@ X!P@8%XP@8%XP@(X$!$P@8%XP@0XP@4X,!P@8%rootpassword: bad password file /bin/sh-cannot execute shell sorry /etc/passwd  !"$(0l0123456789ABCDEFCDEFLOSXcdeflosxLX0LXC0X@ P@ PA@,Cd@P$PA@$ю p,p,Ї X@ !4$CP$PX@ ZX.,Z.#4$C(X&PZ@ B0$P@ $#ю p,p(Ї@@C04@P@ PA@P@ PAC@P@ PA't@P@P@ PA@,&tX@#9@ PA@,@#9@ PA@, #9@ PA@,#9@ PA@,#9@ PA@,#9@ PA@,#9@ !PA@,#9@ (PA@,@ -P ( -0 10 5 0 900 = B G L Q U Y ] a@ e@@ i m q t ze }e     @2Kn,X `%05075110134134.515020030060012001800240048009600extaextbeven-evenodd-oddrawa @ &X@a @ &$ @ X@&P@@P@ PA@,C('tP@mP$PA@&tA@$$@PPA@ B0&C@PA@X@PA@$Cюp(p(Ї$X( C00 0B 9B $, &C #юp(C@"p(ЇPX(PA@<BX,P$X,PX,P #юp(p(ЇX,$PX(PA@hP$P P  #%#$#юp(p(ЇX(X & C X@'xXP PA@,PA@Xp0Ї$#@ &"$@AX4P@ |%Q0C ~X4&P4X-B0X4XP X &P CX @-B0"@`X@ x&P@ xZ@ |PCl$Q@ lC%Q0C X4&P4XP@ pC$PX4X&PPA>CC@P@ &Y 3X#C@CX4X+B0TX@"h&P@"h B@bPAD$PA@A$PX4X&PPAC$X4XX @ x&P@ x"Z @ |PXX @P P@CCjX@ dX0Y4CFX PA@ Y@ xB$'t'tPA&tPA@&tPA@&C@DPA@lX@DPA@юp0p(ЇX(X(PA@ #$Cҽ&ɰ B0$#юp(p(Ї@DP'tX@ XPA4&tPA@#@PAAp$Q@ Xюp(p(ЇX(Y@ xCRX(Z@ |X-B0X(Z@ |X!4$ChX(Z@ |XCRX([@ xP(X(aX @ TX(aX@ TX@ P#ю0 PAz@ 0P  PAd@ 4P  PAN@ 7P PA4@ :P PA@ =PA@,юp(p(ЇX(P(C0$'tX(PX,P@ ?PA@,&tюp(p(Ї'tX,X@ @PX(P@ EPA@,&tюp(p(Ї't$P+P$PA@L&tюp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 't-rawcooked-nlnlecho-echoLCASElcase-LCASE-lcase-tabstabshup-hupcr0cr1cr2cr3tab0tab1tab2tab3nl0nl1nl2nl3ff0ff1bs0bs133tty3337tty3705vt05tntn300titi700tekekerasekillunknown mode: %s input speed output speed speed erase = '%c'; kill = '%c' even odd raw -nl echo lcase -tabs hup nltabcrffbs %s%d %s%d baud 0123456789ABCDEFCDEFLOSXcdeflosx>`Lx>`&X B'tP & PX PA@&t$P P юp(p(ЇX(X 'P C>'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(X 'P CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@%XP@XP@!P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@XCx@!P$Y@"hB d$!$C X,"Y@B0,&C$CZX," +P&C&CX@ xB0"@qX@ x&P@ xZ@ |P$PA@P@ dPA@!4" PA@ $P@ \X@ \$P@ \X@ \P@ `X@ \Z@ dP@ h@sP@ PX@ PP@ TX@ TX#6$Q@ T" X@ TaX@ dPX@ PPA@C PX@ PPA@ CdX@ TzB0$/%W@ P@X@X>$/V@ P@$QCX@ ?X,$юp(XP@ X !$P@%XP@ X !$P@%XP@XP@X !P@%            @ @           $'xXP PA@,PA@$Xp(Ї$Y(CZ,X-B0dZ,XC0$P@ 8CrZ,X&PA8P@CRC@P@$&Y 3X0C0X@ 8C0Z,XP@ <# Z,XP@ 8&CDX@ 8C0VX@ 8C0H@PX@ 8PA@|C('tP@XP$PA@&tA@$X@ ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~'X( %P(C #4'C  #3&"C' 0   C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@&x #3&"$P@CC@LP@&Y 3XD X@#:Y@#&X@ [@X0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@B 'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@(&t !$%C& & P P X&PX(#юp(X@X#X@ZP@ ,'xXP PA@,PA@Xp4Ї$P X4#@ PA@A@X8XPX&PPC0BX0!X9#,@+PA@A@X $ZP CX PA@юp4C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,X(CP@ L D!P@ h%XP@ TXP@ XX P!P@ h%XP@ `XP@ dX \!P@ h%a.out%s not found Bad format: %s %s: %l+%l+%l=%l (%x) 0123456789ABCDEFCDEFLOSXcdeflosx@L $@L $P$PA@$P$PA@ &P@pX('P@tX@x#8X@xPAA@ACюp(p(Ї@P@@ 0P@@P@|@P@$@$@X@|A 9@ DP@@ P@@B0Z@B0,A@X@B0 B0@&@@C X@|&P@|CCRX@|&P@|X@|&P@|$CCP C*XB0X$#8@&@ &P$$QC%QX!3P C&YLC0X>!8XP#'XB0&YL!9@&@'@|PXPA#8@&@X ^|^^`` &();v()^| R()<>  V , .HangupQuitIllegal instructionTrace/BPT trapIOT trapEMT trapArithmetic faultKilledIllegal addressMemory faultBad system callSig 14SigɐB0J C08 PAB0&XP@ sPA@PA@CCPA@ #:XPA@C/ . $ PA@#PA@CR. $ PA@#PA@C XPA@#XPA@ю|pp(ЇX( .B0 C0 .!5 #3$#$#юp(p(Ї$X(| &C0ɠ/!2Ҭ&"  !6@ C. $ @|#юp(C@"p(ЇX(P@ PA@X@,Y@ C X@,P@ PAosx&|H4`&|H4`P#@ CP@ =P @ :P@ 5P@ +PA@pXP@ GPA@A@XP@ TPA@CXB0A@!6P#$PXTB0t$PA@dxC0`'tXPXP@ cPA@&tAPP XP X C0X#6AP" X yB0,XPA@C0XP@ pPA@юdpp,Ї X,'t$PP$PA@&tю p,p,Ї 't$PP$PA@,&t#3$##ю p,C@"p(Ї,X( C0ɠ%@PA@@PALC*@PPABC0HX@xC0,@PA@X8P@PA@@PAC@PPAC0$P%PA C@PPAB0X8X P$PT!6A@0PX!:@ PA CDXC0$TC0$X()|^ "'Command line overflow Too many argsToo many characters;& <>([?*chdirchdir: bad directorychdir: arg countshiftshift: no args login/bin/loginlogin: cannot execute newgrp/bin/newgrpnewgrp: cannot execute wait:try again : cannot open: cannot create/dev/null/etc/globglob: cannot execute /usr/bin/: not found/bin/shNo shell! : too large : -- Core dumped**gok()XX'X7$@X[#@C"X@,X@ @P@ PA@юp(p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C'@   ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX( ! + E W i y '6G[o!Error 0Not super-userNo such file or directoryNo such processInterrupted system callI/O errorNo such device or addressArg list too longExec format errorBad file numberNo childrenNo more processesNot enough corePermission deniedError 14Block device requiredMount de#8PA@:C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C #3&"C' 0  9C'@   ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb 'xX(P X@ PPPA@<&x #3&"$P@ CC@ P@ &Y 3XDC0F$PX8XPA@XPXB"'t$P$PXPA@&tCJPX8XPA@PXC$X8XPA@:PAA@@$PA@XPA@XPA@$TC0B$PA@X#8@=#3A't$P@P$PA@h&tA юp0p(ЇX@#$P@X@$@'tX@&P@P$PA@h&tA@юp(p0Ї%P X &P X @<#2" X@Z &##AbX@&PXB&X@X.Z. @X'PCX Z@&P@@X @X 'P X B"X @X4PX0PA@X0P@UPA@ $PA@ C"X B0@dPA@ $ChPA@Y #2" XP C04X C0(X C0X0P@oPA@ AX#юp0p(ЇX@X( &X@&P@#2" #юp(P@p%XP@hXP@lXd!P@p%2DIOPSTUcmopvTT T/lib/cpp/lib/c0/lib/c1/lib/c2/lib/crt0.o/lib/mcrt0.o/lib/crt2.o/lib/crt20.o/usr/&C &#3&" X@ L#9X@ LPA@PPA@P@ LB P@PA юp8p(ЇX,PX(PA@$ PA@T$PA@юp(C@"p(Ї,X( C0ɠ%#8PA@TC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ P$ɠ.B0,&ӡɠ9B ɠ0B$ CP@ T'tPX PPA&t!&&C<юp(p(ЇX, xX(C'X( %P(C #4'C #3&" XP@XP@!P@%XP@XP@X!P@%XP@XP@!$P@%XP@XP@X!P@%.../ BPA@X@t & CPX@tPA@CX@t & C$P$PA@B0P$PA@X@tPA.P@x1X@tPAP@|2X@tPAP@3X@ B0X@tPAP@4$YCXC X@ @P@PA@ X@ @PAs!;X@ @P@C@P@x$YB X@ +"P@x&"X@ @+"&P@xX@ C0 iPX@ @PAvP@X@&P@x&$P@x@xPX@p(ЇX(X,X@ &X@#6$Q@" &X@&P@#2" #юp(p(ЇX,PAlo#4$CHX(&P(XC00 &C0 & !2" !5 !3$#X,C$#юp(p(ЇX(!3$# X(PA@#юp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX,c/cpp/usr/c/c0/usr/c/c1/usr/c/c2/tmp/ctm0a%s: cppc0-p-mc1as-o/bin/asld-x-o-l2-lc-l/bin/ld-- %s Can't find %s Try again Fatal error in %s 0123456789ABCDEFCDEFLOSXcdeflosxXd$<Xd$< C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb X'xX(P X@ TPPPA@&x #3&"$P@ TCC@P@<&Y 3XD X@ T#:Y@ T#&X@ T [@ PX0B0 &# PA@T" C P&A@T"  &# PA@T" X(#юp(p,Ї X@B $PX@xPA@C&X@xP@PA@$PA@$X@ #4%C 't@P@ PPA@&tY@C0hX@B0X@ P@PA@C2X@C ('tX@ PX@P@PA@&tP@$P@ X@ B0jB0$P@PA@X@ !5$Q@ $Q@  B0$X@ Y@|!$Q@ # Y@!$Q@ &Cюp(p(Ї@PA@$PA@юp(p(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@K$ɠ.B0,&ӡɠ9B ɠ0B$ CP@K'tPX PPA&t!&&C<юX@ |PA@<&tC*@ |PX,PA@\#$##ю p,p(ЇX,?X,$юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@<&t !$%C& & P P X&PX(#юp(XP@@XP@D& C$QCX@ P@PA@ A@ ю(pHp0ЇX0tPAH PAP   @ X@ C0"X@h&#2" @& @юp(p(ЇX(&P(X.,B0X,&P,!3$#C$#юp(p(Ї+*#юp(p(ЇX(  C H PA@ Cюp(C@"p(Ї,X( C0ɠ%#8PA@xC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %Pp(p(ЇX,K8X(C'X( %P(C #4'C #3&"C' 0  9C'@0  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- CbK'xX(P X@KPPPA@4&x #3&"$P@KCC@@P@&Y 3XD X@K#:Y@K#&X@K [@KX0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@B @`PPA@X@\C0@PA@$PA@Cюp(p(ЇX( -!2&XC0. B0/dev/rmmt0ff Forward Space Filebf Back Space Filewf Write File Markfr Forward Space Recordbr Back Space Recordrw Rewindffbfwfweoffrbrrwrewrewind %s Can't open %s Stty%s: %d error %s 0123456789ABCDEFCDEFLOSXcdeflosxlx8$Plx8$P       H PAhP &&  C H P&ABP&CH PA,PH PAVP 0H PAPH PAVP 8@tPAH PA C0X4#9@0PA@ CH PA`@#3$#$P &  C H C0H PAhC00@tP'tH PAH&tPAttCH C0  B0@tP'tH PA&tPA^t tC\H C0N%Q4B@tP'tH PA&tPAX #8@tPA@tPA&CC(C #4'C #3&"C' 0  9C'@t  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb 'xX(P X@ PPPA@&x #3&"$P@ CC@P@&Y 3XD X@ #:Y@ #&X@  [@ X0B0 &# PA@x" C P&A@x"  &# PA@x" X(#юp(p,Ї X@B P _ o @ d'xXP PA@,PA@ XpHЇ(@|P@h@ tPA@XHB0&@ PL$PHXHX@ #5$QH" %QH$QLXLXP$X$C0X$&P$C@PA@ A@ C$Q@ C%QH$QLXLXP@hCXLXPA$P@4$QL%QHClXLXPAP@4$QL%QHCF$P@ P@ |C4C@4P@P&Y 3XCXH!,@PA@ A@ XLXP@PA@ $PXLXPA@HPN%Q4B@tP'tH PAf&tPAX #8@tPAj@tPA&CCN%Q4BT@tP'tH PA&tPAjX #8@tPA@tPAD&CTX4!3C.@tPA%Q4!@tPA" $Q@ юp0p(Ї't$PX(PX@pPA@&t'tPX,PX@pPA@t&tC0X(P@9PA@ юp(p(ЇX( '#6$P &"юp(p(Ї~X@ X( '#5Z&"X@ P &3 P X(PA юp(p(ЇX@ B06@D#$##ю p,p(ЇX,?X,$юp(XX]P@`p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X@ X#X@ ZP@ P@d%X!$P@d%XP@(XP@,$!P@d%XP@4XP@80!P@d%XP@@XP@DX] [-r] [-e] 0123456789ABCDEFCDEFLOSXcdeflosxp|<(Tp|<(T(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cbt'xX(P X@pPPPA@0&x #3&"$P@pCC@P@ 4&Y 3XD X@p#:Y@p#&X@p [@lX0B0 &# PA@" C P&A@"  &# PA@" X(#юp(p,Ї X@ |B 'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX $% &!'(nt 1|2 qt pt pint floz 1|16 pt fldr 1|8 floz / US Dry dry 268.8025 in3/gallon fuzz peck 8 dry-quart pk peck bushel 4 peck bu bushel / British brgallon 277.420 in3 fuzz brquart 1|4 brgallon brpint 1|2 brquart brfloz 1|20 brpint brpeck 554.84 in3 fuzz brbushel 4 brpeck / Energy Work newton kg-m/sec2 nt newton joule nt-m cal 4.1868 joule / Electrical coulomb coul ampere coul/sec amp ampere watt joule/sec volt watt/amp ohm volt/amp mho /ohm farad coulkcylinder rptrack 10 block rpcylinder 20 rptracks rp 406 rpcylinder rftrack 8 block rfshoe 8 rftrack rfdisk 16 rfshoe rf 2 rfdisk / Trivia % 1|100 admiraltyknot 6080 ft/hr apostilb cd/pi-m2 are 1+2 m2 arpentcan 27.52 mi arpentlin 191.835 ft astronomicalunit au atmosphere 1.01325+5 nt/m2 atm atmosphere atomicmassunit 1.66044-27 kg fuzz amu atomicmassunit bag 94 lb bakersdozen 13 bar 1+5 nt/m2 barie 1-1 nt/m2 barleycorn 1|3 in barn 1-28 m2 barrel 42 gal barye 1-1 nt/boam 4|5 gal karat 1|24 kcal kilocal kcalorie kilocal kev 1+3 e-volt key kg khz 1+3 /sec kilderkin 18 gal knot nmile/hr lambert cd/pi-cm2 last 80 bu league 3 mi lightyear c-yr line 1|12 in link 66|100 ft longhundredweight 112 lb longquarter 28 lb lusec 1-6 mm-hg m3/s mach 331.46 m/sec magnum 2 qt marineleague 3 nmile maxwell 1-8 weber metriccarat 200 mg mev 1+6 e-volt mgd megagal/day mh millihenry mhz 1+6 /sec mil 1-2 in millenium 1000 year minersinch 1.5 ft3'xXP PA@,PA@tXp(ЇX(C *X,X-B0$Q@%Q($Q,X(C L$PX,XPA@pP@ C(X,XP@PA@|$PA@tX(B $PA@XP@ CNPX,XPA@,P@ C(X,XP@ PA@|$PA@tX@#4AP#A@ PA@юp(p(Ї%$@ PA@,B B0t&ɠB0h 'PA$@ PA@, !6ɠ#&"@ P 'PA@PA@&t !$%C& & P P X&PX(#юp(XP@ XP@ !P@ %X)!P@ %XP@ XP@ !P@ %XP@ XP@ X !P@ %XP@ XP@ X !P@ %Can't find %s Can't create %s Input file format error 0123456789ABCDEFCDEFLOSXcdeflosx::::z/ dimensions m *a* kg *b* sec *c* coul *d* candela *e* dollar *f* radian *g* bit *h* deg *i* / constants fuzz 1 pi 3.14159265358979323846 c 2.997925+8 m/sec fuzz g 9.80665 m/sec2 au 1.4959789+11 m fuzz mole 6.022169+23 fuzz e 1.6021917-19 coul fuzz energy c2 force g mercury 1.33322+5 kg/m2-sec2 hg mercury / dimensionless degree 1|180 pi-radian circle 2 pi-radian turn 2 pi-radian grade .9 degree arcdeg 1 degree arcmin 1|60 arcdeg arcsec 1|60 arcmin s/volt henry sec2/farad weber volt-sec / Light cd candela lumen cd sr lux cd sr/m2 / Money / epoch fri sept 6, 1974 wall st j $ dollar argentinapeso .102 $ australiadollar 1.4925 $ austriaschilling .053 $ belgiumfranc .0253 $ brazilcruzeiro .149 $ britainpound 2.3101 $ canadadollar 1.012 $ colombiapeso .0397 $ denmarkkrone .1603 $ equadorsucre .0401 $ finlandmarkka .2630 $ francefranc .2071 $ greecedrachma .0338 $ hongkongdollar .198 $ indiarupee .125 $ iranrial .0148 $ iraqdinm2 bev 1+9 e-volt biot 10 amp blondel cd/pi-m2 boardfoot 144 in3 bolt 40 yd bottommeasure 1|40 in britishthermalunit 1.05506+3 joule fuzz btu britishthermalunit buck dollar cable 720 ft caliber 1-2 in calorie cal carat 205 mg cent centidollar cental 100 lb centesimalminute 1-2 grade centesimalsecond 1-4 grade century 100 year cfs ft3/sec chain 66 ft circularinch 1|4 pi-in2 circularmil 1-6|4 pi-in2 clusec 1-8 mm-hg m3/s coomb 4 bu cord 128 ft3 cordfoot cord crith 9./min minim 1|60 fldr mo month mpg mile/gal mph mile/hr nail 1|16 yd nauticalmile nmile nit cd/m2 noggin 1|8 qt nox 1-3 lux ns nanosec oersted 2.5+2 pi-amp/m oe oersted pace 36 in palm 3 in parasang 3.5 mi parsec au-radian/arcsec pascal nt/m2 pc parsec pennyweight 1|20 oz percent % perch rd pf picofarad phot lumen/cm2 pica 1|6 in pieze 1+3 nt/m2 pipe 4 barrel point 1|72 in poise gm/cm-sec pole rd poundal ft-lb/sec2 pdl poundal proof 1|200 psi lb-@ PPA@ B&$#$@,&ɰ!PA$CPPA юp(p(ЇX(C0D@ PX('PA@$Y(C @ P @,PA@&Cюp(p(Ї@ PA@,BC0D@ PA@,#Ap 'B@ PPA@"CC: 'B0@ PA@,#A&@ PPA@CC`юp(p(Ї@ PA@|$PA@tюp(C@"p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ teradian radian2 sphere 4 pi-steradian sr steradian / Time second sec s sec minute 60 sec min minute hour 60 min hr hour day 24 hr da day week 7 day year 365.24219879 day fuzz yr year month 1|12 year ms millisec us microsec / Mass gram millikg gm gram mg milligram metricton kilokg / Avoirdupois lb .45359237 kg lbf lb g ounce 1|16 lb oz ounce dram 1|16 oz dr dram grain 1|7000 lb gr grain shortton 2000 lb ton shortton longton 2240 lb / Apothear 3.4 $ israelpound .2385 $ italylira .001508 $ japanyen .003303 $ lebanonpound .45 $ mexicopeso .08006 $ netherlandsguilder .3675 $ newzealanddollar 1.43 $ norwaykrone .1795 $ pakistanrupee .102 $ perusol .0234 $ phillippinespeso .149 $ portugalescudo .0387 $ singaporedollar .4035 $ southafricarand 1.425 $ spainpeseta .0174 $ swedenkrona .2225 $ switzerlandfranc .3314 $ taiwandollar .0264 $ uruguaypeso .00081 $ venezuelabolivar .233 $ germanymark .3744 $ mark germanymark bolivar ven06-2 gm cubit 18 in cup 1|2 pt curie 3.7+10 /sec dalton amu decade 10 yr dipotre /m displacementton 35 ft3 doppelzentner 100 kg dozen 12 drop .03 cm3 dyne cm-gm/sec2 electronvolt e-volt ell 45 in engineerschain 100 ft engineerslink 100|100 ft equivalentfootcandle lumen/pi-ft2 equivalentlux lumen/pi-m2 equivalentphot cd/pi-cm2 erg cm2-gm/sec2 ev e-volt faraday 9.652+4 coul fathom 6 ft fermi 1-15 m fifth 4|5 qt fin 5 dollar finger 7|8 in firkin 9 gal footcandle lumg/in2 quarter 9 in quartersection 1|4 mi2 quintal 100 kg quire 25 rad 100 erg/gm ream 500 registerton 100 ft3 rehoboam 156 floz rhe 10 m2/nt-sec rontgen 2.58-4 curie/kg rood 1.21+3 yd rope 20 ft rutherford 1+6 /sec rydberg 1.36054+1 ev sabin 1 ft2 sack 3 bu seam 8 bu section mi2 shippington 40 ft3 shorthundredweight 100 lb shortquarter 25 lb siemens /ohm sigma microsec skein 120 yd skot 1-3 apostilb slug lb-g-sec2/ft span 9 in spat 4 pi sr spindle 14400 yd square 100 ft2 stere m3 sthene 1+3 nt stilb cd/cm2 stoke 1-4 m2/sec stone 14 lb strike 2 bu surveyfoot british-ft surveyorschain 66 ft surveyorslink 66|100 ft tablespoon 4 fldr teaspoon 4|3 fldr tesla weber/m2 therm 1+5 btu thermie 1+6 cal timberfoot ft3 tnt 4.6+6 m2/sec2 tonne 1+6 gm torr mm hg township 36 mi2 tun 8 barrel water .22491|2.54 kg/m2-sec2 wey 40 bu weymass 252 lb Xunit 1.00202-13m #ю p,p(ЇX,?X,$юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@ %XP@ XP@ !P@ %X)!P@ %XP@ P@ !P@ %#!P@ %$*!X'PP$P@ %XP@ XP@ X !P@ %XP@ XP@ P@ %XP@ XP@ X !P C &P  %P X\ (PX PA@ 4P X XPX$ZPC2 $P@ PAC /BX@ Dюp(p,Ї $X, C02Š.C0*CŠa!Šz!#ʠҡ&&CC &" Ƞ.C06& C0* CŠa!Šz!#ʠҡ&&C C &" 't$P$PX@PA@ &t't$PPX@PA|&tXC0XPX@PA&'tP PX@PA<&t#8@ PAC. A@ &t !$%C& & P P X&PX(#юp(X@X#X@ZP@P@%XP@XP@!P@%XP@XP@!P@%XP@XP@X!P@%XP@XP@X!$P@%XP@XP@X!P@%FArg countCan't open %sCan't find %sCan't create %sIllegal os file type %oDirectory block read errorRead error - offset %oIndex block read 'xXP PA@,PA@ Xp(ЇX(#@PA$PX,XPA@ P@DCX,XP@PA^$PA@ $PX,XPA@ C0X,XP@PAX(BX,X PA@ LP@!&P@AX,XPA'tP@P$PA@ &tC *Q@#$ @&"@PAC #@PApX@B0X@P@CX@]@\@P@T@!8@PANA8AP@LPX@DPA&tюp(p(Ї$ CTX@LC0<$X@L#3'" X@L P@L  C&C@QPAlюp(p(Ї't$PX,PX(PA@ &tюp(p(Ї'tX0PX,PX(PA@ &t##$#$#юp(p(Ї'tX0PX,PX(PA@P&tY0#8@[PAюp(p(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(C@"p(Ї,X( 'xXP PA@,PA@Xp,Ї %Q,B .$PA@P@ $PA@$PA@CBPX0&P0XPA@P@ CX0P@PA@ PA@D@ PA@D$P$PA@$P$PA@A@,B00$PA@X@ PA@X@ PA@AX@ PA@A@,B0j$PA@X@ PA@$PA@X@ PA@'t$P@P@PA@&t@PAX@ PA@$PA@X@ PA@P@ %Can't create %s/bin/sh-Can't exec shell0123456789ABCDEFCDEFLOSXcdeflosx(~~4 (~~4 $C0PPA,#4 C0CX PCh$#ю p,p(ЇX(X,$ɰ C &&#3$#&"$#юp(p(ЇX(X[ ## !$ CzX B0%Q #PAlX &PPX@PA'tPX,PX@PA&tC0X P@ PA@DQ  #юp(p(ЇX(X$ZUB ZXXPX@PAh'tX PX PX@PA|&t#8@ PAX &P X&PXPX 'P юp(p(Ї't$PX,P error0123456789ABCDEFCDEFLOSXcdeflosxVxdVxdBюp(p(ЇX,PX(PA@ $ PA@ l$PA@ юp(p(ЇAlP@0PPA^PX(PA|P $$ % &X@P AP@X@P $P@@P@юp(p(ЇX(X, '#6$ &"юp(p(Ї$X( C02.C0*ɰCa!z!#Z,&&CɰCZ, &" .C06& C0*ɰ Ca!z!#Z,&&Cɰ CZ, &" юp(p,Ї 't$P$PX@DPA@ &t't$PPC0ɠ%#8PA@ lC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C'@h  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@ &x #3&"$P@CC@xP@&YA ю p,p(Ї'tP@ P$PA@d&tC D'tP@ P$PA@&t'tP@ PX@ PA@&tCA@юp(p(ЇX,PX(PA@$ PA@d$PA@юp(C@"p(Ї,X( C0ɠ%#8PA@dC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C 0X(PA@ &tюp(p(Ї'tX0PX,PX(PA@ &t#$#$#юp(C@"p(Ї,X( C0ɠ%#8PA@C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,(X(C'X( %P(C #4'C #3&"C' 0  9C'@   ;C # [,'$$0 $$ ?X,C(X@DPA@ &t!(@PAX!8@PAXC0XP@X@PX@DPAF'tP@PX@DPAZ&t#8@PArC $!4 C0"X@PClX@PX@DPAA@P@X@P@'tP@PX@DPA&tP@PA@#ю p,p(ЇAX@!ARX@&P@PPX@DPA'tPX(PX@DPAr&tюp(p(ЇA`P@X@PX@DPA'tP@PX@ 3XD X@#:Y@#&X@ [@X0B0 &# PA@ l" C P&A@ l"  &# PA@ l" X(#юp(p,Ї X@B -39?@FDPA&tX@P@P@@P@юp(p(ЇX@U@CX@&P@$PC$P@X@PX@DPA 'tP@PX@DPAv&tX@]@X @P(X@X@PX@PX@DPA'tP@PX@DPA&tюp(p(Ї't$PPX@DPA@ &t't$P@HPX@DPA@ &t!(@!PAX@HPX@DPA't P@LPX@DPA$&t#8@>PA<юp(p(ЇX@HPX@DPA't !P@@%XP@ XP@$X!P@@%XP@,XP@0X(!$P@@%XP@8XP@P'PA:C, #3$#$CC@ ,P@ @&Y 3Xюp8p(ЇX,!4$C:X(C0(X,PX(&P(PA#3$#C$#юp(C@"p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$C0"X@D&PA|#8$PA&ACRPA@ X,B0&P@@@ P@PA@ `@CA$PAPA.X C0X P PAbCX P#PAJCp$PACbʰ#$ɰ<#(@PA 'C0 $P't$PA<&tPACC@P@&Y 3XCюp(C@"X@8X#X@8ZP@84P@x%X!$P@x%XP@@XP@D'tP & PX PA@0&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@`&t !$%C& & P P X&PX(#юp(X)!P@%XP@XP@X!P@%XP@XP@X!P@%\C0@P@ PA$P$PA@#@PA\юp(p(Ї X@   C " Y(!4 C & #2"C$#юp(p(ЇX,PX(PA@$ PA@l$PA@юp(C@"p(Ї,X( C0ɠ%#8PA@lC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX, DX(C'X( %P(C #4'%<'xXP PA@,PA@Xp(ЇX(C@PA@$PA@P@ %Q(C0X,&P,XP@ X@ -B0$P@ X@ &P@ @ 0B,@ 7B X@ @  P@ CX@ C &X@ P@$PA@$PA@C@X@ PX@ PA@P@ X@ C&X@ P@8PA@$PA@X@ PA@C$PA@юp(C@"p(Ї,X( C0ɠ%#8PA@PC$&K'xXP PA@,PA@A Xp,Ї X,P@#xX@#x#(X0XP@dX@#x#(X0XP@h$PX@dPA@HP@LC X@dP@PA@DzCC@ P@)PA@D$PAC0.$# @* @*&" ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ $'tPX PPA&t!&&C<юp(p(ЇX, HX(C'X( %P(C #4'C #3&"C' 0  9C'@L  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb ('xX(P X@ $PPPA@&x #3&"$P@ $CC@\P@&Y 3XD X@ $#:Y@ $#&b line breaks on r read file b- line breaks off s substitute /old/new/ d delete line(s) t copy line(s) e edit a new file v globally if not f set file name w write on file g globally if x substitute interactively h display this summary ('.' to confirm) k mark line / delimit search string m move line(s) ? delimit backward l list line(s) search string o open line(s) for mods ! unix command (^H for help in 'o') = line number o\ replace line(s) X@#x#%$P@#hA@?R$P@"X@"C X@"\%P@#$Q@"C$P@"@PA@$<#7X@P@*X@H#*X@#x!$A@A@Gh@+HP$PA@I@4P$PA@I$ PA@FX@C0@PA@D<$P@@ P@AX@ C0X@ B0X@!B0pA@HB04'x$P @P@P@PA@H&xA@A PA@I #5#2" @PA@DX@0BX@9B $Q $P@X@0B0*$X@&P@x!7Ƞ$Q@#$X@ #' B( C" BX@ P@$Q@CC|X@.B0X@"P@$Q $Q@CJX@'B0X@&P@P@CX@"B0>X@&P@P@X@X@&P@P@ClX@:B0$Q $Q@A@>TP@CX@CX@ $ [@ X0B0 &# PA@P" C P&A@P"  &# PA@P" X(#юp(p,Ї X@B prompts off o- insert new lines % display context o+ append new lines & .-22,.p p print line(s) " .+1,.+23p q quit editor % .-10,.+10p @B0A@4X@\$!6/P@\X@ B0"/P@\X@#!7X@XQ@"CX@&P@P@\X@##=X@"P@#X@"P@" C0PPARX@ #;@ PA@D!X@l" !#A(X@"'," P@P@"юp(p(Ї@mPA@DP@PA@D@,<X@ XP@,8X@,8C$C( P@,@$CX(&PA@'P@,@$CX(&PA@' C$Q@,8 P@,@X(&Q@,@$C$Q@,8 P@,@X(&Q@,@$C P@,@$Ct$Q@,8 @,?#4P@,@$CR\`dw~"&'bdefiloC0@,<#4$C:PA@9 @,<!6 &Y(#$$CX@,@X,Q$#юp(p(ЇA@*B0AC0(X(P@PAJ#6A$C8CX(_B0AvAC0~@~ :X@Y@,B0AxC0N@~C0@X@C02X(&P@PA#:X@,PACC$CCx$CAC0@~ :@*P@PAfC0X@AC0D@~C06X@C0(X(P@PA#6PA#C$#Cpюp(p(ЇX@BXC C0@P@GPA@D B   &$PC B  $P CY@,!PACX@,AAC0X@İɰC0ɰ!6X@, C0X@,C0*X#8ɰ#5ɰB0XB0hɰ#5ɰB0ZY@B0p(p(Ї'x$P PX@P$PA@I&xP@\Q@\$CF'x$P X@Z@\PX@P$PA@I&xP@+&Cюp(p(ЇX@C .'x$P $PX@P$PA@I&x$P@$P@#$PA`A@A юp(p(Ї't$P$PX@LPA@I&t't P@PX@LPA@IT&tX@C0ZX@C0LX@ C0>X@dP@SPA@D<$P@#xX@LP@HX@TP@PCxX@Z@P@X@P@X@#8X@P@ Q@B0<'t@,=X@P@,<X@ TP@PA@D<&tC#8X@TC0C0BX@XB04't@,=P@,<X@ TP@PA@D<&tCPA@D< Cv@PA@D$@,> #9X@" P@,@#X@" P@,@$CC'!)!X@ C@,>X@P@PA@DP@PA@DC0X@P@PA@DC0VX@P@P]0X.D&PDX]PX$PCXD$#ю p@p(Ї,X( C0ɠ%#8PA@FC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@,D$ɠ.B0,&ӡɠ9B ɠ0B$ CP@,H'tPX PPA&t!&&C<юp(p(ЇX,,lX(C'X( %P(C #4'C #3&"C' 0  9C'@x  ;C # [,'$$0 $$ ?X,CX(dsxP>~B"&'bdlox "^|"@ v#.=bcdefgprsw , 8Lnv V  8|!$/;=?^  2  6Ha.outcoreHangupInterruptQuitIllegal instructionTrace/BTPIOTEMTFloating exceptionKilledBus errorMemory faultBad system callUnable to open %s Symbol table too large Can't read sy@!*X@P@$CX@B0F$Y@+C4X@*Y(B0X@"Z@P@$Cr&C$CfX@B0T$Y@+CDX@*Y(B0, !4$C0X@"X @! 'P@$C&C$#$#юp(p(ЇX(X,&C &&#3$#" $#юp(p(ЇAA(C0` T@C0NX(U@B@X([@ B 0X@!8X(Y@B0_PA$X([@C #юp(p0ЇX0İðC0, &PAP 'PAVC8$Y@tB 0_PA$CR BX@#X@  #[@ C  #_PAfCBY@,!3%# #ю p,p(ЇX@,$Y@+C,X@*Y@,B0X([@"#&CA|AC0@~ :X@Y@,B0A~C0\@~C0NX@C0@Y@B0_PA$C>X@  C  #_PAtCY@,!4%C  #C^%#юp(p(Ї$X@"X@C0|#;@cPA@D7X7z7677088*8>8R8f8z&|9Z9$9\%o%c*** symbol not found ** invalid function argument specifier no core image file %2d: %.8s(%o,%o) ** unable to read core file ** uneimquy}chiahishisrhlslhlsrhaslhastmlmstblbclbalwbrbwhrhwdrdssoctssvcsintscplatlatrrlrllsrlsllsraslatiniclioixiliciaisinopbbmbnmbpbnpbnebebobnoblbnl ?? %s %s,%s %o,r s %s%o(%s)(%s,%s*** not an active function ** no such special symbol name Unknown termination status Termination status: %o %s AAAAAA AAAH0123456789ABCDEFCDEFLOSXcdeflosxENEEEP@u0X@u0PA@#X@u(Aюp(p(ЇX@u  ?@C$P &' 5X'PB0Cюp4p(Ї'tP@,(PX@uPA@$&tC04@'$PA@`$T@u8!4A@L,($P ' 4$Q@u юp(p(Ї'tP@,(PX@uPA@%&t#<@'5PA@`A@L$Q@uюp(p(ЇX(P@u 't$PX(PX@uPA@$&t#Aюp(p(ЇX([@u# C L C0F't$P 'PX@uPA@$&t't$P@uPXPA@`A@LaPATBU@u$#$P@u$P@tPA@vX@dpP @du @dv $T@u8#9$@dw$P@dxX@dx X@dxP X@dP X@dP ю p,p(ЇX,X($X,'P,C0*ӭ& &X, !3 # C #юp(p,Ї .($PX C0xP@tPA@X@uC BtX@uX C0 &&B0(" #7 /B0PX,A$Q#ʰU@u$C rXB0,X@uC X@uXP@'PA@`$Q@uX@able to read a.out file ** invalid address ** can't access bss - no core file can't read core file %.8s%o(r5)%.8s+%o%.8s%o** not on word boundary Unable to write child memory addr = %o value = %o no write access to core file no write access to core file no write access %s ?? no breakpoint cant initialize from fcore fcore seek error fcore read error Not a.out format: %s *** invalid breakpoint condition *** invalid breakpoint condition 0369<?BEHKNQ "%(+.15:>AFJNRVZEEpE\EENEEEEEpE\EE:p(Ї@&PA@`ALюp(p(Ї$ T@u8#3AX@t!#AA@@PA@A@|Aюp(p(Ї$ T@u8#5A@H#A@A@ A@0Aюp(p(ЇCT@u8#3A0A@ T@u8#9@&PA@`@PA@AFюp(p(Ї$T@u8#3AA@@PA@A(юp(p(ЇA@A юp(p(Ї@&PA@`A@(юp(p(ЇX(X@u4X,PX@u0 #@&PA@`A &&#2" X@u4  !P@u4C(@uPA@$&tP@u't$PPX@uPA@$&t#A юp(p(Ї@'GPA@`A@Lюp(p(Ї`T@u8!4$C't@tPX(P@'XPA@`&t@T@u8B0@'_PA@`$CXA@0n!:A@0 !4A@L !4%C,yB0A@0 !4$CA@0 #2"C^юp(p(Ї%Q@tB0.@t$@tAzCB%Q@tB6X@u&P@uXt &&#2" A8Cюp(p0Ї$P@tPA@$tP#A'tP@tPXPA@t'P@tB ю p,p(ЇdPA@ P!X(PA@~юp(p0ЇA.(X C0T C0X !6 C0 X PT #4$QX@uP $Q X ZY@u!A$X C.$@d#5P C&CX P PAHU@u$C 6A@|A юp0p(Ї.($X C0T #8X  #XU@u$C C06X P X !6 C0P@tPA@PA@ ~$P@tPA@$tC@tP@'PA@`TWZ]`cfhjlnprtvx{8= BGJNQTWZ]`dhmrw|) 1)^adhknqtwz~:::::8:8:n;D;D:>:R<<<<<=P=*=n=n==n=nr0r1r2r3r4r5r6spr8r9rarbrcrdrerfpcps89lmqadrfslnormal exithangupinterruptquitillegal instructiontrace trapIOT instructionEMT instructionarit, 0X@u4P@&PA@`X,PA@~юp(p(ЇX(X,X &&#2" юp(p(ЇX@u.($P &' 5$P@u$юp(p(ЇX($$P &' 5Y@u$B00X@u$P@u$.(#$P@u$#X@u$XC0юp(p8Ї$PAV$PA:AZ@.'@.&C0$T@u8#;P@uX@uP@u@.(PX@uP $T !8A@,(P PXPA,X PX B0XX C0P@u$PPA@v ! P  "  # % '&P $&tP C0X !:XPA@$0CxA~@t@tC0tt .C0&#2"' @/#6/ & &&#2" AH$ C@юp0p(Ї@tP@'aPA@`A@Lюp(p,Ї @dhP@tPA@%0#$PAX@dpİ`#8ɰ@!3AC$P.(X !8X!3PCP@tPA@tt & B0X& <T@u8C0(X Y@dB X Y@d!8X Y@dCrPABCt#U@u$C VXB0(X@u$U@u !@'yCH X  C06'tP@,(PPA@$&t#3AA@ 'CX C0*'tP@,(PPA@$&t #3ADA@ 't$P@,(PPA@$&t#3APA@$0Cюp(p(Ї@tP@'PA@`юp(p(Їd$P &' 5X@u. ʰX C0$T B0X !5 #5PA'B0юp(p,Ї X, X T #2&X U@u!AP$@d#3A$ @d @d&Bю p,p(      "$&(*,16:>BFJNQTWZ]`hmetic exceptionkilledaddess faultsegmentation violationbad argument to system callbalrbtcrbfcrnrclrorxrlrcrarsrmhrdhrsrlssllschvrbfcrlpsrmrdrbtbsbtfsbfbsbffslislcsaissislerceraersermerderfxrflrbtbsbtfsexhrsthbalbtcbfcnhclhohxhlhchahshmhdhstambtcbfcncloxlcasmdcr12cr16steahmatlablrtlrblleceaesemedestmelmelhltbtsbtrbtcbtsrlssllsstbrlbrexbrepsrwbrrbrwhrrhrwdrrdrssrocrbxhbxlelpswthinhiclhiohixhilhi%pK'xXP PA@,PA@(Xp(Ї"P@u(P@u8X(P@uP@t#$P@tCNX,XX,&P@u &C0. C @%@%"X@u8P@u8CRPACX@u8P@u8CX@u8P@u8CX@u8P@u8C$Q@uPA@4$P@ $P@ $P@ X@ P@ A.!6AC$P@ A;!6,P@ ,C0X@ !7X@ P@ A!Z!#  CAAX@ P8PACAvP@P+#4-!6$P@P# #3A-!4#CALA2AX@ 'PPACA$A A`CX@#3A6AAP@P #3A$@AvX@ P@ C X@#3AA^A$P X $P  Q Aɰ0!ɰ9C P@P !4X@  # [ P X  $C$P !3 #4$Q CCp& !4X@ C`' !4X@ CPPAX@ ɰ/B0&U@ #$X@ # 'U@ #X@ P$PAB0Y@ !9?PAACCX@ CX@ CAɰa!ɰz##AX@ U@ B X@X-  #4&CCNP@P !4$CL  U@ !U@ ##Af C,C@YBYB0.X C"PPA@PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(# PA@"" X(#юp(p,Ї X@)B 'tP & PX PA@$&t'P  #%C & P X&P#юp(XX]P@, p(ЇX,X(%Q CNX C06'tX & P & PX PA@%&t !$%C& & P P X&PX(#юp(X@+X#X@w #:P@P$@A@PATC$PACAp$P@ PA@:4P#@PAC'tP@$P$PA@:CB$P@C6$P@C*%P@CC@P@0&Y 3XCX,X!5%P@$Q,%Q(X(C :X,X &&#2"  'PAt@P@ $PA@9,P@ X@#(@PAAz$P$PA@:B0P$P>AAAnX@ P@ X@ P@ X@ P@ X@ U@ #%X@ #X@ &P@ CZANA`AX@ P@ X@ P@ X@ (P@ X@ U@ !(X@ &P@ X@ U@ #'X@ P@ X@ '$ PA&U@ B 4Y@ !3A\'tX PAr&tPApY@ !3A8CCX@##$#X@P@A@7$P@A@7AAZX@ [@ P@ A$ PAFCACX<C0>$PA@8xC0*CC@DP@&Y 3X|A"Cnюp<p0Ї$$Aɰ0Bdɰ9B \CJ$P@ %C<'t$PP$PA@:`&t!&%P@T# P@T#ю p,p(Ї'tP@ PX@ PA@:`&t'P@ #%C\  X CX X&P$ &X &P &C)B0.XC >$ &X'P &CN$ & C0 &C4$ &C(CXC0X !3AXCA|P@P B0x$ &C$ &$ &$PAJ^!8A>$ @ C0d&$Q CNA]B0XXCb$ &&C@P@&Y 3XC2$@ X@ #4$C< &&#2" X@ P@ C,X,Y@ !4$CX,XPA$P@  Ӽ  B0PPA\#7P@ $CB&B0$C.PPA,#7P@ $C&B0$#юp(p,Ї X,X0 &Cl &&"<$Cr&B0$C^ C0$CNP@ $CB't$P P&PA2&t#6 C$C't$P P&PA&t#6 CV$C&P@C>&P@C,юp(p(ЇX(0#$C>X(9!$$C.X(_P(X(A#$CX(Z!#$#$#юp(p(ЇX@ #;X@ P@$P@ < &&C0  &&" P@AP@$#юp(p(Ї't$P+P$PA@;P&tюp(p(ЇX( C0.& #2"'t [(PX(P$PA@;P&tюp(p(Ї@PA@'^@PA@'^@PA@'^@PA@'^@$PA@'^@RPA@'^@sPA@'^@PA@'^@PA@'^@PA@'^юp(C@"p(Ї,X( C0ɠ%#8PA@'C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@,$ɠ.B0,&ӡɠ9B ɠ0TMPepqs !"%&<=>abcdefghiklmopqrstvwx h* `:> .  V~NVPrH $'+-./?^ V V Z j z z j @ $*.[\"#""#"" #%%%%*     $*P@P gB0$P@PXPA|P@P nB0$P@PXPA\X#ю p,p(ЇX6C2'tXX@PXX@PPA&tC\X & !ARC>X@  < P@  &&#8 !A"< &&#2" ю &#2"CX & !2"&CB't @#5$P#$P P&PAn&t#3C #'Y@ C0PPA#4$C0B $C$ATC' ' X@Cnю p,p(ЇX(X,!4$C.ӽ&'C0 & !5X0C" X0#3$#$#юp(p(Ї't$ PX@ PX@ PA@9&tP@ $P@ X@HX@ #3A 0PANюp(p(ЇX($P@  C0 P&A" $ PA юp(p(ЇX@X(X@ C0$Q@ X@ HB$P@ "C8 B. PAB0 '' !4%QC&&C C0H PA B0> ZU@C .$ PA$ PXPA&X &Cj !4$Q && ZY@!6$PATC4&#2"'CTPAfCHAC@X@ CX@P@ @ P@#C`C &&#2" A< $PC@PA@'^C C0 B0 P&&AC PARC0 PA@C00 P&&AJ ZY@!6$PA2CB$ CP@0'tPX PPA&t!&&C<юp(p(ЇX,TX(C'X( %P(C #4'C #3&"C' 0  9C'@(  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb4'xX(P X@0PPPA@8&x #3&"$P@0CC@8P@|&Y 3XD X@0#:Y@0#&X@0 [@,X0B0 &# PA@'" C P&A@'"  &# PA@'" %%Z&%&%>%N%rEditor/usr/lib/emhelp/usr/lib/emhelp not found?/bin/shsh-c!/tmp/exxxxx %d ^? '.' to confirm +-;\)))()(!#'()@\^2&2b2N122b2b2:2n #@\-&-X.&-...11.&.//J/^10-11j11z2\ \ sorry, can't spell today\ !! ^A display Again ^Q next characterQl P'xXP PA@,PA@JXp,Ї AhX0PX,PA@ X@U(P@fA@$A@-0A@&A@.A@7A@>AApю p,p,Ї $P@CF$PXPX!7$P@C"XPX!6$P@#$P@ю p,p0Ї$PA@JLX@U!7$PA@J$PX CXPA@J$QCX@CX@UC0.X@#@UPA@Jp# @UPA@JpC*X@#@UPA@Jp# @UPA@Jp$PA@J@UP Xp,p(ЇX(X,X0C && !A" #юp(p(ЇAnA A|!3AADX@ X@ X(C0X@ P&PAX@ &C@  P@ & C0`PPA^PPARPPAFC8B.P@ &PPA(PPAPPA#Aюp(p(ЇX(X,'XC X P P&" юp(p(ЇX@ U@ #$%C X@ &P@ XPA$#юp(p@Ї  #B0 <- &$ &&CH C: C02\ & 0 & 0 &$Q@ #& #6B4@P@'t P@P$PA@;P&t#P@юp(p8ЇX@p P@$P@ A@P@PPC8$P A@X@ P@ C6$P C,$P C"CC@pP@&Y 3X$P@PX@ Y@ #4A@$P@X@ X  PPA@X@ X ' P@ P@ A@ A@ \X@ Y@ !4A@A@P B0@ B0h ZU@C ($ P&X &$ PA$ PA B0$  B0 P&&ACC\ C0R PA|B0@ !4$Q P&&Av ZY@!6$PA^CC8 C0' !7 B" PAC0F' PA#7 B\" B0' !7 B8" C2 B( PAB0 ' !4%QC&C $PC$ P@T@PA@'^AA@#PAf C0' !4%QXC0VC$ PX X(#юp(p@T$p@T$ppЇPPXpPA@9B$P@PA@:4#xCX 'tPPPA@:`&tB0VȾ   B0< tB00 tB0$ yB0 C0 !4 #Cx#юPppp(ЇX,?X,$юp(XX]P@HX@X#X@ZP@P@L%X!$P@L%XP@XP@!P@L%XP@P@!P@L%#!P@L%$X ^B backup word ^R Release margin ESCAPE ^S re-scan from Start or ^D close line and exit ^V verify spelling ^E display to End ^W next Word ^F delete line Forward ^Z delete word ^H Help # or ^X delete character RUBOUT exit unchanged @ delete line backward Other characters (including RETURN) inserted as typed0123456789ABCDEFCDEFLOSXcdeflosx6^67 7 666l66^67 7 666l66J/devx@UC0B'x$P X@#@UP#@UPX PX PA@P4&xCXX@C$'t$PX PX PA@P4&tC*'x$P @UPX PX PA@P4&x@UPAxX@UC0.X@#@V PA@Jp# @VPA@JpC*X@#@V/PA@Jp# @V>PA@Jp$PA@JC'!)!X@Uюp0p(ЇX@PA@JLX@P@ юp(p(ЇX@PA@JLX@P@ юp(p(ЇX,&P,X.(#6$Q(CX(#юp(p4ЇX4XP X X#%$Q "X. [X@pP X XX@8P@PA`P@VPPXPAFPX &P X4Y!4_# X&PX XPC $XPA4PXPAPCX$@#юp4p,Ї X,!X,X@8#X,X@XPX !4$QX#ю p,p4ЇX@UB0>X@UB04AX@U(P@VTPA@K@X@UDP@VdPA@K@X@Q P@VuPA@K@@VPA@K@$PXY@U(B >XX@\B XPAP@VPA@ X,P,X,!;@XPA@K@C@XPA@K@$PXY@U(B NXZ,XX. C0 XPAhP@XPA@K@$QC@XPA@K@ю p,p<Ї%P@$PX<BX@X-B0X.@X&PC0X@XCwP@ZPA@IP@X@#@ZPA@ C$P@UC$P@U$P@UC|$P@UCpX@XP@ZPA@ C@XP@X&Y 3X$C.$Q@%QX X@pXB X X@pXZ@U@$P@$Q C$P X Y@Q8CX K@$QC@VPA@K@@VPA@K@$PXY@UDC*XX@8P@VPA@K@$QCX@UDX@8P@VPA@K@A'|X@UX@UC0t@[1PA@K@@[LPA@K@@[jPA@K@@[PA@K@@[PA@K@@[PA@K@@[PA@K@CP@\PAY@U,BX@U,P@^PA@ X@X@U(P@XX@ B0,X@B0X@X @U(#P@\CX@ B0X@\B0X@B0X@CX@U($P@\CX@U($P@\CX@U($P@\CX@U($P@\CpX@U('P@\CZX@U("P@\CDX@U(\P@\C.@^PA@ C@YP@Y&Y 3X CX@7B X@0BX@0BHX@7B 4X@0B X@7!(X@ #5C@_PA@ #5C@_PA@ #5C@_PA@ #5C@_PA@ #5C|@_PA@ #5C`@_PA@ #5CD@_PA@ #5C(@_PA@ #5C @_PA@ #5C@_PA@ #5C@_PA@ #5C@_PA@ #5CX@P@_PA@ X@Ux C0X@Ux #8X@Ux B0$X@Ux !5$Q@A@KP@UxCX@Ux:#5C"%P@UxX@Q@Ut$P@ #юpP$P@UX@U#:A@$PA@Jюp4pDЇ$X@UD&PA@ P@$P X Y@UDB 't$PX@fPX PA@ 4&tX Z@XPX Z@XPXUCXXP X XPC `XC6X X $X. X@P@C"CXZ@U@X@#6$Q C$QCl$Q C$PXC0$P$P X Y@UDB X Z@XPX Z@XPXUCXXP X XPBf'tXPX PX X@pXZ@U@X@B0tX X@p&PXXB"XXZ@U@X@#6$QCXXC$X X@pXZ@U@$P@CV$Q CRюp0p8Ї$P@Q X@Q,P@fP@f't$PX@fP@PA@ 4&t@PX@p&PA8$P@s$P@Q X@fP@f$P@Q4't$PX@Q0P@PA@ 4&t$PXY@Q C"XX@sB0X$P@s't$PX@U(Z@UD&P@$PA@ 4&tXPA$PXY@CDXX@B0*X$P@XX@X@WPA@K@'tX@UdPX@U`P@WPA@K@&tX@UTP@XPA@K@X@UXP@XPA@K@X@Ul!6X@UpC0$PA@JL$P@ @X6PA@K@X@UlC0X@UlP@XCPA@K@X@UlC0X@Up#9@XSPA@K@X@UpC0X@UpP@XVPA@K@@XgPA@K@юp4p,Ї $Q@U$PA@JL$P@ @XiPA@K@X0PX,PA@K@X@UtP@XyPA@K@X@U#9A$PA@Jю p,p(ЇX(P@XPA@K@$P@юp(p(ЇX(P@XP@K@@\>PA@K@@\]PA@K@@\|PA@K@@\PA@K@CAhACX@XP@\XY@UC,XC XX@XP@\PA@ C@X P@\PA@ C@YP@Y0&Y 3X,#CX@Q,P@pX@Q,&P@Q,PX@Q,&P@Q,PX@Q,&P@Q,$PX@Q,&P@Q,$PX@Q,P@t$PAP C$X@Q,Y@tB0*X@U#:@\PA@K@# @]PA@K@X#9@]PA@ $PADX@Q,PX@Q,X#@]2PA@ $P$Q@Q,C^$P#9@^PA@ X@X @" X @" PX @U(#P@\X@U(X@\!9@_PA@ CX@U0&P@U0X@U(P@\X@U($P@޼X@U(#юp4p(ЇX@UY@U(B X@X !2& C0:a!zC A!ZC 0!9#$_!2#CP&C'xX@\P X@XPX@U#6 P##P@_(PA@K@&x&CLX@U(&P@Uюp(p(ЇX@U4PU@ !+@_9PA@ CX(X@ &P@ юp(p<Ї$PX@UxB(X<p0ЇX@ !4$P0$P X Y@U(B 8X X@XPA@ #;X@P@ X C$Q C$P X Y@UDB >X X@8PA@ C0X@P@ X CR$Q CX0C .X@ C0X@P@` PA@ X0PA~#юp0p,Ї A@KPX !:A@KP$Q@UtXC0X\B0 A@KP}C0x\PA@MX%B0 A@KP}C0L%PA@MXPA@MX !5$Q@UtA@KPCr@`-PA@ ю p,p@Ї $PAPA@ v&tPXVPXZ@U@X#6$Q C$QCb$Q C"C $P X Y@UDB .X PAX Z@P$Q CX@`C0A@$$P X Y@UDB hX X@8P@`PA@K@X Z@XPA@ X Z@U@XP@`PA@K@$Q Cю$pDpLЇ,X@Q X@fPX@Q X@fPXY!4$CX'PXUC X'PXUBnXXX.UC PXXP(XXX.PX(XPXXP(XXX.PX(XP%QPXB JXX@fX."[@fYB $XX@s!3$#$XP@sCXP X Y@CVX X@XYB04X PX X@&PAX $P@$Q CXCXPANXP@$CXPA2XZ@U(P@$$QCX@`C0A@$XP@aZ,X-"Z.0VZ,X #2$Z(P&C #юp(p,ЇAX@Q,PX@Q,XC X@Q,XX@޼X @Q8"P@Q@$Q@Q,X!9@]WPA@ CX@Q8X@Q@P@Q@X!9@]aPA@ X@Q8PX@U#7@]{P#@]PA@K@A*X@U#7@]P#@]PA@K@XC0N [@Q8X@Q,&P@Q,PX@Q,X@Q8&P@Q8P@pX@Q8$P@Q@$PX |B0,$PX@Q8X@lXX @Q,&P@Q,PCX#9@]PA@ A@TAX B0A@KP#9XPA@M"CX!9@]PA@ A#9@]PA@ $PA@UxPX@Q@Ut%P@Ux$P@#A@KPX C0X #7X B0 X !5$Q@UtA@KPCX/B0|A@K*#9@_bPA@ A@KPXC0>X !5$Q@UtX*B0A@KP/#9#A@KPCX!4$CC$PXCXP X@ P@ PAh$C0hA@KPX #4X!9@_lPA@ X\B0A@KP\PA#XY #9XPACC*A@KPCBCJCBC:C2C*C"C$PC@YP@Z&Y 3X@KPXCX!:XPA@MCC$QC$PA@KPX$!;@`X*B0 XPA@MA@KP/C0XPC%QCfX[P$XL!XLX@d#XLX@ C02X@fP X@fPX[ P X$Y B0XPX PXUC$XXX.YB0$Q$QCXYB0X@Q X@fX @Q "P@fXPX PXUCd'tXXPXXP@PA@ v&tC0"$P@s@PAXP$Q$QC CX@CXX@Q P@fX@Q &Y@Q$!@`PA@ XLB0XLX@dX @Q "P@X@Q XLP@dC,XLX@X @Q "P@@K@&t$QC@aQPA@K@X@U(P@$PA@X XXP$BNX(!6X$P(#X(Y$B02$Q CX@aC02A@$'tX(X@8PXPP@bPA@K@&t$PXYPCXPX@lX." CP@ 'tPX PPA&t!&&C<юp(p(ЇX,DX(C'X( %P(C #4'C #3&"C' 0  9C'@c  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb$'xX(P X@ PPPA@N&x #3&"$P@ CC@cP@c&Y 3XD X@ #:Y@ #&X@  [@X0B0 &# PA@M" C P&A@M"  &# PA@M" X(#юp_f./yopt -r./yopt -rv./yopt./yopt -v/usr/yacc/yoptchar, yyerrf, yydebu integer yyprdn,yyval,yylval,yypv,yyvalv #define yyclearin yychar = -1 #define yyerrok yyerrflag = 0 extern int yychar, yyerrflag; int yyval 0; int *yypv; int yylval 0; yyactr(__np__){ please define type # of %s earlierbad precedence syntax, input %dgoto 1000 switch(__np__){ previous rule not terminatedtoken illegal on lhs of grammar rulemissing :semicolon preceeds action %d case %d: return break;rule not terminated before %%%% or EOF%%prec must appear inside rule# ,"P@&C$Q@$QC&CCX@Y@UL#'X@P@ULX@`C0A@$'tX@QPXDP@ahPA@K@&t$Y@CzX@#9@aPA@K@$P@ PA@P@aPA@K@ PA@ @aPA@K@&C|ю$pDp0Ї$Y@U|CXX0X@f PUCX &&YB0" C&CX@U|&Y@U!@aPA@ $P X Y@fC.X Z0XX0@U|$/Z> 2P@$Q CX@U|&P@U|#юL Y@Q0!@b]PA@  Y@Q4! P@Q4 Z,X- ,"P@&CX@aC0b$Y@Q4CV@bsPA@K@$ B & X@P@buPA@K@&C@byPA@K@&C C&C@b{PA@ ю p,pHЇ(A@T@bPA@ $P$P$X$Y@UDB X$PAXX$P@d%P$P$P X Y@Q B X X@sC0|X X@sYC0h$PX X@sP X PXY@Q B "XX@sY !4$Q$QCXY#)X PXP$Q C\X'Q@Y@lB0X@aC0$'tXPXPP@bPA@K@&tXX@fPXX@fP X UCX XXY(B0F$Q C [XPP@sXX@sQ@U`$Q@UdXPPA'tP & PX PA@P&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@P&t !$%C& & P P X&PXi-r-rv-voptimization execl call failsMH2019.yaccopt -rMH2019.yaccopt -rvMH2019.yaccoptMH2019.yaccopt -v : int nterms %d; int nnonter %d; int nstate %d; char *yysterm[] { "%s", 0 }; char *yysnter[] { "%s", "%s" }; %d/%d terminals, %d/%d nonterminals %d/%d grammar rules, %d/%d states %d shift/reduce, %d reduce/reduce conflicts reported %d/%d working sets used memory: states,etc. %d/%d, parser %d/%d %d/%d distinct lookahead sets %d extra closures %d action entries %d action entrieillegal %%prec syntaxnonterminal %s illegal after %%prec%%{ appears within a rulesyntax error, input %d 1000 goto(%d,999),yyprdn 999 return end define YYERRCODE %d } return(0); } int yyerrval %d; too many nonterminals, limit %dtoo many terminals, limit %dinvalid escapeillegal \nnn construction'\000' is illegal%c define %s %d too many characters in id's and literalsillegal /illegal or missing ' or "termTERMtokenTOKENleftLEFTnonassocNONASSOCbinaryBINARYrightRIGHTprecPRECinvap0p8ЇA@T@aPA@ $PXY@Q C XX@s#3$#$P@QXPA@2p't$PX@U(&P@$PA@ 4&t$PXY@CbXX@XPXC 0#C0X X@$B0XX P@$C`X X@$CA@$'|X PA@PX@UHP X  [@$PUXA@T$P X Y@Q B `X X@sC0FX X@sYC02X PA@ X X@sPA@ $Q$Q@UT$Q C$Q@UT%PA@ XPA@ $Q$Q$CfA@ @bPA@ $P$X$Y@UDB X$X@dPA@ $Q$CA@ ю(pHp<Ї't$PX@UD&P@$PA@ 4&tX<$P@$$PXC0$P$PXY@Q8CtXX@pXPBLXX@$C0PA@K@CXP@cDPA@K@C [P@cMPA@K@$QC6X@UHC0X@UHP@cWPA@K@# @chPA@K@A@Tюp<p,Ї X0rB0"$PX,PA@P`PP@C`X0(#юp(X!$P@f%XP@fDXP@fHf@!P@f%XP@fPP@fTfL!P@f%XP@f\XP@f`fX!P@f%XP@fhXP@flXfd!P@f%XP@ftXP@fxXfp!$P@f%XP@fXP@fXf|!P@f% yPs saved through merging %d states %d goto entries %d entries saved by goto default conflicts: %d shift/reduce, %d reduce/reduce fatal error: , line %d int %s[] {0,%d ,-1}; memory overflow NULL { %s }ORSVorsv 2 > R 2 > R ^,; R ":(4;=| ZDZ0FN"'\bnrtlid escape, or illegal reserved word: %s%s should have been defined earliereof before %%}yyvalyyvalv(yypv%c%d)yypv[%d]EOF inside commentEOF in string or character constantaction does not terminatenonterminal %s not defined! %s: %d too many statesputitem(%s), state %d yacc error--duplicate itemout of state space%d: %s %d, %s %d, working set overflow State %d, nolook = %d flag set! %s too many lookahead sets:R:::yyact %d: reduce/reduceXP@aPA@K@&|X  [@$Y@UH#+ [@UHX P@$$Q@UpA@TCX PX@UHPA@CA@$'|X PA@PX@UHP X X@$PXP@bPA@K@&|$Q@UlA@TCJ [@UHX P@$C2X P@$CCC!)!X@a$Q C8$QCXPA$QCA@TA@ A юp8p0Ї@b:PA@ $P $PXY@Q ClXX@sC 2X XP@$X PA@ XX@sQ C X." [@sX@$PA@ $QC8P@bPA@K@$PXY@UDB :XX@$C0 XX@8P@bPA@K@$QC@bPA@K@'t$PX@Q P@sPA@ 4&tA@$X<X@8P@bPA@K@$PXY@Q CXX@fPXX@fP X UC`X XXPB>XPX@$C0&XX@Z<X@X."P@s#$Q CXX@sC0,'tXX@sPXP@bPA@K@&t$QC юp<p0ЇX0X@Q@P X4X@޼PX#5$T !4$C4XX  !7XaB0:$PX,PA@P`P't$P$PXPA@P&tCPX,PA@PPX#ю p,p(ЇA@JX(P@d4юp(p(Ї@cxPA@ юp(p(ЇX(PA@Oюp(p(ЇA@JX(PA@Jюp(C@"p(Ї@d4PA@Nl#юp(p(Ї@PA@N#$# #юp(p(Ї,X( C0ɠ%#8PA@MC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$2%02<=>\{"%'\zz "$'/;{}$~$$"##j!" #H$y.outputcannot open y.outputillegal option: %cyacc.tmpy.tab.ccannot open table filecannot open input# $enderror$acceptdefine yyerrok yyerrf = 0 define yyclearin yychar = -1 subroutine yyactr(yyprdn) common/yycomn/yylval,yyval,yypv,yyvalv(150) common/yylcom/yychar,yyerrf,yydebu integer yy conflict (red'ns %d and %d ) on %s %d: shift/reduce conflict (shift %d, red'n %d) on %syypactyyr1yyr2off = %d, k = %d action table overflow %d no space in action tableyygoyypgo%s: gotos on %s nonterminal %s %d %d state %d, pre-nonterminal %s states %d and %d have equal positions state %d %s same as %d %s accepterrorshift %dreduce %d . reduce %d . error The function "system" is called0123456789ABCDEFCDEFLOSXcdeflosxLRLLLLLtL`LLRLLLLLtL`LL>"Jsystem"Jpexecl"P4error" settty"$cout$ settab"Tchcopy"writem"symnam"printf"K@arrset" arrval" arrdone" copy" @compare" yalloc" aryfil" 4setunion" vprlook" copen"Icin$defin"hgettok"chfind"defout"cpycode" cpyact"!finact"getchar"Kputchar"Mchstash"pindebugauto break case char 4 continue default do double 4 else extern 2 float 4 for goto if int 4 long register return static struct 3 switch while %P'xXP PA@,PA@xXp`Ї@XdX-B0&XdPAP8X8QdX`[8P`A$PX&PZ4XC &X@$$X@#TX0@$$/Z@#XP# X@,*PX[ PX PA@,$P@PA@,C$P@$%P@,X@Q@,$P@$P@,D#юp<p@Ї XHXY@FDC0TXHXP@FDXHXP@FHXHXP@FXXHXP@FPXHX P@FTXHXP@FLX@ZD$X@PXDP$PX'PC0XX.&P"PCX!6$PC0XC []@FH# X]@FHPX!4$QXZ@FDXZ@FXPU@FXC nXD&P X@P%Q C0(X main",exit"J_exit""tbitset$fnolook#Qnstate#Q pstate$fapstate$ltystate$sstsize#Q$memsiz#Q(mem0$yPmem#Q,amem$actsiz#Q0memact#Q4nprod#Q8prdptr$pprdlim#QP$PA@$P$PA@C0P$PA@$PX@PA@8P@$CX@ & CX@$PA@ X@ X @ PX@@,*X0@$$/P@#H#юp(p\Ї<$P@,DX@,$@*X@,*X0@$$/[@#HX0@$$/P@#LX@#@B0X@$$X@#LC0X@$$X@#H'P8P4X8&P8X.4&!P.4C06X4AB X4Z!)X4 CX@#@B0p'x$P @,tPX@$$X@#LPPA`&xPX#3$#$X@,8#3$#$ C0@, X@,@*$CzX@#@B0LX@$P X C0:X 'P $X@#HPX@$$X@#HPAFB0C@, X0@$&P@$$/@#P$#юX8&P8#юp4p(Ї%Q(%Q,X(&P(X.,&!P.,B0X(!3$#C$#юp(p(ЇX@,h@,lB0$X@,h&P@,hP@,H$#юp(p(Ї@, C0%Q@,h$C*C&%Q@,$X@,hP@,H$P@$$#юp(p(ЇX@$C0D@, X@(B02%Q@,@, !3Al@, !5$Q@$CH$P@$X@,D@, X@$C0X@,$@*Al%Q@,h$#$#юp(p(ЇX@,hX@,HC0(X@,h&P@,hP@,H$P@$$C@#Utpeekc#Uxtstates$ntstates$dmstates$clset$lkst$nlset#U|lsetsz#Uwsets$cwset$wssize#Unumbval$rflag#Usflag#Uoflag#Undefout#Unerrors#Ufatfl#Umachine$whereami"setup" cpres"$cempty"-0cpfir"&stagen".output"7go2out">summary"windup"cflush"JLcexit"Jcclosemake world still own see men work long get here between both life being under never day same another know while last might us great old year off come since against go came right used take three !'-"(.#)/06<B17PA@8P@$X@#@B0D@,P@,@4P@,P@,tP@,x$P@,|$P@,$PX@PA@P #@!PA@A't$PPX PA@&tB0XB0'tXPX@,PX PA@&tY#@@PA@A'tXPX@,PX PA@&tY#@_PA@A^X PA@ # X PA@ A#юp<p(ЇX(P@}PA@A юp(p(ЇX@$C *X@F@B0 X@PA@,X@PA@,A@xюp(p4ЇA@PB0$/#X"@#HX^$OZ%@#LCX@$'PX@$'P@$C0X@$$X@#LP!$PXPX@$$X@#HPA@,X@#@C0$P@PA@,C$P@PA@,X@#DB0VX@, P@,$PA@,'t@,P$PX@,PA&t$P@,PA@,C8't@,P$PX@$PA&t$P@,PA@,X@$B0$P@PA@,X@$BX@$$X@#'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@l&t 0    @9DPA@(0C$P8X8C6$PX8PA@"X8&P8X@2tPA@(0CX@p#4A@#@*P(@+P@+P @+P$P$PX8PX4PA@(tX4P@,;PA@#$PA@#C"XB0@,JPA@#$Ct PA@)`Y#2" X PC0@XC00X4P@,UPA@#XP@,hPA@#AX #юp4p4Ї$PX4XPX&PC0XCXP@,pPA@#A,$P@,C$P@,C$P@,C$P@2\C@,P@)X !7@,P@)$P@2\Cd@,P@)X !7@,P@)CBX B0($P $P@9@X&PZ4XP@)C$P@, !$%C& & P P X&PX(#юp(X!$P@#<%XP@"XP@""!P@#<%XP@"XP@#"!P@#<%#!P@#<%$XP@#XP@# #!P@#<%XP@#XP@#X#!P@#<%XP@# XP@#$#P@#<%XP@#,#(!$P@#<%!X'PP@#<%XP@#4XP@#8X#0!P@#<%  JN +6D N . . . .     @9 B,'t@9,PX@9P@+>PA@#&tA<@9C0,'tX@9P@9P@+TPA@#&tAX@9lC0X@9lX@9LAB08X@9H@9 X@2P#9XX@)ACCX@pY@p#9X@pP@pCю p,p<Ї@hP@p@lP@p@QZ#$CPX@2`P X C02X 'P $X@0PXXPAB0C$Q@2`$#юp8p0ЇX@9H!3AX@2`PX'PC04X$@0X>$X@9l&P@9lP@9L@9X@9l@9p$C2@9\B0@9X@9l@9p$C CX@9l'@9p@9\B02NX@9l&P@9lP@9L@9X@9l@9p$C$C@9 !3A@9\B02X@9l&P@9lP@9L@9X@9l@9p$Cb@9>#4$CPC@@9 #4$C:@9 !3AC@- P@-<&Y 3X%Q@9l$#юp(p(ЇX@9H!3AX@9l@9pC@9*B0X@9 @8/#4$C@9X@9l&P@9l@9pX@9lP@9L$C@9 !3AX'tP & PX PA@(&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & Pemp file %d 0123456789ABCDEFCDEFLOSXcdeflosx$%@%%%L% $%$$%@%%%L% $%$$,PX,&P,X.0&!P.0#3CX,[#ю p,p(Ї%Q(%Q,X(&P(X.,&!P.,B0X(!3$#C$#юp(p(Ї%Q@ C0X@&P@C'tP@PX(PA@ &tP@ C00X@ B4@P@X@&P@C*$P@ $C$P@ @ PA@$#юp(p0Ї%Q4X0X@Z8P BxX8[ P8X0X@ X.0"Z@'P%Q8B X4&P4X.&!P.CX0P@X0PAnX P8CDEFLOSXcdeflosxT`  8T`  8A#5CCXHX@ PX8PADX@&P@PX8PA&Q@X@'P@$XHPDXD&PDYpCXDX@ $CCrCC& B vBpX@ 0$QHC*XlPANX@&P@ C0X@C0fC$Q@ , C0&'t$P@ P$PA&t$Q@ ,'tX@&P@PP$PA&tCx$#юLplp,Ї %Q0X,'P,PX,&P,X.0&!P.0#3CX,[#ю p,p(Ї%Q(%Q,X(&P(X.,&!P.,B0X(Q CNX C06'tX & P & PX PA@ &t !$%C& & P P X&PX(#юp(X!$P@|%XP@\XP@`X!P@|%XP@hXP@lXd!P@|%XP@tXP@xXp!P@|%d8VtFvRUsage: crpost [-d] file1 file2 ... -d: 0 < d < 10 read error 0123456789ABCDEFCDEFLOS.nr DO \n(.o .nr tm 0 .de RT\" RT - reset everything to normal state .if !\\n(1T .BG .if !\\n(IK .di .ce 0 .ul 0 .if \\n(IP .in -\\n(IQu .if !\\n(IP .nr IQ 5m .if \\n(IP .nr IP -1m .ft R .ta 6 11 16 21 26 31 36 41 46 61 56 61 66 71 76 81 .ps \\n(PS .vs \\n(VSp .fi .. .de IZ\" IZ - initialization .br .nr y 0-6 .nr x 0 1 .nr IP 0 .nr IQ 5m .nr PS 10 .nr VS 12 .ps \\n(PS .vs \\n(VSp .nr TB 0 .nr LL \n(.lu .ll \\n(LLu .nr LT \\n(.l .lt \\n(LTu .tc ~ .tr ~ .ds CH "- % - .ds Ch \\*(CH .ds CF "\\*(DY .wh 0 NP .wh l Laboratories and is not for publication. (See GEI 13.9-3)\p .ft R .nf .sp .ll 30 .ps 9 .ta 10 40 47 .mk Title- \fB\s10 .rt .in 10 .WT .rt .ll \\n(LLu .in 40 \s9\fRDate-\s10\fB .rt .in 47 \\*(DY .sp .ti 40 .mk \s9\fRTM-\fB\s10 .br .rt .CT \\*(MN .rt .in 0 .sp .mk \s9\fROther Keywords-\fB .rt .in 20 .OD .rm OK .rm OD .in 0 .sp 3 .ps 9 .ta 20 35 45 .ft R Author Location Extension Charging Case- \s10\fB\\*(CA .ps 10 .nf .mk .A1 .rt \\*(R1 \\*(E1 \fR\s9Filing Case- \s10\fB\\*(CC .if \\n(NA-1 .CB 2 .if \\n(NA-ce 0 .nf .WB .fi .ad .. .de SG\" SG - signature .nf .in +(2u*\\n(.lu/3u) .sp 2 .A1 .if \\n(NA-1 .sp 2 .A2 .if \\n(NA-2 .sp 2 .A3 .if \\n(NA-3 .sp 2 .A4 .if \\n(NA-4 .sp 2 .A5 .in \\$1 .br .. .de Ta\" Tables. TS - table start, TE - table end .br .RT .ul 0 .sp .nf .. .de TE .fi .sp 1 .. .de DS\" DS - display. If .DS C, center; L, left-adjust; I, indent. .KS .\\$1D .. .de CD .ce 1000 .nf .nr oi \\n(.i .sp 1 .. .de D .ID .. .de ID .nf .nr oi \\n(.i .sp 1 .in +8 .. .de LD .nf .nr oi \\n(.i .sp 1 .. .de DE\" DE -lragmsbhn!3$#C$#юp(p(Ї%Q@ `C0X@&P@C'tP@PX(PA@ &tP@ `C00X@ `B4@P@X@&P@C*$P@ `$C$P@ `@ PA@t$#юp(p0Ї%Q4X0X@Z8P BxX8[ P8X0X@ hX.0"Z@'P%Q8B X4&P4X.&!P.CX0P@X0PAnX P8X0X@ hX.0"Z@'PX8X0Q@%Q8B X4&P4X.&!P.C$#юp0p(ЇX(XXcdeflosx 2 2 2 2 r-6 FO .wh -3 BT .nr EP \n(.pu-6v .. .de TM .pi /usr/bin/col .nr ST 1 .ds MN \\$1 .nr MM \\n(.$ .nr tm 1 .if \\n(.$-1 .ds CA \\$2 .if \\n(.$-2 .ds CC \\$3 .rm RP .rm S0 .rm S2 .rm AX .. .de RP .nr ST 2 .rm SG .rm CS .rm TM .. .de TL\" TL - title and initialization .nr TV 1 .di WT .na .fi .ll 50 .if \\n(tm .ll 30 .ft B .if !\\n(tm .ps 12 .. .de TX .rs .sp 3 .ce 1000 .ul 1000 .ps 12 .ft B .vs 15p .ne 4 .WT .. .de AU\" AU - author(s) .nr AV 1 .ad .br .di .br .nf .nr NA +1 .ds R\\n(NA \\$1 .ds E\\n(NA \\$2 .di A2 .CB 3 .if \\n(NA-3 .CB 4 .if \\n(NA-4 .CB 5 .ft R .sp 2 .WB .br .sp 5 .FF .rm FF .nr x 50-\\n(nl .sp \\nx .nf .ta 15 30 45 Pages Text \\$1 Other \\$2 Total \\$3 .sp No. Figures \\$4 No. Tables \\$5 No. Refs. \\$6 .ps 7 .sp .tl 'E-1932-C (6-73)'SEE REVERSE SIDE FOR DISTRIBUTION LIST'' .ll \\n(LLu .fi .ps 10 .bp 1 .. .de CB\" CB - help with cover sheet .br .mk .A\\$1 .rt .if \\$1-1 .if !\\$1-2 \& \\*(R2 \\*(E2 .if \\$1-2 .if !\\$1-3 \& \\*(R3 \\*(E3 .if \\$1-3 .if !\\$1-4 \& \\*(R4 \\*(E4 .if \\$1 display end .ce 0 .in \\n(oiu .KE .sp 1 .fi .. .de KS\" KS keep - for keep release features. As in IBM .if !\\n(IK .KQ .nr IK +1 .. .de KQ\" KQ - real keep processor .br .di KK .nr TB 0 .. .de KF\" KF - floating keep .if !\\n(IK .FQ .nr IK +1 .. .de FQ\" FQ real floating keep processor .br .di KK .nr TB 1 .. .de KE\" KE release - everything between keep and release is together .if \\n(IK .if !\\n(IK-1 .RQ .if \\n(IK .nr IK -1 .. .de RQ\" RQ real release .br .di .if \\n(dn+\\n(nl-\\n(EP .if !\\n(TB .sp 200  X'xXP PA@,PA@lXp8ЇX8#@ lPA@tA@lX -> .ds | ,c`o-""o|o~t~~vo/x/-‚''uu|-Â`/--\O=/\[][]->--Yo[][]-‚'`O¡-->_<_=_-=~=/-><-|^=x/+_Uooo```\--/-,|'`'`+rOcO|c/**|O|||||||||||WTEPRYFHZ>_<_=_-=~9~8=/-><-|^=x/+_Uoo][_^+8r98c9|c/**|O|||||||||||sp .ti +5 .. .de SH\" SH - (unnumbered) section heading .RT .if \\n(1T .sp 1 .if !\\n(1T .BG .RT .ne 7 .ft B .ul 1000 .. .de NH\" NH - numbered heading .RT .if \\n(1T .sp 1 .if !\\n(1T .BG .RT .ne 7 .ft B .ul 1000 .nr a \\$1 .if !\\n(.$ .nr a 1 .if !\\na .nr a 1 .nr H\\na +1 .if !\\na-4 .nr H5 0 .if !\\na-3 .nr H4 0 .if !\\na-2 .nr H3 0 .if !\\na-1 .nr H2 0 .if !\\$1 .if \\n(.$ .nr H1 1 .ds SN \\n(H1. .if \\na-1 .as SN \\n(H2. .if \\na-2 .as SN \\n(H3. .if \\na-3 .as SN \\n(H4. .if \\na-4 .as SN \\n(H5. \\*mo-7 .ds mo August .if \n(mo-8 .ds mo September .if \n(mo-9 .ds mo October .if \n(mo-10 .ds mo November .if \n(mo-11 .ds mo December .if \n(dw-0 .ds dw Sunday .if \n(dw-1 .ds dw Monday .if \n(dw-2 .ds dw Tuesday .if \n(dw-3 .ds dw Wednesday .if \n(dw-4 .ds dw Thursday .if \n(dw-5 .ds dw Friday .if \n(dw-6 .ds dw Saturday .ds DY \*(mo \n(dy, 19\n(yr .IZ .rm IZ .rm mo .de FN .FS .. .de FS\" FS - begin footnote 'ce 0 .di .da FF .ev 1 .if !\\n+x-1 .fs .. .de FE\" FE - footnote end .br .in 0 .ev .di .nr y -\\n(d\\n(.n\" .sp 1 .in \\n(.iu-\\n(xiu .fi .. .de PA\" paragraph .br .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ne 6 .. .de NS\"new section. $1=inc indent $2=section no if given .br .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ne 6 .nr n \\n+n .nr s\\nn \\$1 .in +\\n(s\\nn .nr zi \\n(i\\nl .nr i\\nl \\n(zi+\\n(s\\nn \\$2 'cu 1 .. .de ES\" end section and pop back things .br .if \\nw .sp 1 .nr w 0 .if \\n(.n\" .sp 1 .nr zi \\n(i\\nl .nr i\\nl \\n(zi-\\n(s\\nn .in -\\n(s\\nn .nr n \\n-n .. .de UL\" lynnies choice .t( "%(+.147:=@CFILORUX[^adgjmpsvy|  !$'*-(  "%(+.147:=@CFILORUX[^adgjmpsvy|  ...37carcar_old(SN .. .de BG\" BG - begin, execute at first PP .br .di .ce 0 .nr 1T 1 .S\\n(ST .rm S0 .rm S1 .rm S2 .rm OK .rm OD .rm TX .rm AX .rm WT .rm I1 .rm I2 .rm I3 .rm I4 .rm I5 .rm CB .rm E1 .rm R1 .rm R2 .rm E2 .de TL .ft B .sp .ul 100 .ce 100 .LG \\.. .de AU .ft I .ul 0 .ce 100 .sp .NL \\.. .de AI .ft R .ce 100 .ul 0 .sp .NL \\.. .ds Ch \\*(CH .sp 2 .fi .ll \\n(LLu .. .de IP\" IP - indented paragraph .RT .if !\\n(IP .nr IP +1m .sp .ne 3 .if \\n(.$-1 .nr IQ \\$2m .LB "\\$1" .. .de LP\" LP - left aligned (block) n .ch FO \\nyu .if \\n(nl-\\n(.p-\\ny .ch FO \\n(nlu+1 .. .de fs\" SEPARATOR __________________________________________________________ .br .. .de fz .FS .nf .fy .fi .FE .. .de fx .di fy .. .de xf .ev 1 .nf .FF .rm FF .di .fi .ev .. .de FL .ev 1 .ll \\$1 .ev .. .ch FO 100 .wh -6 fx .ch FO -6 .ev 1 .ll \n(LLu .ll -(\n(.lu/12u) 'ps8 'vs10p .ev .br .em EM ul 1 .. .de FO\" foot title macro .de x1 'sp 2 'ie '\\$2'date' 'tl '\\$1'- % -'\\n(dy/\\n(mo/\\n(yr' 'el 'tl '\\$1'- % -'\\$2' 'bp \\.. .wh -5 x1 .. .de HE\" header title macro .de x2 'sp 2 'tl '\\$1'\\$2'\\$3' 'sp 2 \\.. .wh 0 x2 .. .de AR\" make page nos arabic - no leading zeros .nr % 1 .af % 1 .. .de BR\" make page nos big roman eg I, IV, XLM .nr % 1 .af % I .. .de LR\" make page nos little roman eg i, iv, xlm .nr % 1 .af % i .. 059<?BEHKOSW\adgjmpsvy|*1<GLSVbknqx #&).36;>ADGJMPSVY\_behkn!$',169=AEJORUX[^adgjmrw| $),18=AEJMPSV[^adgjmqv{....nsuftabtermtmac.mtmac.ntmac.satabctabetabaigncigneignzemhelpmunitsquiz*bookparagraph .RT .sp .ne 3 .if \\n(.$ .LB \\$1 .. .de IE\" IE - synonym for .LP .LP .. .de LB\" LB - label paragraph .in +\\n(IQu .ta \\n(IQu+1m .ti -\\n(IQu \\$1\t\c .. .de RS\" RS - prepare for double indenting .in +\\n(IQu .nr IP +1m .. .de RE\" RE - retreat to the left .br .in -\\n(IQu .. .de CM\" CM - cut mark .po 0 .tl '-''' .po .. .de B\" B - bold font .ft B .ul 1000 .. .de R\" R - Roman font .ft R .ul 0 .. .de I\" I - italic font .ft I .ul 1000 .. .de TA\" TA - tabs set in ens or chars .ta \\$1n \\$2n .nh .pl 66 .ll 64 .lt \n(.lu .nr xi 0\" in-out value .nr n 0 1\" level of section .nr l 0 1\" level of indent .nr s\nn 0\" level zero inc indent for section .nr i\nl 0\" level zero indent .nr o\nl 0\" level zero outdent .nr w 0\" .sp indicator for levels .de BP\" $1 - .in +$1, $2 - .ti -$2 .br .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ne 6 .nr zi \\n(i\\nl .nr l \\n+l .nr t\\nl \\$2 .nr i\\nl \\n(zi+\\$1 .nr o\\nl \\n(zi+\\$1-\\$2 .ta \\n(t\\nl .in \\n(i\\nl .ti \\n(o\\nl .. .de NP\" reset indent, tab, and.pl 66 .nr in 5 .de i0 .in \n(in .. .de lp .i0 .ta \\$2 .in \\$1 .ti -\\$2 .. .de s1 .sp 1 .ne 4 .. .de s2 .sp 1 .. .de s3 .sp 1 .. .de fo 'sp 2 'tl ''- % -'' 'bp .. .de th .de x1 'sp 2 'tl '\\$1(\\$2)'\\$3'\\$1(\\$2)' 'sp 2 \\.. .wh -5 fo .wh 0 x1 .in \n(in .. .de sh .s1 .ne 5 .ti 0 \\$1 .br .. .de bd .tr __ .ul \\$1 .. .de bn .tr __ .ul \\$1\\t .. .de it .tr __ .ul .li \\$1 .. .de dt .ta 8 16 24 32 40 48 56 64 .. .de un .mc | .. .de uf .mc .. .ds b B .ds G G .ds a ' .ds - - .ds _ _ .ds v | .ds p J DDdD7 PpaAQ PQP !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~-o+[]-_-fiflffffiffl''`_/ c(B|)/o<<-c,<n|O-ik\ġ''u,(/c 897 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~-o+[]-_1/41/23/4-fiflffffiffl''`_/ AB\DSQNOikLM@XoJKYIvUxVCGtD8 'xXP PA@,PA@eXp(ЇbP$ PA@s'xX,PX(PA&xPA@cюp(p(ЇX(C %Q($Q,X,XP@DPA@Mp#8@HX,PrPX,XP@4PA@dP@D$P@0X@DC*'tX@4P@XP$PA@e&t$CjPA@C@C04PA@f(P@rPA@M#4A@CX@DPA@cX(##C$#юp(p(Ї$P$ PA@s$PA@cюp(p(ЇA@DdyPA@eX@FlZ,cP@H$Q,X(^B0X@Fl!)@PA@BX,!@PA@B$P$CNQ(X,C0>X@FlZ,+ P X(I!42#3X X $CX,C X@FlZ,$P@!CX,C0X@FlZ,+ P $P X X $PXCA@DP(XB0X((!:)P A@DP(X(C0X(Y !6$P CxX B0X( C0dX(Y@C0VX( B0X@DPX(PA@CC.X(X ZX(0!X(9#&$QC2$P X Y@QC`X@ X@QX@,X. # PX@QX@,X. # $P$P@PX@ PA@MpC0'|X@QX@CDZ /PX@QX@CDZ + P X PX@QPX@ PA@Ex&|X@QX@,X. # PCX@ PC0XY@#7$Q@ CX@ &P@ $X PX@QPA@OCX@QX@,X. # XPA@KX@QX@,X. # PCvX@QX@,X. # XX @Q"X"@,X> 3 #P@X@QX@,X. # PCC@,X.# XPPA@>XC0&P@UPA@e'tXX@CDZ/PXX@CDZ+ PXPAR&t@]PA@e'|&PP &PP@_PA@e&|XX@,X.# XPPA@>XC0l'|X@PXP X@P&P@}PA@e&|'|&P P &P P@PA@e&|CXX@,X.# XPPA@>XC0&P@PA@e'tXX@CDZ/PXX@CDZ+ PXPe$QC@XPA@e't&P&P@ZPA@e&tX@!9X@ !5X@#6$QCXX@Q[@FlP'xXP &P&P@nPA@e&x't&P&P@PA@e&tC&P@PA@eOP@PA@eX@B0X@!9X@ !5X@(#3$#$P$PXY@QC'|&PXP XOPX(P@PA@e&|'tX(PXPP@PA@e&tX\XC0,'tX(PXP@$P@ $Q@QCX@ P@(AX@$#4A@H&#юp0p,Ї $PXY@QCFXPX,PA@O#$C,Ca!)!X@$QC$#ю p,p0Ї$PX0PA@OP $PXY@QC.XPX@QPA@OY #4A&t@PA@e'|&PXPP &PXPP@PA@e&|C@P@&Y 3X$QCX XC0<'| PXPP XPP P@PA@e&|X\XC0'tPX'xX@QNP X@Q'PX@QOP@PA@e&xX@QOP@PA@eX@!:X@!6X@ C0.'t&PX@QX@FlP@PA@e&t'tX@4PX@0'P@PA@e&t#юpp(ЇX(PA@BC0X@P@oPA@eX,#(X,PA@8X0#8X0PA@9.X(P@tPA@eX,#)@wPA@8X0#9@yPA@9.X@P@{PA@eCX(P@~PA@eюp(p0ЇX@!9X@!5X@ #3A$P #$P X@QPX@Q'P$PA@] &x@ UPA@e@ WPA@e@ [PA@eюp8pLЇ,$PP@Q XL!5$P@Q$XLB0@X@!:X@!6X@ C0&X@ #6=P#-P$PA@TXPX@IB0~XPX@FB0n$P(X(Y@QCZXPX@,X.(# XPXC0,XPA@BB0XP@ PA@e$Q(CXPX@MC0$XPX@M`P@ PA@eXPPA@\P$$P(X(Y@QCXPX@IB0/Z> 2P@9X>/Z> 1@+ XZ $P@!XZ lP@L$QCr$Q C*$P@QP@Fl$P@,P@(A юp0pPЇ0$P,P$A@DP(C0vX(CNX(Y@#9@PA@BCX$$X X>,$/0Br  #)@>PA@BX !8X(PA@CC|X,BpX,$P@$P@CVX(P A@DP(X &P PA@N#3CX@DPX(PA@CPA@NhPX,X@FlPA@OX,P@FlCX@FlZ,$Q@9X,!5$P@(CC' rB BX@Cz@TPA@Bю0pPp0ЇA@>P@$P@ $P@$$P@FhP@QX@ PA@C@C0dX@FhX@QP@CDX@ P@PA@M#7$P@ C&X@ P@PA$C$QCX #юp0p<Ї$PXY@QC$PXY@QCjXPXPAjC0FXPA@\PXX@,X.# XP XX@,X.# XPXY@QC"XPXPA#6$QCX X'PX@,X.# PXXX@,X.# PXPXPA@OX>2X3@CD/Z>2P@LXYCNXX@,X.# $P@XX@,X.# PXPA@\xPC$QC$QCjюp<p(ЇX(X@I#4$CxX,PX(PA&PXPP &PXPP@lPA@e&|$PXY@QCXPXPA@PPC0&P@PA@e'tXX@CDX.[. /PXX@CDX.[. + PXX@,X.[.# XPA&tXPXB*XP[P@PA@e%QC@PA@e'|XP&P &P&P@PA@e&|'t&P&P@PA@e&t$PXYB X[Z\XC00't&PX[ZPA@eXa#7XnB0(X0X@,X. # X#8X X@M#X X@MC0X P#4$PX$B,X$X@,X.(# XPA@P#4$P$Q(ChXC0 @ PA@e@ PA@e$P$P(X(Y@QCXPX@,X.(# XPXC0XPA@BB0XPPA@\P$X$BhX$X@,X.(# XPA@PC0@'|X(aPXP X(aPXP@ PA@e&|C$'tXPXP@ ]PA@e&t$Q(C XPX@IC0XPX@IPA@f(CXPX@FC0NXPX@FP CX PXPPA@TC@ \P@ h&Y 3X CX@C0X,PX@QPA@OP@QX@FlZ@QX@9#)$Q@Q$Q@,X$#5$Q@FlX@Fl!@PA@B$P,X@Q#5X@Fl!9@PA@BX(.B0lA@DP(#7X( #2" $P,X,Y@QC:X,X@FpC X,&Y@Q#$#$X,P@Fp$Q,CCD$P$C Q(X(_!5-P(X(X0@Fl/Z>,2P@LX(sB0X,!)@'PA@BX(sB0LX@FlZ,X@HaB0,@FPA@eX@FlZ,lP@HX(sB0LX@FlZ,X@HnB0,@@MB0X@ P@PA@M#8A@$Q@FhX@Q!$P@ CX@Q$P@FX@ .B0NX@ PA@NC04X@ X@QP@IX@ &P@ #2" CF# X@Q$P@IX@QPA\C0ZX@QPAP#:XX@QP@F$Q@Q$Q@Fh$X@QP@FX@QP@ICX@QPA@?TX@QP@,X@ B0ZX@ C0X@Q-P@FCpX@Q=P@FCZC@pP@|&Y 3X X@FhX@QP@CDX@Fl'PX@Fh&PA@P"P@Fh@O^!4$CVX(X@,X.,# X#4$C6X(X@F#4$C"X(X@,X.,# XPA #юp(p(ЇX(!4$C2X(PA@B!4$C@PX(PA@Mp#юp(pЇ$PXY@QCh$X PX\PXPP@8PA@e$PXY@QCLXX@IB02XX@FB0"XPXPA@PLB0XPXPA@OCX $PXX@,X.# XC0X\XB0$'t PP@BPA@e&tX\$PXX&PX[ZPP@PA@e&t$QCp$QC$QCX@C0*&P@PA@e$PXY@QCVXX@C0<'|XPP&P &PXPP@PA@e&|$QC$PXY@QCXX@C0zX\XC0@'|&PXPP XXC0 X@Q$C -PXLPA@T$P@Q$XLPA@$XLPA@Q#9@ PA@e@ PA@e$P(X(Y@QC8X@,#9X(&Y@QC0XL&Y@QCd'tPX(PXLPA@Z&tP$B8X(PA@Q'xXP X(PXLPX$PA@] &xX(PXLPA@OPsC0NXn#7XaB0X(X@MP!8X(X(C00X(PX(#7@ BP#@ JPA@eюp(p(ЇX(C0&X(C0X(P@ QPA@eюp(p0ЇX@$P@ PA@C@C0X@ P@ PA@MB0X@ .B0,X@ PA@N!9@ PA@BX@QxPX,Q@QxX#ю p,p(Ї$P@ %P@ $P@Qюp(p8Ї$PXCX$P$QC$P@P@$PXY@QC:XX@IB0 XX@FB0$PXY@QCXPXPA@OP X C0X -C0X =C0XX@,X.# XPXPApC0.XC0 X&P$PCXX@,X.# XPXPAC0.XC0 X&P$PC$QC$QC@ C0 PX(PA@O~#X($X@8&P@8#юp(p(Ї@PA@e&P@PA@eюp(p0ЇX4Y@QB6X@ C0&X0!4$CX@Q'Y0!$$C$C$CX0C X4PX0'PA@[p#$P X0&Y@Q!$PCs#3$#$#юp(p,Ї X0PX,PAs#4$Cj$Q0X0Y@QC X0PX,PAs!4$C6$PX0'P0PX,PAs!6$QCX#ю p,p,Ї $Q0$PX0Y@QC,X0PX,PAPsB0$Q0$QCX#ю p,p(ЇX(!;@PA@eC,'tX(OPX((P@ PA@C0XP@PA@eXC XL&PXDPA@HdCNX!5@#@P CJX!5@#@P C*@P CC'!)!X@TC`XB0TXL&PXDPA@HdC @P C*@P CC'!)!X@`XL&Y@QBX P@PA@eC4'xX P XL)PXLPP@PA@e&x$QCX C0 [ P@PA@eX!9@PA@eю$pDp<Ї$P$PXCX$P@M$QC$PXYC0X@P@ PA@eXPA@P#6$PC0'|X(PXPP X PXPXPAX&|XC0X@P@ PA@eX@P@ PA@e$Q(C@ PA@eXLPA@Q#9@ PA@eX@Q C0XPPXLPAXC0$P(X(Y@QCXPX@,X.(# XPA@PC0dXPC0@XPPA@\P$B(X$X@,X.(# XPA@PB0X(aP@ PA@e$Q(C\ю,pLp0ЇX0PA@BC0X4PAX8PARX<#;X@ PA@f(C$P@FP@IX@ B0zX@ CP-P@F$PX@Q'PA@*LC0=P@F$PX@Q'PA@*LC C@ TP@ `&Y 3X $P X Y@QCbX@ X Z@,PX Z@,$PX@ PC0XY@#7$Q@ CX@ &P@ $X PX@Q'PA@OClX Z@,XPA@KX Z@,PCXX Z@,XX. #Z @,P@ X Z@,PCC@ lP@ x&Y 3X X &PX@Q'PA@OsB0 @ X &PXC0BXXB0"XP@X@$P#$QC@+PXC0.XX!9XP@#$QCX@#5X@!9@rPA@B#юp8p(ЇX(#X(!$#$#юp(p(Ї'|X(PX@0P X@4P@P$PA@e&|@P$PA@e$PA@cюp(p,Ї $Q@0X,PA@d|PX,#5$Q," %Q,X,\!7X,PAX#ю p,p(ЇX( !5%Q@0X(X@&P@XQ!$CNX4C X4'PX0PA@Rr#$P X B \X0C T'tX0PA&tPA@QC04X4C &X4'P'tX0PA&tPA@Rr#$P X4PX0PA@RrPXB ZX0C R'tX0PA&tPA@QC02X4C $X4P'tX0PA\&tPA@Rr#$PX =B0X=!4$C"X =!4$CX=!3$#$#юp0p(Ї%Q(X(X@IC0X(#%%Q("X(#юp(p<ЇXXPX4PA:PX!4$C X#4$P $QCX #юp4p0ЇX4#$C6X0#$C*X4PX0PAP X _#6X -!5-CX =!5=CX ^!4$CX0X@F#:X0X@FCX sB0X4'PX0PAFCX !4$CX0X@,X.4# XPXC0 XPA@BC0X!4$C8XPA@P#4$C XPA@c:P #4X #$#юp0p0ЇX4PX0P@QCz$PXY@QC\'t PXPXPAr&tPXB&XX@MB0X&PXP@M$QC$QCxX@!9X@!5X@ #5$P@Mюp<p0ЇX8$PX4PX0PAP X !4%CX0&Y@QC,X4P'tX0PA&tPA|Y !4%CfX0B4X4PX0PATY B0X0PPAP0CXPA!4$PX X8PX#юp0p,Ї X,Y@Q!X@Q'P,X0PX,PA@OsB0NX0PXPX,PA@Os!6%QCXPA@\P X<X@CDP!X@ X#3$#$PX BxX X@,X.@# XPA@PC0PX@aP@ PA@eXC0X@aP@ PA@e@ PA@eX0P@ PA@eX BxX X@,X.@# XPA@PC0PX@aP@ PA@eXC0X@aP@ %PA@e@ PAX8#8@ @PA#$P@Q юp0p4Ї@ BPA@eP@ JPA@e$PXY@QCX8X@,X.# XP X P Z@,PCX#6$Q CX &P Y@QC@ X Z@,PC$PX@Q'PA@*LC,X@ P@(#юp0p8Ї$PXY@QC$XP@MXP@MPXP@M$PXY@QCXX@IB0jXX@FB0ZXPXPA@OP X -C04X =C0(X n#7X aB0XX@,X.# XPAPXX@MPVP@MPXX@,X.# XPAPXX@MVP@MXX@,X.# XPAB0:XX@,X.# XPA@T8!@PAюp(p,Ї X@RDC X@'P@P#A@dPX !5$Q@0X#ю p,p(Ї#P@PA@e@PA@eюp(p(Ї#P@PA@eюp(p,Ї $PXC6XX@MC0XaP@PA@e$QCX@(P@PA@eю p,p(Ї@ PA@e@PA@eюp(p(ЇX@8z#)@8PA@B@WPA@eX@8P@\PA@eX@$B0 &P@eXB0$PX<C0`X<.B0DXP@QX@QP@QX@QP X<&P<X @Q&P@Q#3CX$X #юp<p(ЇX(X.,B0$X(&P(!4$C$Q,C$#юp(p,Ї X,&P,PX.A@RrPXC0X4C X4'PX0PA@RrYC0X4P X Y@QCDX PX0PA@OsC0X PX0PA@RrY!6$Q C'|$PX8P X 'PX4PX0PA&|юp0p0Ї@lPA@e$P X Y@QCX PX0C &XPX0'PA@#6$QCXP X Y@QC.X0C X PX0'PA@!6$Q CXY@QC.'|$PX4P X PXPX0PA &|C8@tPA@eюp0pDЇ$$P@zPP XPC$PCPX,PA@Rr!4$CpX,X@CDP,X,Z0X@9P,X,#%X,C8X@ #7X0!4$C$X@#4$CX@#6X0!3$#$#ю p,p(ЇX(&Y@QC&$Q(X(X@F!8X(X@I#3CX(#юp(p(Ї%Q(B X(X@F!8X(X@I#3CX(#юp(pHЇ($PPP P$P $QLXLX@I#5$QL" $PXYTCX[T&PXY C0X[ P@PA@eXP XLY@QCXLX@FB0"XLX@IB0 XLPA@Q#8@PA@BB0X C0@ XPA@e%P@ hPA@eXPX4PA@OC'xX P XPX8PA@Q4ZOPX(P@ pPA@e&xCjX(P@ PA@eCJ'tX PXPP@ PA@e&tCC@ P@ &Y 3X%P@ PA@eX4X@CDZ+ PXPAX4C 'tX4PA@\&tX@,X.# XPA@PC0XaP@ PA@eX4X@CDP!X XB0T'xX P XaP&P@vPXX@MVP@MC:XX@,X.# XPA8PXX@MVP@M$QCn$QC*юp8p(ЇX(!4$C,X(PA@B!4$CX(!3$#$#юp(p,Ї X@ X@Q(C0X@ &P@ X@Q(ClX@ !@ PA@B$PPA@eTPX@ &P@ P@Q(X!9@ PA@BX#ю p,p,Ї X@ B"X@QxZ,X@ X@Q|C l$Q@ X@ X@Q|B0"$PPA@eTX@ P@Q|X@ X@Q|P@QxX@QxPA@e$P@$A@DX4C0&X4C0X4P@tPA@eX8C0&X8C0X8P@|PA@eX0$@B|C0&X0$B|P@PA@eCB'xX@Q&P X0PX,PA@Q4P&P@PA@e&xPA@C@C0^TB0 }!8 Y@C0:P@PA@MpB0P@PA@eCX4C0X4#9@PA@eX8C0X8#9@PA@e@PA@e@PA@eX@8P@PA@eX@8P@PA@e0&P0B0X!4$CCX#3$#$#ю p,p(ЇX(aBX(z!$$CX(ABX(Z!#$#$#юp(p,Ї $PX,0B6X,9B $X$X.," P$Q,CX#ю p,p(ЇX(0!X(9##$#$#юp(p(ЇX(Y,#$X(#X,#юp(p,Ї $PX,ZC0$X,ZY0!5XC$QC%#ю p,p(ЇX,&P,X.(&P(#3Cюp(p(ЇX(X@I#4$C>X(($PCC@ P@,&Y 3X XC ~XL[HY@QCXTB0XDPA@Q!3$#$PX!9@{PA@e$P PXYCX[&PXY C0X[ P@PA@eXP XHPA@QXC XHPXDPA@HdCNX!5@#@PCJX!5@#@PC*@PCC'!)!X@<XC0XP@PA@eCXB0xXHPXDPA@HdC @PC*@PCC'!)!X@HXP$CRXPPXLPAVC @P$C,@P$CC@P@&Y 3X XTC XPPXLPA@IvCN@P CXX!5@#@P C=\(\n(\*(#du-\n(^%cu-((\n(#-u-\n(^%cu)/2u)'%s\v'(\n(\*(#du-\n(^%cu-((\n(#-u-\n(^%cu)/2u)'P0.mk ## .nr %d \n(## .sp |\n(##u-1v .nr %d (\n(%du+\n(%du-\n(%c-u)/2u \n(%du \n(%du-\n(%c-u .in +\n(%du .sp |\n(^%cu .nr %d \n(#-u-\n(^%c-\n(%c|+1v .if \n(%d>0 .sp \n(%du/2u .%c+ .in -\n(%du P.mk %d .if \n(%d>\n(%d .nr %d \n(%d .sp |\n(%du \f(%.2s\f%.2s\s%s=_:J:$:an;X;*;.TEToo many characters in tableno space for charactersno space for vectorlY 0main",exit"e_exit""expflg#ctrflg#boxflg#dboxflg# tab#evenup$evenflg$F1#F2#allflg#leftover# textflg#$left1flg#(rightl#,cstore@!PA@eXC0XP@:PA@eXC0XP@>PA@e@BPA@e$QCю(pHp,Ї X0PX,PA>PXB0"X0C X0'PX,PAPX#ю p,p,Ї X0PX,PA@OPs!6%Q0CX-#6X=!5XC2X,X@,X.0# XPAP#4X#$#ю p,p(ЇX(!4$CRX(#4$C@X(C-C*=C"C@pP@|&Y 3X $#юp(p(ЇX(PA@mBюp(p(Ї@\n(%d .nr %d \n(%d .if \n(%d<\n(%d .nr %d +(\n(%d-\n(%d)/2 .nr %d %sn .if \n(%d<\n(%d .nr %d \n(%d .nr %d -\n(%d .if \n(%d>0 .nr %d \n(%d/%d .if \n(%d<0 .nr %d 0 .nr %d +\n(%d/2 .nr %d +\n(%d .nr %d 0 .if \n(%d>\n(%d .nr %d \n(%d .nr %d (100*\n(%d/\n(%d)*\n(%d/100 .nr %d \n(%d .nr %d 0+\n(%d .nr %d \n(.l-\n(%d .nr %d \n(%d/%d .if \n(%d<0 .nr %d 0 .nr %d 1n .nr %d 0 .nr %d \n(%d+(%d*\n(%d) .nr %d +\n(%d .nr %d +\n(%d s!%&#/?,:;<=>@`^~_{}+-*ABCDEFGHIJKMNOPQRSTUVWXYZabcdefgjkoqrstwxyz:_~^`@;,<=>#%&!/?{}+-*ABCDEFGHIJKMNOPQRSTUVWXZabcdefgjkoqrstuwxyzcouldn't find characters to use for delimitersRD %s: line %d: %s tbl quits too much backup.nr %d \n(.u .nf .if \n(%d>0 .fi .nr #%c 0 %s .ds #d .d .if \(ts\n(.z\(ts\(ts .ds #d nl Too many text block diversions.br .di %c+ .nr %d \n(.lu .ft %s .ps %s .vs \n(.s+2 .ll %sn .ll \n(%du*%du/%du T}%s .ft P .br .ps .vs .br .di .nr %c| \n(dn $ cspace$$last$(table$,style$Lctop$!font$+ csize$/lefline$9cll$B|stynum$CDnslin$Fhnclin$Flsep$Fpfullbot$Finstead$Iused$Mlused$MPrused$Mlinestop$Mnlin$Qncol$Qiline#0ifile#4texname#8exstore$Qexlim$Qbadsig"signal"stbl"vcexit"cmatch"MpcopenA@mBX(PA@eюp(p,Ї X0C.@hPC:@jPC,@lPCC@DP@T&Y 3XXPX,PA@m#ю p,p(ЇX(X@D%QBX @DX&P# X@DPA@jB" B0$ X(C#&C$#юp(p(ЇX@D%QBX @DX&P# X@DPA@j#юp(p(ЇX(\,P(X(PA@nC0X(&'!$P &" #юp(p(ЇX(PA@pVюp(p(ЇA@mX(P C@VP @VP ClPA@n P !9  CB  $C(X C 'tPP PA@s&tP X, &P C %#X,#ю p,p(ЇX( B0JXC0BX C 6PP 'tPP PA@s&t #7 юp(p(Ї,U@l#PA" юp(p(ЇX( C0.PA< PA@r #8X PA@pV$P  $P $#юp(p(ЇX,, C0U@l!$Cʰ <aInput-ms/usr/lib/tmac.scan't open input file %s .TS  expandcenterboxallboxdoubleboxframedoubleframetabIllegal option N N N N N N N N N N.nr %d (\n(%d+\n(%d)/2 .nr TW \n(%d .nr TW +%d*\n(%d .if t .if (\n(TW+\n(.o)>7.75i .tm Table at line %d file %s is too wide - \n(TW units \w%c%sP0%c\n(%c-%D&V%&V&V&V&V&V&V&V&V%&V%D&V&V&V%%.nr #I \n(.i .in +(\n(.lu-\n(TWu-\n(.iu)/2u .fc %c %c .nr #T 0 .fc .nr T. 1 .T# 1 .in \n(#Iu .ta \n(%du \n(%du \n(%du .ne %dv+%dp .eo .de T# .ds #d .d .if \(ts\n(.z\(ts\(ts .ds #d nl .mk ## .nr ## -1v .if \n(#T>0 .nr #%c \n(#T .if \n(T. .vs2p .i.nr %c- \n(dl .nf .ll \n(%du \h'|0'\h'(|\n(%du+|\n(%du)/2u'-=UUV VWW$WWWX$X@X`XXX.vs 2p .vs \v'-.5m'\v'%dp'1p-1p1p-1p-1p\h'%s'-1p1p\h'%s'-1p+1p-1p+1p-1p+1p-1p\l'|\n(TWu%s\(ul'\l'(|\n(%du+|\n(%du)/2u%s\(ul'\v'%dp'\v'+.5m'-=^^^:^^n^`^^^-=___`,`H````=_cxcpc\h'%dp'2p(1v-.5m)(1v-.5m+1p)-1p1p-1p1p-1p-1p1p0p.5m(.5m+1p)-2p2p1p1"dcin#Dprintf"egets1"C@puts"f(prefix"Mtableput"cclose"csavefill"Ddifdivert"EBgetcomm"4getspec"gettbl" Dgetstop"Ycheckuse"%Q@@BX@<&P@<C@0 .sp -1 .if \n(#%c>0 \h'|\n(TWu' .if \n(#a>0 .sp -1 .if \n(#a>0 \h'|\n(TWu' .. .ec -=----=aclnr00/00/01 aclnr66:66:66.ne \n(%c|u .mk #%c .nr #^ \n(\*(#du .nr #- \n(#^ .if (\n(%c|+\n(^%c-1v)>\n(#- .nr #- +(\n(%c|+\n(^%c-\n(#--1v) .if (\n(%c|+\n(#^-1v)>\n(#- .nr #- +(\n(%c|+\n(#^-\n(#--1v) .vs 2p \&\h'|\n(%du'%c%c%c%c%c%c%c .vs .nr ^%c \n(#^u \v'-p-1p1p-1p1p-1p\v'%s'\v'%s'\L'|\n(#%cu-1v-%s+%s-%s-%s'\v'\n(\*(#du-\n(#%cu+1v+%s-%s',arwd.dd dZrwa0123456789ABCDEFCDEFLOSXcdeflosxhfhiihhhthhfhiihhhthhRReading bad file writing TT">nodata"oneh"alocv"?Tmin"P"gettext"Exctype"Omaknew"Kpermute"untext"H&vspand"prev"\next"\xvspen"Ppoint"Bfspan"PLreal">Xwide""lspan"Pputfont"8putsize"9.need"&deftail"'^putline"*Lyetmore"9pruntabs"$ifline"&zdrawline"Uleft"Ztohcol"Qdrawvert"] watchout$Q once$Q$fullwide"Tallh"Qputtext"3makeline"Sfunnies"5zctspan"Q4spcount# spvecs$Q(calloc"eTthisvec$Qxtpcount# tpvecs$Q|gets"d|backup$RDbackp#getchar"dtcopy"O~interv"Hdlefdata"[pinterh"Ivthish"Rrup1"KBbarent"c:midbar"bRmidbcol"b_iob#,cout$T8fclose"mBfopen"m_filbuf"jmalloc"ncfree@X(X@B@&P@B@@BHA CX,Z@BD>B0$A>P-PA.$Q@BDCAiPmPA AClPsPACAACACX(X@B@&P@B@@BHX@BD&P@BDZ,P(X @B@&P@B@@BHX@BD&P@BDZ,X @B@&P@B@@BHX((B0.X@BD&P@BDZ,X @B@&P@B@"efree"pV_cleanup"m_doprnt"f_flsbuf"kD_prfwidt$T<_prfprec$T@_strout"q_prf1"h2prfhex#pftoa"i_error"pread"s write"sgtty"r_sobuf$Vfflush"l_lastbuf#lclose"rcreat"ropen"rseek"sPallocs$Tallocp$Talloct$Tsbrk"r`_sibuf$Tstrlen"pbrk"rTend$Yerrno$Z[[ P4XP$PA@*ZX@P@:X@8C0hpX@X@:PX@X@$# / P'tXPX@P@PA@O&tX@CC'x@P @P@PXPA&xCl'x@P @P@PXPA&xC:@PA@O$PXYC@ PA@O$QC@PA@O$PXYC@PA@O$QC@PA@OC'x@)P @$P@PXPA&xC|'x@8P @3P@.PXPA&xCJ'x@P @P@PXPA&xCC@P@&Y 3X P XPX P@PA@OpCLX4B0@pXPX PX'tP & PX PA@U,&t'P  A@O&tюp(p(ЇX('P(P@:X,P@:X@:C X@:X-B0X@:XC|X@:XP@B4X@:XP@B8CjX@:X&PA@(P@CJX@:XP@C2$Q@FDC&$P@8C@P@&Y 3X%Q@:$Q@:C $P@?$PA@TP@6X$P@:$P@:X@:B $PA@TP@JCL$PX@:XPA@UP@JC&'tX@:XP@fP$PA\&tюp(p(Їюp(p(Ї$P@9DX@P@:X@P@:$Q@:юXYCn'tXX@8Z&PX&PXX@8ZX@8PA@\&tX@XPX&Q$QCA@*P@XX@:X @"P@:XX@\n(%d .nr %d \n(%d .ds %d \v'%du'\h'\n(%du-\n(%du/2u'\*(%d\ \h'-\n(%du-\n(%du/2u'\v'%du'\*(%d\ \h'-\n(%du-\n(%du-2u/2u'\v'%du'\l'\n(%du'\v'%du' . b:b shift b: S%d <- S%d vert %d S%d vert %d; b=%d, h=%d .as %d \v'%du'\*(%d\v'%du' . e:eb: S%d <- S%d S%d; b=%d, h=%d .as %d "\*(%d . numb: %s %d . shift: %d;ps=%d .ds %d \v'%du'\e\L'%du'\l'\n(%du'\v'%du'\h'-\n(%du'\*(P@PA@O&tюp(p(ЇX(C0T'tX(PX@:PX(PA@+&t'xX(P X(PX(P@ PA@O&xCA@*P@X@P@)PA@O'tX@PX@:PX@PA@+&tX(X@:X @"P@:X(X@'xX@FHXP@H#X@0P@B<%P@0X@B<#6X@B\n(%d .nr %d \n(%d .ds %d \v'%du'\h'%du*\n(%du'\ \v'%du'\*(%d\h'-\n(%du'\v'0-%du'\ \v'%du'\h'-\n(%du'\*(%d\v'0-%du'\ \v'%du'\h'\n(%du-\n(%du/2u'\*(%d\h'-\n(%du-\n(%du/2u'\v'0-%du'\ \v'%du'\h'%du*\n(%du' . shift2 s%d <- %d %d %d .nr %d \n(%d .if \n(%d>\n(%d .nr %d \n(%d .as %d \v'%du'\*(%d\h'-\n(%du'\v'%du'\ \*(%d\h'-\n(%du+\n(%du'\v'%du' ([cfn{@4fvD@)]cf}R b0RRRRtRRRRR RRRRRXRRXAIPSU4& `.nr %d \n(%d .if \n(%d>\n(%d .nr %d \n(%d .if \n(%d>\n(%d .nr %d \n(%d .ds %d \v'%du'\h'\n(%du-\n(%du/2u'\*(%d\h'-\n(%du-\n(%du/2u'\v'%du'\ \h'\n(%du-\n(%du/2u'\*(%d\h'\n(%du-\n(%du+2u/2u'\ \v'%du'\h'-\n(%du-\n(%du/2u'\*(%d\h'\n(%du-\n(%du/2u'\v'%du'\ . from to: S%d <- %d f %d t %d; h=%d b=%d .ds %d \v'%(<===\(==!=\(!=+-\(+-->\(-><-\(<-inf\(ifinfinity\(ifpartial\(pdhalf\fR\(12\fPprime\(fmapprox~\d~\unothingcdot\v'-.5'.\v'.5'times\|\(mu\|del\(grgrad\(gr...\v'-.3m'\|\|.\|\|.\|\|.\|\|\v'.3m',...,,\|\|.\|\|.\|\|.\|\|,\|alpha\(*abeta\(*bgamma\(*gGAMMA\(*Gdelta\(*dDELTA\(*Depsilon\(*eomega\(*wOMEGA\(*Wlambda\(*lLAMBDA\(*Lmu\(*mnu\(*ntheta\(*hTHETA\(*Hphi\(*fPHI\(*Fpi\(*pPI\(*Psigma\(*sSIGMA\(*Sxi\(*cXI\(*Czeta\(*ziota\(*ieta===> >>*?????>:>J>Z>n>>>>? ??0?B?T???f?v  " ! # $ % /   & ( ' ) *     # $ % & ' ( ) ,* .+ -, +- / 0@ " ! # $ % / 1 2 & ( ' ) *    % & ' ( ) ,* .+ -, +- /  " ! # $ % / 1 2 & ( ' ) *     # $ % & ' ( ) ,* .+ -, +- / 0 k0@1 B2 D3 =4 C5 @6 A7 >8 ?0)1 B2 D3 =4 C5 @6 A7 >8 ?0*1 B2 D3 =4 C5 3! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0 " ! # $ % / 1 2 & ( ' ) *     # $ % & ' ( ) ,* .+ -, +- / 0B |.  |.  |.  |. 0 000@C KhLieopqwax5ycz7 4j68XY+\,]-^._kS 79;?AQSUWY]_cegikmoqsuwy{}: 1Y1_1f1l1r1w1{111du'\(bv\(bv\(lf\(lc\(bv\(bv\b'\(lt\(bv\(lk\(bv\(lb'\(lt\(bv\(lb\(lc\(bv\(lf\v'%du'\*(%d\v'%du'\(bv\(bv\(rf\(rc\(bv\(bv\b'\(rt\(bv\(rk\(bv\(rb'\(rc\(bv\(rf\(rt\(bv\(rb\v'%du' . curly: h=%d b=%d n=%d v=%d l=%c, r=%c \b'%s%s%s'. diacrit: %ctype over S%d .ds %d \v'-1'_\v'1' .ds %d ^ .ds %d ~ .ds %d \v'-1'.\v'1' .ds %d \v'-1'..\v'1' .ds %d \v'-1'\l'\n(%du'\v'1' .ds %d \l'\n(%du' .as %d \h'-\n(%du-\n(%du/2u'\*(%d\h'-\n(%du+\n(%du/2u' .ds %d \h'%s%d.%dm'\*(%d \(*ykappa\(*krho\(*rtau\(*tomicron\(*oupsilon\(*uUPSILON\(*Upsi\(*qPSI\(*Qchi\(*xand\fRand\fPfor\fRfor\fPif\fRif\fPRe\fRRe\fPIm\fRIm\fPsin\fRsin\fPcos\fRcos\fPtan\fRtan\fParc\fRarc\fPsinh\fRsinh\fPcoth\fRcoth\fPtanh\fRtanh\fPcosh\fRcosh\fPlim\fRlim\fPlog\fRlog\fPmax\fRmax\fPmin\fRmin\fPln\fRln\fPexp\fRexp\fPdet\fRdet\fP\ \tconverted token %s... too long. %ctext: S%d <- %s; b=%d,h=%d .ds %d "%s Rdefs,L,,,x,  # $ % & ' ( ) ,* .+ -, +- / 00 ; < 3! :" 91 B2 D3 =4 C5 @6 A7 >8 ?000  " ! # $ % / & ( ' ) *     # $ % & ' ( ) ,* .+ -, +- / - I- J- K- L @6 A7 >8 ?0+1 B2 D3 =4 C5 @6 A7 >8 ?0, r s t u0G0Y0Z0[0\0K0<0= " ! # $ % / 1 2 & ( ' ) *     # $ % & ' ( ) ,* .+ -, +- . v/ 0.0/0001! :" 91 B2 D3 =4 C5 @6 A7 >8!$-./$01234?@ABCDEFGH$$$$IJefghijklmnopqrst8IZk|*EJ6;@EJKLM11111111111111111112222 22222$2*21262:2=2B2G2K2N2R2W2]2a2h2l2r2v2|222222222222222222222222233 3333 3#3(3-32"36!3:3>3C3F 3J33N73R83W13[23b53f43l63r3w3{3333333-\v'-%d.%dm'\*(%d\v'%d.%dm' \v'%d.%dm'\*(%d\v'-%d.%dm' . move %d dir %d amt %d; h=%d b=%d \(*S\(cu\(ca\(*P\(is.ds %d %s . funny: S%d <- %s; h=%d b=%d                    # + 0 5 @ F K R Z b c h w }                      ' , 2 7 = B I N U Z ] b e j p u {                 %s.nr 99 \n(.s .nr 98 \n(.f 'nr %d \w'\*(%d' .if %d>\n(.v .ne %du .rn %d 10 \*(10 .ps \n(99 .ft \n(98 .EN%s.nr 99 \n(.s .nr 98 \n(.f .ds %d " .as %d "%s .as %d \*(%d .ps \n(99 .ft \n(98 .as %d "%s.ps \n(99 .ft \n(98 \*(%d .ds %d \x'0'\x'0-%du'\f%c\s%d\*(%d\s\n(99\f\n(98\x'%du'. answer <- S%d: h=%d, b=%d, before=%d, after=%d no strings left.ps %d .nr %d \w'\*(%d' can't open file %sfatal error: file %s, between lines %d and %d fatal error: file %s, between lines %d and %d .as  " ! # $ % /   & ( ' ) *     # $ % & ' ( ) ,* .+ -, +- / 0%- R T U V W0H0I0J0C0D0F0E T U V W- Z0O0P0Q0R0S0T0U0V0W0X0  ; < 3! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0"! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0# ; < 3! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0 ; < 3! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0' |. { " ! # $ % / 1 2 & ( ' )   3 33#3$3(3%3&3'3/303333344 4)4*4,4+4# 4( 4/46 4:4?4D "^{}~A\ArAAjAzAAbBsyntax error in equation %d. eqn: S%d . sub box %d %d %d \|\|\|errorCONTIGQTEXTSPACETHINTABMATRIXLCOLCCOLRCOLCOLMARKLINEUPSUMINTPRODUNIONINTERLPILEPILECPILERPILEABOVEDEFINETD            $)-26;?DHRV`clox{ &*47@DNR !'()+-/0123456789:;<=>[\]^|~#"$h" " "4"#"""""""""""""L"L"L" #2" #*"4#$>=\(>=<=\%d \k(97 .ds %d \k(97 . mark %d as %d .ds %d \h'|\n(97u-\n(%du'\*(%d .ds %d \h'|\n(97u' . lineup %d in %d . %c column of S%d, rows=%d \ \ . colct=%d . row %d: b=%d, hb=%d . matrix S%d: r=%d, c=%d, h=%d, b=%d .ds %d "\*(%d%s 55666J6p6666??67747f7777888(848Z888899N99:J::?:;2;b;;;<8 ?01 B2 D3 =4 C5 @6 A7 >8 ?01 B2 D3 =4 C5 @6 A7 >8 ?0! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0 " ! # $ % /   & ( ' ) *     # $ *     # $ % & ' ( ) ,* .+ -, +- / 0A |. } |. ~ |. 0$ T U V W.  r s t u. 0 - - - - 00000N0!0&0000 0>0?0 0-! :" 91 B2 D3 =4 C5 @6 A7 >8 ?0 ; <M [|f0EF G HNOPQ3`4a5b6c7dM0[0f0xz0llmnJgEFINENDEFINEDELIMGSIZEGFONTFROMTOOVERSQRTSUPSUBSIZEFONTROMANITALICBOLDFATUPDOWNBACKFWDMQMQ1LEFTRIGHTDOTDOTDOTHATTILDEBARUNDERVECDYAD$acceptstuffeqnboxmatrixcollistcolumnlcollistccolrcolcolsboxsuptboxtosizefontlpilecpilerpilepilesubleftrightpboxfromdiacritfwdupbackdowntextsubsup.ENfromtosumhatvecdyaddotdotdotbartildeunderprodintintegralunioninterpilelpilecpilerpileoversqrtabovesizefontfatromanitalicboldleftrightdelimdefinetdefinendefinegsize.gsizegfontupdownfwdbackmarklineupmatrixcollcolccolrcolcan't open file %s quoted string %.20s... too longdefinitions nested > 9token %.20s... too long. define %s . name %s defined as %s .ft %c LLLMLKfKKLstate %d, value %d, char %d character %d read reduce %d syntax errorerror recovery pops state %d, uncovers %d error recovery discards char %d 55550123456789ABCDEFCDEFtatatortentatouslosisisasr$urigr#rtororherpherrrrcopyntonhononen$nn%ainlininouinomomimllllillcklllllalfalaltablbllalalalikgagiagergmgkgdgifnifereeidididuenclunc&esncerncinc%ancerncarncancalncincusicticieclacrooeli$ieoontintrinrinpinninminlinlinlin%sinrinlinnlinkinlinlinlinlinlinyhineethne(.4#)/5$*06%+178>DJ9?EK:@FL;AGM<BHN=CIOPV\bQW]cRX^dSY_eTZ`fU[aghntziou{jpv|kqw}lrx~msy@MPX@MPA@P&t@ZPA@ X(a!2&PPA@$C@gPA%PA@PA@ $PPA@P@NL'#5@N" @OA@a$ 'C0*'t P@PX@NLPA@&tCX(a#4P@Uюp(p(Ї$P@NP$PA@xC0@N`P$PA@#$P@Nl$PA@xC0(@@NTP$PA@X@N\P@UX@ l#6$PAX@ pB0FX@EB0<$P@ tPA@P@ pC@PAf%PA@jA@T@;P@U@EP@I@aCd$PA@bCTA@c,CJA@dB0C:A@dB0C*A@xCA@CA@C A@CA@CA@,|PA@92C0X@CZ@!PCAPC0Ch'tX@0PA@`&tPA@eC@A@fB04CxPA@ebC C@`P@&Y 3XP#P@OX@ P B0 $Q@O$P@CX@O!5$Q@O%Q@EB0PA@`Q@CP@O #ю p,p(ЇX@OC0X@O$P@O CX@O#:%Q@OX@OCX@MC0&X@M&P@MX!7$P@MC C ~!'@ &C$ @ P@M%Q@O@ #юp(p(Ї$Q@OA@$:B0ArC0$P@ PA@BX@3CAX@OX@3P@OP@OX@NpX@3P@O$P@Np$Q@M$Q@OX@3&P@3X@OB0<EGX@IP@IX@IP@IU@ICX P &&" юp(p(Ї$X(P@I%P@I$Q@TAC0 Cj" #P@MA@A X@OB0j  X@ &P@ P$X@  B@PAh%PA@jC+B BX@$LOSXcdeflosxPQTQQQ`Q Q Q8PQTQQQ`Q Q Q8Phingindinbinnoutortittiseispisrisnislisuislisbisgisdissraporugurgicaairhifedsciorarooalracacuselelheltaltaalvukthtchadua#uaur%gaonaiaia%ririiiiaaea$eaciaiaaaaoiuoi#i#eivsisiisals$es$asoooaithithowowurpoooooo alaioaiolioio%sioionoioiooooiiiiiiteiaightomeoekee+*\ 'xXP PA@,PA@Xp8ЇP$PA@P$PA@C06$P$PA@$P$PA@$P$PA@fP$PA@2P$ PA@tP$PA@XC6C.C&$C C$C$CC.  C~C@P@&Y 3XdX@OB0J C($Q@C~A@`C0rC&A@P&t#$CZ EP@I@EP@IX@OPA@xB0$X@NpEP@IU@I!$#$#юp(p(ЇX@OB0j$P@MX@O !5$Q@O$P@O$Q@OX@OB0X@O#8X@OY@O#5A|C%Q@O$P@Cюp(p(Ї$Q@OAHB0$ C0 #4#5P@M$%Q@O #юp(p(Ї$Q@OA@$:AT$Q@MA*$Q@O$P@P@OP@OP@OX@OP@OX@O(P@Oюp(p(Ї$Q@O$ɰ?C(AfA@ j#4A@X@O!6$PAf$P@M@BP@!X@P,#7$PA@'6X@#7$PA@{$P@X@O!6$PA^$P@O$P@OX@OP@OX@O(P@OX@P!4A@g$Q@O$PA@wdA@юp(p(ЇX@+V(P@+X@CC0$P@O$PA@wdA@X@EC0A@A$PARCX@P!5$Q@P8$PA юp(p(ЇA@AhX(PA юp(p(ЇX@+V(P@+$P$PA@$P$PA@X@UPA@XA@"X@EC0&X@NhP@Nh@N`P$PA@X@ l#7$PA@ xX@+PA@юp(p(ЇX@OP@OX@O(P@O$P@OX(PA:юp(p0ЇX@+B0:A@$:B0.A@C0"PA@0#8A@!;@PA@ CX P@ p C "XPA@ $Q@+$Q@BC$PA@ XPA@PX PA@ 't$P@ P@ PA@h&t@(PA@ @ PA@ @6PA@ %PA@юp0p(Ї$P@P A.#9$PPA@ jюp(p(Ї$Q@OAdA@ C0B0>A@ : "#5PAVA@ : #6PA8"$PA%Q@Oюp(p,Ї $CX@+#3&" !9$P@PDC8C4%P@+PAP #$P@PD#XP@PD#ю p,p(ЇX(PAX@+C0X@+P($P@+C$P@+юp(p(ЇX( #юp(p(ЇX(PAAюp(p(ЇX@P C0X@P,!;X@P P@P,$P@PpX(X@Pp&P@PpP@/X@P &P@P B0tAX@P 'P@P PA X@AVB0X&PP$PA@ : "!5$Q#P@M$C0A@ :X@OB0X!9 C0XC00 "B0 A@ : "#6P@MCXP&X@+C0,UB$@PA@ %Q@O$PA@X@Nt' !'PABCB$P &CX P@OX[@O' X@OPP@PH%Q@Oюp<p(ЇA@ :C * B "X@OX !Z@OX$P@Oюp(p(Ї$Q@P0A юp(p(Ї$Q@OA!7A@ B0tX@!X#&$PA^X@PC A@ ю(pHp(ЇX(dB$X(d0X.,&P,X( B0X(d$0X.,&P,X($0X,&P,X,&P,$X,$юp(p,Ї $P@PPPA@ :+!6$PC-!5%P#P@MA@,|C0 CX@?CX@CX@&CX@ TCA@w(CxX@ XCnX@(CdX@CZX@OXCLX@ lCBX@OC8X@tC.X@P,- X>,$# / #"&\, #4  #юp(p(Ї$P@8A@$:B0hA@ : C:$P@|CH$P@8P@|C6$P@|C*$P@|CC@P@&Y 3Xюp(p(Ї$P@8юp(p(ЇA@g$Q@D$P@P@юp(p(ЇA@g$P@Dюp(p(ЇX@!$Pюp(p(ЇX@!$Q^PAP@PTBJA@'tA@ PA&tPA C0$X@PTX@ X @PT#P@ юp(p(Ї$Q@OA'tA@ PAn&tPAюp(p(Ї$Q@P0A юp(p(Ї$Q@P(A*юp(p(Ї$Q@P0A юp(p(ЇX@!X#3ALȰ.$Q@OA,A@ C0PAbP@P C0X@P(#4A#A4AX@PTPAX@PX#< X@PXP@ X@P`C0"X@P X@P`P@P $PAP@P X@!XP@P ɰ.#9$PPA@ j$P@P0P@P(#юp(p+B06ARB0@ZPA@ $PA@@X@PDP@+X@+P@P X@Pp!A юp(p(ЇX@P,C0x't$PX@P,PX@NLPA@&t'tX@PpP@/PX@NLPA@&tX@P,X@Pl !5%P@Pl$P@P,юp(p(ЇX(#юp(p(ЇX@OPA8B0X@P0!4A(# X@OPAP@O #юp(p(ЇX(Y@PlC0\P@Pl't$PX@PlPX@NLPA@&t'tP@1PX@NLPA@P&t!4$CX(XPX@!XP@CX@!X$P@CX@P'P@P0BP@!X@!XP@P CX@P&P@PB0$%Q@P@PA@ $PA@X@!X#6$PA$Q@PhX@P0BP@!PAX@!PX@!P,X@PTPAT$ B Z@!$P&" $P@P0$P@Phюp(p(Ї$Q@O$X@!PX@!P X@!PA$PA@EX@!P X@O!;AA@ X@!Pюp(p<ЇX@!$PAX@!X#3AAP P@P C0A@ :PC0XP@M'P# &CX@ CX@UCX@CX@CX@!X, P@I P@I$P@I@IP@MCPA!4$C<X@Pt\,"Z @!Z,"Z @!PX@RP@PPC@P@(&Y 3X`PA@IP@Mю p,p,Ї @IP@M$P@PLPX,PAPX@M$P@IP@Mю p,p(ЇX(!4%C$CX@Y(#3&" #4 C~$C"X@!9X(P@#&CB0FX@3!9@PA@ X@3&P@3#($PA@@#X$A@ : =!3&#P@MAP X@O#6$PCX Y#$P#$PC$A@ : =!3&#P@MAvP X@O#6$PCPX Y#%$P#$PCC.A|PCC%B BX@X#юp0p,Ї A@ : (!6AP#P@MAPX#ю p,p8Ї$ PP P$PA@ : C.P@MC>"$PCX&P $PCC@(P@8&Y 3XA@ : B" B $Q&X$ PC юp(p(ЇA@$:B0.A@ :B0 #8 !8P@MX(## #юp(p(Ї.PAP@Hюp(p(Ї'PA`P@Lюp(p(ЇPA:P@Pюp(p(Ї$PAP@dюp(p(Ї$PAP@hюp(p(Ї$P@XA@$:B06$Q@TA@=$P@TX@OB0$PPA,P@Xюp(p(Ї$P@Xюp(p(ЇX(Y,#$X(#X,#юp(p(Ї$Q@TA@$:$PA@=PAX@O(Ї$CX@ Y(#4&C!2% #юp(p(ЇX(BDX(X@ C0X(X@ PAX$X(P@ X(P@ юp(p(ЇX(PADP@PT$P@PdP@P`P@PXX@P0C0X@PTBX@PTX@ C0jX@OX@PTX@ P@O%P@PTA#2"X@OP@P`X@Ph!;X@OPAP@OX@OP@PDP@OC$CX@ #3&" #9AP@PDB0R$P@P0X@P\&P@P\#'$PA@@@&xC.'x@P @PX,PX(PA&x#юp(p(Ї$X(!4$C'x.!7$Q$CP@MXC0BA@ : Cn$CX@$CtX@$ChX@$C\HCP$CF.C:$C0X@ \P@MX@ `C@HP@l&Y 3X$X#6 [PX@T!:X  PX C0$ C  'C0X$P"X C0FX@!X#7X@!X#X@CX@T!4X@CX !4 X PX#3$#$P@OX#юp8p(Ї$Q@OA@$:A@ C0R$CX@ #3&" C0.$P@RP@PtZ@!PP@юp#2$A@gP@$P@Tюp(p(ЇA@$:#6X@C$$P't@PA@EV&tPA@A@gX@P@P@X@!:X@P@A@{юp(p(ЇA@$:#6X@,C&P't@(PA@EV&tPAX@(P@,P@(A@{юp(p(ЇA@$:#6X@4C$$P't@0PA@EV&tPA\X@0P@4P@0юp(p(ЇA@$:B06$P't@PA@EV&tPAA@gP@`A@{юp(p(Ї$Q@TA@$:#6X@$C$$P't@ PA@E&tPAPhB0 P@PXX@PT!7%P@ # X(P@ $P@P0X@PDP@P #юp(p(ЇA@ : !2" P@MX@O#юp(p8ЇA!6A@ !3.P$Q@OA@T$P@O$P $C0A@ :PX B08 C0 B0"XP@MA@XP@M C0$P C` B0$P $P@OCFX B0.B0$Q X@P PCX B0 !5$Q #$P X@P #7XPAC,X@P C0AXP@P $PA%Q@OX#юp8p(Ї$Q@OAZP@OX@OX!7(Q@O#X@PHP@OX(P@O#юp(p(ЇX(PA@B0 @PA@ @PA@# Z(P@Nt #юp(p(ЇA@!4$C(!5A@ # #юp(p(Ї$Q@OAC0$PA#;X@ B0%Q@O$CPCLX@Nt'U@O#PAX@O$P$Q@+%Q@OX@ PA#юp(p<Ї$Q@OX@O$PAB0X@OP X@O P@OP$P@+X (P$ PU@Nt#'PALXYC0PA@GP@8юp(p(Ї$X,#6X,P@3$C0X@3PA2X@3PAP@3 #4!4 Cl Y@8B0H P@PL%PA@92X@RP@PPX(PX@CPA@9 #PX(A CZюp(pHЇ($PPA\#3$#$P$CX@ P C0ȾX@ P$$X$PAX@+P$#4&C$QQXB0RX &!6 @X  & &PPARPA@ &Cюp(p(Ї$Q@OA@$:A@X@NlB0X@EC0:X@NhP@Nh@N`P$PA@@PA@X@CA@$:#8X@!P C$A@ C0PA@92Z@!Pюp(p(ЇA@$:$PA@EBX@O#2$Q@UxA юp(p(ЇA@w(Y@UxB,X@X@UxP@$PA@qP@$P@Uxюp(p(Ї$P@P@A@$:B0$Q@$Q@T@CPA@EX@OB0$PPAhP@C$P@@PAF$P@B0$Q@$P@OA@TAC%PPA>CX@C06%Q@X@PX@x$Y(#4&C #юp(p(ЇX@ &P@ XP@ X@ P@ X@ !:A@$PA@T@ C0"X@ P@ $Q@ $P@ юp(p(ЇȰX@!XC0(X@!XC0X@!X [(#" CP$C2X@TC0X@T#Z@ T[(#$ #&CX@ T[( #" #юp(p(ЇX@!X#7X@!X#X@CPA2#юp(p(ЇX@!XB0l$Q@PX(#7X(P@P #X@OP@P X@OB0@ C0"@ PA@ @PA@ # @PA@ A@-Z$Q@Up%PA@+юp(p,Ї $'t$PP$PA@P&tB00 !6$Q@Up#$P@UpX@Up#5CBA@*^$P@UpX@EC0&X@NhP@Nh@N`P$PA@$#ю p,p(Ї\PAP@ Pюp(p(Ї$P@ Pюp(p(ЇA@$:$P't$PA@E&tPAP@PX@OP@PX@!XB0X@C!7$PA@qюp(p(Ї$P@OP@$"CX@OB0A@$:@TA@$:$PA@=PAP@$P@Tюp(p(ЇX($C0 @B0 #4 Ct!8 [@UCX!4X@ PY@PC0BC:B02@N B X@\@P@U #юp(p(ЇA@ !4$C4!X C0&X!4$C&"&XV@ #юp(p(ЇX(BB Y@ h#5' C2$Z,XY(C0Z,X!3%#&C #юp(p(ЇX@V@ P@X@ PALP@юp(p(#юp(p(Ї$P@OX@B0X@!XB0X@C!8$PACX@B0(ABX@C0X@#6$PAAC X@C0X@3!8$PAnAp$X@!PX@PX@!X!8X@ XPAX@#3A$X@P@tX@3#7$P@ C0X@8C0&X@([@P@tY@#X@P@tX@|C0X@8C0|X@3C0nX@P@t$P@pP@lX@|B0.X@ PX@x$PA@F8Q@CX@|!7X@xQ@$Q@ $P@3X@!X$Y@t#X@tX@!P$X@PAPA@F8#$Q@X@B0$PPA$P@3AAT$P@OP@юp(p(ЇX@O#5X@O#X@$P@OPA@Oюp(p(ЇX@C0&%Q@B0$P@X@UtP@A@aX@C0,%Q@B0 X@C0$PX@PA@ jюp(p(ЇX(B00X(PA@92#;X@Z@!PCX@U@B 6X@UB0(@PA@ $Q@UP(%P,#CVX,!:X(PA@`P,X,Q@X@x[,P@xX(X@&P@P$Q@@OC0юp(p4Ї$P@UX@X@B0BX& B0*%Q@PA@`PX@[P@C'X@Y@xC RX@\B0HX@XC0>X@C0X@$Y@xC $T@X#7AY@#&PA@X@P@P@U$P@UX@UXC0X@UX!'$Q@UCX@C0X@\C0X@UX B0r$Q@UX@C0HX@& CRU@CH$T@X#8X@' C 0$T@X#8X@& C$Q@U$P$PAZX&PA@`X@ P@%Q@PPA&C.X@x!$Q@&P@TP@UDX@Ul C0't$PX@Ul PX@NLPA@&t't P@PX@NLPA@&t't$P PX@NLPA@&t't P@PX@NLPA@P&tP@Ulюp(p(Ї%Q@3#$P@3$P@3$PAdюp(p(ЇX@3B&@sPA@ $P@3 PA@$PA$Q@3юp(p(ЇX(B0$X@3X@3C$A@$:A@ : !!3$#$P@MA@=X@O!6 #"&CbA@ : C4$T@C!2&C>$T@C#2&C.&CB0$P't'x$P 'PA&xPA@EV&tPAd?P@X@OB0fX@M C:X@@P@C<X@P@C"CC@4P@@&Y 3X $P@MP@O&C$P@юp(p(ЇA@$:$PA@EX@O#4X@A@w( C*X@P@X@!$P$PA@qP@юp(p(Ї$Q@OA@$:A@ : C0,A@ :B0 !3 @NCюp(p(Ї$Q@A юp(p(Ї$Q@TA@$:#3$#A@=ЇA@ :+#5-B0.A@ :P@MB !'$P@MCV!3CL C F B >B 6A@ :P@MB B $ $P@Mюp(p(ЇA@$:$PA юp(p(ЇX(#6A@ #A@,| #4P!6X@ C"SC00@PPA(#$PAX@!XC0.X@!XX @!Y(#+X@!XX @!P(C"X@!X(Y@C#X@CX@!P(X@ ' C X@OB0$PA '"$P@юp(юp(p,Ї X,B0X@!XC0FX@PA@X@O#7X@OP@X@!XZ@X@!QPA@$ PA@P@$P@OX@!PX@!XC0NPA@X@!XPA@$ PA@X@!XX @!QX@!$PX@!X C0hX@!XB0ZX@!XX @!Y BBX@!XC04$PX@!XPA@ jC0$Q@OX@!$QCPX@X@O#7X@OP@X@!XX @!ZZ@Q@C$ PA@$P@OP@X@CY@ TB.$P@CX@!P(P@PX@OP@P X@$CP$P@UPA@`P X@UB0X@C0X@YC0X@'P@XB0%Q@U!6X@C0X@xY #%Q@CX@X@-C0ZC0RX@X@X @PX@XPA@`X@x P@xQ@$Q@$Q@P@$CF%Q@X@XPA@`X@ P@Q@xQ@$Q@'Cюp4p(Ї$P@TX(C0'tX(PA@e&tPA@юp(p(ЇX@B0N@P@X@`!X@`P@%P@`X@([@P@x$P@pP@lP@(PATC@P@&Y 3XX(B0 #3$#$X@3P@3 C0@$P@CA@ : "> C0P@M$Q@OCL$Q@OPA@B0&PPA$#7$P@OC%Q@Oюp(p(ЇA@ :Y(C0Y,#6 #3CY,B0,X,PX(PAY(#7$P@OCC #юp(pLЇ,TL#4$CXLPLX@!X#4A@(JA@&@P(P@P !4$C$P$$P@CX@PX@PX@PX@ PX@P X@PAX@C0  B0X@UtP@$P@P@ C0&X@!=X@P@UtX@ P@P@$P@TA@aюp(p(ЇA@$:B00A@ C0$SC0@PPA@a,!6$P@ #P@ X@ !5$P@ X@  P@ юp(p(Ї$Q@O$P@P@$Q@TA@$:A@=A@$:X@OB0A@ P@#4P@$P@Tюp(p(ЇX@#%$P@$P@A@$:B0HA@ :P@$P@A@$:$P't$PA@EV&tPAX@O!4P@юp(p(ЇX@!X#7X@!X#PC4@C0( P #6 [P[$P#CY@C#P@C ZPY@C#&XP@CCZ$P@PPPA@8XP@CXP@EX P@XP@ A$P@Uю$pDp(ЇX@P@ \$Q@TA2#юp(p(ЇX@P@ \A #юp(p(ЇX@A@ :A@=C0*X@T#4X@'xPPA@F8&xPAA@ :$P@T$P@ \ #юp(p(ЇX@X(u!6 CX(r!5%$Q@TPA$P@T #юp(p(ЇX(# p(ЇX@P@PLX@PL1PA@`X@#7%Q@C X@C]@@C0"$Q@CX@$P@\X@&X@U&P@UPX@U#'@P@UX@OPPAA8 C04 B0X@X@.#7!#4?!5$Q@X@$P$P@@ P@$P@X@U&P@U$PAX#ю p,p(ЇX@B6X@UB0(@PA@ $Q@UP(%P,#CFX,!:X(PA@`P,X,Q@X(X@&P@P$Q@юp(p(ЇA@ :B0x T@ C0lX@C0" @N !<%W@  _X@B0. C &CX@!6%W@  #ю@P@&Y 3Xюp(p(ЇX('P(U@B$X(XPA~#4X(#C$#юp(p(Ї4|X(&P(PAX &C X(&P(PA0 &'C@4|$@4|@4|#юp(p(ЇX(Y@C0L't$P P@PX@MPA@&t'tP@4PX@MPA@P&tX(@4#юp(p8ЇX@4x&PAC0P@4xX@4xPA|C0|P$P '&U@4xC0X@' C "$Y@B02't@%PX PaPAA@ :P B0X P I$PX@PA@ :Y C02ɰ C0*MB  P &XP &$QC%QBRX!9X @P@MC<$P 'X\@P@IP'X P @IP@Mюp4p<ЇA@ :PB0XPX@P@ \$Q@TX@PA@=PA@F8$P@ \ B0XPAJ$P@TC*A@ : Y!7X@#A@ :$P #  PX@P ] P] PA@eVPX PA@P@PPA@P&tX PXPA@, 't$PX@ PPA@&t'tXPPPA@P&t[@!CX #4Q#@!P &CX@P@X@P@X@!6X@C0>X@N\%W@P@N\X@N\V@P@N\@NTP$PA@X@PA@~X@U#7X@P@ ю(pHp(ЇX@PA@~X@BC0 X@ pPA@ @EPA@|X@UP@N\@NTP$PA@юp(p(ЇX(X@U&P@UPX@UB!%Q@UX( B0%QA@~" X@0C0X@U|!6X@P8C0X@9!9X@0PA@~X@U|]@P@U|X@P8]@P@P8X@U|'P@U|#:X PA@~CX@P8'P@P8#:XPA@~CX@4PA@~$P@P8P@U|юp0p(ЇA~юp(p,Ї A@'t$PP$PA@P&tю p,C@"ppЇPXp #3&"A@'ӱɰXB0 0 CPXpPA@Bɰz!%C&ҽCXp#юPppp@U$p@U$ppЇPPXpPA@B   " ZZ\Floating Exception. Cannot open suftab. /tmp/taXXXXXCannot create temp file. Typesetter busy. Cannot open Too many page numbers RHdWaiting for Typesetter. Pipe not created. Cannot exec: %Too many string/macro names. Out of temp file space. Bad storage allocation. Core limit reached. Macro argument too long. Cannot divert. .$.A.H.T.Vp(p(ЇX(X P&AT#2" 'X PAtC00P@&X P&AX#2" ' 'P@P@4xX P&A#2" 'X B0X@[@'B@P@UX@U$P$P@\A<!7A^!3AX@U&P@U$PX@C0|$ C0t$@P@UX@UXC0TX@UX@X @UUC .&X@UXX@UX@X @UPX@UP@$Q@UCCюp(p(ЇX(C0X(PA#3$#$#юp(p(ЇX(A!Z#'a!z!#$#$#юp(p(ЇP@A4&tP\CrX@& B04't@' PX PX @PA&tP\C0't@)PX PX @PA&tP\'t@(tPX PX PA&tP\'t@%PX PX PAb&tP\Y #'P  &PCXP@4xX Y@C XX@U&P@UPCTюp8p(ЇX,PAVX(PAD$<$# / Z0@!2 #юp(p(ЇA@ :!3 #юp(p<ЇA@ :PB0XP$P@TX@PeVP IX!6X P &TC0P&XP &MC&X'PC0P&X P &CX @P @X!2'$P @IP@M$P@Tюp<p(Ї$P@ L P@OA@$:B0hA@ :B0V C0HP@ LA@$:B06T@MB0&X@MP@MY@ L#7X@MP@Oюp(ptЇTXtY@ !P@@>>\>P>z>P>>P>P>P>P>P>P>P>P>P>P?`>P@<??+-|A^A`AjATPcimnpuvBbBVBLB(B4B@BBBlToo many number registers. ixcmzvldwIXCMZVLDWDivide by zero. bc@$:B0$Q@TA@=P@$P@Tюp(p(Ї$A@$:B0X@4vB @PA@ X@$C|$C0rA@ : : #5 B0 $ &P@$ C02C2-!5CPA &$4vClCCHюp(p,Ї 3$C0 P !4$CX@ C00U@4xB &X PAP !5&&C B0 'Y@4xC0&Y@B0zX PAsB0^X@X C0B C0X@U&P@UPX@U#'@P@U&&C$C@ \X@PA@=PA@F8$P@ \ !9XPA|CnA@ : Y!:P@MX@ư#  C0PA@`PI CPA@eP & ]PB0PX> <$# /P> PA@eP &P&X [ PA@eP &C]P C0J C$ P &X PA@eP &C@,P@<&Y 3XXC0$ P &XP &P&$P &XPA@IP@Mюp<p(ЇA@ :Y(#5 #2"  #юp(pЇ`A@ :PX0X@?[@CPP!$&CX@P@5PL$# / PPX@OPA@`#4XP!'$P@OC"XP P@OXP PPXP]@\@PPXPPA@e@5P@M$P@OXP@ LX P@ XP@  #юTptp(Їюp(pHЇ($P@ PA@C<@tPA@ @ PA@ @PA@ %PA@'t PPPA@P&t't!@8#X@ 6 r V  l  (0Lbdfhjkloprsuvwxz 8B V.L'/usr/lib/tmac.xxxxx/usr/lib/term/37/usr/lib/nsuftab\ P/dev/cat  ds as spOftbpsgnvsf^nrCifS:ieRelRpoLtl1ztmObpNchMlpnN4brgtiKDneZnfGceIfiGTinJliY<llJnsGmk]rtPV0 ((.'.@@@ @sqemru141234mififlffFiFldedgscfmaagaulsl*a*b*g*d*e*z*y*h*i*k*l*m*n*c*o*p*r*s*t*u*f*x*q*w*AA*BB*G*D*EE*ZZ*YH*H*II*KK*L*MM*NN*C*OO*P*RP*S*TT*U0@ `0 @P@`0r&bY*FH0"p @` `P P @@``&@`6%XfXC@  ``P P"`q"cr Q"0`S!Q"0P`Sp!)Vha0f6uP p`@`aR pc"b'cP `0a@ `@``HU)rPUWDD*` p`0  ˙`.`p`5"0 f`a/devV  0 main",exit"_exit$Onxf$Onx$Mtime"Dldiv"atoi"=cbuf$Istat"chmod"flusho"findmn"!contab# collect"-Zpushi"+getach"level$Egetch0"traw$Ofi#Dflss$Osetrpt">lg# getlg"gfc# Ltabch# ldrch# setfield"$chbits#width"`makem"esetn"6setstr",setaam de di/da/|whLdt1it\rm JrrCdrnadFrsGnaG8plLftaYtr[4ul[cu[ltJnxDso igtcHfcecXeoY lcHevQrdWzabW`flPexssgfpfcsgbdglgghcHhyInhIfnm^nn_sv^,os^llsKccHNc2HtemPafDphwmc]:pm4pi`uf\Npc3ht*F*XX*Q*Wsrtsrn>=<===~=ap!=-><-uadaeqmudi+-cucasbspibipifpdgrnoisptesmoplrgcobrctddrhlh**bsorciltlbrtrblkrkbvlfrflcrc0 "!S3"#`""ttyx#ms# catch"signal"fpecatch"kcatch"npn# xflg# cps$Mstop$Efindr"92vlist#!nfi# nextf# mflg$Mgetpn"eqflg$Utti# 0termtab# dotT$Upto# pfrom# print# argp$N|rargc$Nxinit2"setexit"nlflg"/(eschar# Pspread#setch"`setps"asetfont"bsetwd"c,vmot"dhmot"dsetz"xsetline"setvline"setbra"setov"getsn",|xlss"fsethl"ebch0$Oip$Oiline$Ocwidth$Oifilt#nchar$Orchar$Ocp$Map$Ordtty"XHrbf") donef$Odone"nfo$Onextfile"ifilep`Аp@РP`p"! #!4!@``Pp`#s5$#D"1f1@` @P` 0P` @````p``p0#!Q "b"1P```PPp@ P@0`` @!`@PA! "Qp@`p``@F! g 3!Bp ``Phk22jWf@P`@P0@ 00 @P@`0#b&`2gY&FI00 @0 @ @@@ @`6%e`8XC  @`PP P 00p P P p P`P` )Vh`0fu$Onflush$Onb#lgf$Ocopyf$Oframe$Ogetch" :ejf$Pejl$P trap$Och$Meject"wdpendt#lit$Plitlev$Ptflg$Ppchar"cc#Hc2#Lgetrq" control" jflushi"Ttext"ldone3"jprstrfl" suftab# 4open"suffid$Mprstr" seek"sufind$Mread"Pmktemp$Oifi$3popf"offl$Oifl$Oxbuf$Gxbufp$Ixeibuf$Icasenx"Dskip"$:getname"caseso" noscale$Tatoi1"A nonumb$Opnp# pnlist# chkpn"utoolate$+error$+pchar1"tlss$Pdip#!ralss$PB"f()/ /// @/N@//_?OU3u&'=  //`O@//?@/0e:ou36t(OUH/,oL+/???L?>???o,O=U5/63'V /)P./0>._|-ݶm?o//3"? /?@~(wf"J?H2*s0 P0 o UͯfV/ @p o~%hlr"gjC@ `@P" creat"$close" ibf$NLtrtab$Nmchbits"ablock#write"unlkp$Uttyod$NPttyn"ittys$N`gtty"iflg$Nlttys$NTttysave$Uascii# lmesg" xptid# pwaitf$Eptname# tptinit"Toline$;olinep$Uibuf$Eeibuf$Iibufp$Iinit# Hioff$Npv$Ccvtime"Fsetbrk", stk$P(app$P0em$P$reset"d$Bwoff$P,wbt"'6pendw#getword"{pendnf#done1"tbreak"gnofeed$Eptlead"gflag$Plead$P8done2"@unlink"Xtwdone""stty"edone"casepi"`pipe"0fork"pipeflg$Bdup"Pexecl"hpagech#8strflg$+blist$+wbuf$/rbuf$1caseig"copyb"$tcasern"oldmn$PTclrmn""$caserm" Jcaseas" caseds" casede" caseam" wbfl"(Jfinds""copys"%newmn$PXapptr$P`free"&aplnk$Pddiflg$Phincoff")nextb$PDalloc"&@macerr$P\boff"'blisti"(wbfi$Pproff$Plrbf0")\popi"*^enda$Ntargtop$PHsbrk"caseda"/|casedi"Mlcasepn"N4npnflg# casebp"Ncasetm"Ocasesp"Ocasert"PVcaseem"Pcasefl"Pcaseev"Qevi$Tevlist$UDev$Ulcaseel"Rcaseif"S:caseie"Rcmpstr"U>eat"eatblk"Tapts#apts1#pts1#casest"W`dummy">caserd"Wztty$Upcaseec"Xcaseeo"Y caseli"Yю(pHp4Ї$PA@X8PX4 !4A# A@PP X CPA@A" $'tP$PPA&t$ CPA@A^$P B0$PPA@A6A@P P X #3$#$X #3$#$X  #3$#$X #3$#$#8X$PC,'tXP$ PPA&tXXX.P #8X$PC(PA@'tXP$P$PAv&tXC0 B0PA@A> P X !3$#$X  !3$#$#decml":roman";$abc"ckph"@dfact# \dfactd# `vflag$Tcaserr"Cdcasenr"Cinumb"Ecaseaf"Dpalph"res# dhnumb"EVquant"F8iflist$3casead"Fad#8admod#|casena"G8casefi"GTlnsize#casenf"Gcasers"Gcasens"Gcasecc"HNcasec2"Htcasehc"Hohc# hsps#caseft"bsetwdf$Umot"dcasefp"fcasevs"f^lss1#caseps"gncaselg"gcasecs"gcasebd"gcasess"gbrflg$3wch#movword"wlinep#donum"kne#totout# adrem#padsp#lnel#xline#nwd#nofill"ogettch"Fcallsp"pӼɰ#9@/PA@ PA@X Y@4\C0d'tA@P$P$ P$PA&tӼ C0(ɰC0ɰC0DA@PXPPAӼ C0ɰC0dɰ#9@0PA@ PA@'tA@PP$P$PAp&tӼ C0ɰ#9@0#PA@ PA@A,ӼɰC0b B0"X#Pcasetc"Htabc#dcaselc"Hdotc#hcasehy"Ihyf#Xmax"Icasenh"Ifcasece"Ice#casein"Jin1#nc#un#setnel"{casell"Jll1#,caselt"Jlt1#4caseti"KDun1#`casels"Kls1#$ls# casepo"Lpo1$Tcasepl"Lfcasewh"Lfindn"Mmlist$Tnlist$Tcasech# dostop"findt"vfindn1"uwordp#wne#hyoff#\hyphen"hyptr#hyp$Unhyp$Uwdstart#wdend#xbitf$Uword# storewor"~spflg#hbuf$3nexth#hyend$4xsufoff#thresh#punct"Xexword"suffix"digram"Vcaseht"casehw"maplow"getsuf"Vchkvow"vowel"rdsufb-P'xXP PA@PA@*Xp(Ї'tX(PA&tPA*юp(p(ЇX(PAPAPAX,  #юp(p(ЇX(C :$PX,XPA@-P@4X@4#@.PAJA@*$P@.*PA\P@4L$P@.,PABP@4P$P@..PA(P@4T$P@.2PAP@4X$P@.8PAP@4\$P@.?PAP@4`$P@.FPAP@4d$P@.NPA$P@.UPAA@jX@4TX $0 X $P X B0$XCAP- P # APCюp0p,Ї 'tX0PAz&tP'tX,PAf&tZPA#ю p,p,Ї 'tX0PA4&tP'tX,PA &t[PA#ю p,p,Ї 'tX0PA&tP'tX,PA&t\PA#ю p,p,Ї 'tX0PA&tP'tX,PA&t]PA<#ю p,p(ЇX(!9X,PA4CRX,!9X(PAC$ C^A@*A@>CbXXCBA@PA@CBC!)!X@0@1DPA@ CX PA@ #юp(p<ЇX@4l!4$C$X'tn-labelattempt to make an illegal assignmentP@ X!P@ %                       `'xXP P@&p dP'!&# P PA@C0#;@ PA@CC'C0&X PA@" юp(p(ЇX(A@C0Ű #5Ҽ&" $  #юp(p,Ї $PX C$X, C0ɰ !4&C&ɀB ɰ #Ȱ X #X'C@P@&Y 3X  !ɠ!$#$ @$ C0$  #6*P# PA@C$C PA@&" &C>$ PA@$QCP,B0ю pmain",exit"_exit""gets"bprint"getchar"chset#putchar"fin$ getc"fout#write"putc"read,0'xXP PA@PA@X main exit _exit""P$C0( B0~YC0YC0nXXCX P$X P XX$PX$$PX XP B0nXPX$PAZPXC0X C0$C0@X [P X C0rX BXPX$PAPXC0CX B04X#3$#$X!3$#$#9XX$PCC(X 'P C0XPX$PA:C0NCCXP,C2X(PA@X,XX,PA@ !4 CP,X,XP(X(XX,#PA@ 2CX P$X P  !3$#$X X!3$#$C0DX$XB0X$PXXP$PX PAX PXPA@P X C0($PXXPAX XB0>X PA@'tX PPA@ p&tPPATPA@ 2CX XX,YB0PPA&X PA@CA@X XXPXXP'tPPA@ p&tPPAX PA@PA@PA@ 2CC!)!X@1X@4l!6XX# $P@4lXX !8X8XCT$PPAzY@4`!4$C6Y@4d!8$P@4l$C #9@1PA@ X #юp8p(ЇX(Xmatchno space beginning statementunrecognized component in matchunrecognized component in assignmentunrecognized component in gotoname doubly definedname doubly definedillegal component in define"t"z""~"""#<#<#<#<#<#<#<%X%X%X%X%X##%%&&l&~&Z&H&'&''*****0*>attempt to take an illegal valueattempt to store in a valuephase errorillegal functionillegal functionparameters do not matchattempt to transfer to no,C@"p(Ї@ PA@#$# #юp(p,Ї X@B 'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(XP@XP@X!P@ %XP@ X"errno$ /* * Information about a device waiting to use a selector channel */ struct selchq { int (*sq_sstart)(); /* startup routine when selch is free */ int (*sq_sintr)(); /* selch interrupt routine */ struct selchq *sq_forw; /* next device waiting for channel */ }; /* * Selector channel address & commands */ extern char selchaddr[]; #define STOP 0x48 #define GO 0x50 #define READ_GO 0x70 # /* */ #include "param.h" #include "conf.h" #include "inode.h" #include "user.h" #include "buf.h" #include "systm.h" /* * Bmap defines the structure of file system storage * by returning the physical block number on a device given the * inode and the logical block number in a file. * When convenient, it also leaves the physical * block number of the next block of the file in rablock * for use in read-ahead. */ bmap(ip, bn) struct inode *ip; int bn; { register *bp, *bap, nb; int *nbp, d, i; d = bap[i+1]; return(nb); } /* * Pass back c to the user at his location u_base; * update u_base, u_count, and u_offset. Return -1 * on the last character of the user's read. * u_base is in the user address space unless u_segflg is set. */ passc(c) { if(u.u_segflg) *u.u_base = c; else if(subyte(u.u_base, c) < 0) { u.u_error = EFAULT; return(-1); } u.u_count--; if(++u.u_offset[1] == 0) u.u_offset[0]++; u.u_base++; return(u.u_count == 0? -1: 0); } /* * Pick up and return the nexgnal to * all processes with 'tp' as its * controlling teletype. * Called by tty.c for quits and * interrupts. */ signal(tp, sig) { register struct proc *p; for(p = &proc[0]; p < &proc[NPROC]; p++) if(p->p_ttyp == tp) psignal(p, sig); } /* * Send the specified signal to * the specified process. */ psignal(p, sig) int *p; { register *rp; if(sig >= NSIG) return; rp = p; if(rp->p_sig != SIGKIL) rp->p_sig = sig; /***/ if(rp->p_pri > PUSER && rp->p_pri < 128) rp->p_pri = PUSER; if(rp n = (14<<16) + ((SSIZE-2)<<8) - 16; /***/ } else { /***/ n = asp - 12; /***/ } /***/ /***/ grow(n); /***/ suword(n, aps); /***/ suword(n+4, u.u_ar0[RPC]); /***/ suword(n+8, asp); /***/ u.u_ar0[RSP] = n; /***/ u.u_ar0[RPC] = p; /***/ return; /***/ } switch(n) { case SIGQIT: case SIGINS: case SIGTRC: case SIGIOT: case SIGEMT: case SIGFPT: case SIGBUS: case SIGSEG: case SIGSYS: u.u_arg[0] = n; if(core()) n =+ 0200; } u.u_arg[0] = (u.u_ar0[R0]<<8) | n; exit(); } /* * Create ut how ***/ return(-1); /*** if(sp >= -u.u_ssize*64) return(0); si = ldiv(-sp, 64) - u.u_ssize + SINCR; if(si <= 0) return(0); if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep)) return(0); expand(u.u_procp->p_size+si); a = u.u_procp->p_addr + u.u_procp->p_size; for(i=u.u_ssize; i; i--) { a--; copyseg(a-si, a); } for(i=si; i; i--) clearseg(--a); u.u_ssize =+ si; return(1); ***/ } /* * sys-trace system call. */ ptrace() { register struct proc *p; if (u.u_arg[2] <= 0) { &u.inta[ipc.ip_addr>>2]; /***/ if (p >= u.u_fsav && p < &u.u_fsav[24]) /***/ goto ok; for (i=0; i<18; i++) /***/ if (p == &u.u_ar0[regloc[i]]) goto ok; goto error; ok: if (p == &u.u_ar0[RPS]) { /* PSW : allow only cc & af bits to be changed */ ipc.ip_data =& 010017; /***/ ipc.ip_data =| (*p & ~010017); /***/ } *p = ipc.ip_data; break; /* set signal and continue */ case 7: u.u_procp->p_sig = ipc.ip_data; return(1); /* force exit */ case 8: exit(); default= ip->i_dev; if(bn & ~0377777) { /***/ u.u_error = EFBIG; return(0); } if((ip->i_mode&ILARG) == 0) { /* * small file algorithm */ if((bn & ~7) != 0) { /* * convert small to large */ if ((bp = alloc(d)) == NULL) return(NULL); bap = bp->b_addr; for(i=0; i<8; i++) { *bap++ = ip->i_addr[i]; ip->i_addr[i] = 0; } ip->i_addr[0] = bp->b_blkno; bdwrite(bp); ip->i_mode =| ILARG; goto large; } nb = ip->i_addr[bn]; if(nb == 0 && (bp = alloc(d))t character from the user's * write call at location u_base; * update u_base, u_count, and u_offset. Return -1 * when u_count is exhausted. u_base is in the user's * address space unless u_segflg is set. */ cpass() { register c; if(u.u_count == 0) return(-1); if(u.u_segflg) c = *u.u_base; else if((c=fubyte(u.u_base)) < 0) { u.u_error = EFAULT; return(-1); } u.u_count--; if(++u.u_offset[1] == 0) u.u_offset[0]++; u.u_base++; return(c&0377); } /* * Routine which sets a user err->p_stat == SWAIT) setrun(rp); } /* * Returns true if the current * process has a signal to process. * This is asked at least once * each time a process enters the * system. * A signal does not do anything * directly to a process; it sets * a flag that asks the process to * do something to itself. */ issig() { register n; register struct proc *p; p = u.u_procp; if(n = p->p_sig) { if (p->p_flag&STRC) { stop(); if ((n = p->p_sig) == 0) return(0); } if((u.u_signal[n]&1) == 0) a core image on the file "core" * If you are looking for protection glitches, * there are probably a wealth of them here * when this occurs to a suid command. * * It writes USIZE block of the * user.h area followed by the entire * data+stack segments. */ core() { register s, *ip; extern schar; u.u_error = 0; u.u_dirp = "core"; ip = namei(&schar, 1); if(ip == NULL) { if(u.u_error) return(0); ip = maknode(0666); if(ip == NULL) return(0); } if(!access(ip, IWRITE) && (ip->i_mou.u_procp->p_flag =| STRC; return; } for (p=proc; p < &proc[NPROC]; p++) if (p->p_stat==SSTOP && p->p_pid==u.u_arg[0] && p->p_ppid==u.u_procp->p_pid) goto found; u.u_error = ESRCH; return; found: while (ipc.ip_lock) sleep(&ipc, IPCPRI); ipc.ip_lock = p->p_pid; ipc.ip_data = u.u_ar0[R0]; ipc.ip_addr = u.u_arg[1] & ~03; /***/ ipc.ip_req = u.u_arg[2]; p->p_flag =& ~SWTED; setrun(p); while (ipc.ip_req > 0) sleep(&ipc, IPCPRI); u.u_ar0[R0] = ipc.ip_data; if (ipc.ip_req < 0) : error: ipc.ip_req = -1; } return(0); } != NULL) { bdwrite(bp); nb = bp->b_blkno; ip->i_addr[bn] = nb; ip->i_flag =| IUPD; } rablock = 0; if (bn<7) rablock = ip->i_addr[bn+1]; return(nb); } /* * large file algorithm */ large: i = bn>>7; /***/ if(i > 7) /***/ i = 7; if((nb=ip->i_addr[i]) == 0) { ip->i_flag =| IUPD; if ((bp = alloc(d)) == NULL) return(NULL); ip->i_addr[i] = bp->b_blkno; } else bp = bread(d, nb); bap = bp->b_addr; /* * "huge" fetch of double indirect block */ if(i == or; placed in * illegal entries in the bdevsw and cdevsw tables. */ nodev() { u.u_error = ENODEV; } /* * Null routine; placed in insignificant entries * in the bdevsw and cdevsw tables. */ nulldev() { } /* * copy count words from from to to. */ bcopy(from, to, count) int *from, *to; { register *a, *b, c; a = from; b = to; c = count; do *b++ = *a++; while(--c); } return(n); } return(0); } /* * Enter the tracing STOP state. * In this state, the parent is * informed and the process is able to * receive commands from the parent. */ stop() { register struct proc *pp, *cp; loop: cp = u.u_procp; if (cp->p_ppid!= 1) for (pp = &proc[0]; pp < &proc[NPROC]; pp++) if (pp->p_pid == cp->p_ppid) { wakeup(pp); cp->p_stat = SSTOP; swtch(); if ((cp->p_flag&STRC)==0 || procxmt()) return; goto loop; } exit(); } /* * Perform the action specifiede&IFMT) == 0 && u.u_uid == u.u_ruid) { itrunc(ip); u.u_offset[0] = 0; u.u_offset[1] = 0; u.u_base = &u; u.u_count = USIZE*256; /***/ u.u_segflg = 1; writei(ip); s = u.u_procp->p_size - USIZE; estabur(0, s, 0, 0); u.u_base = 0; u.u_count = s*256; /***/ u.u_segflg = 0; writei(ip); } iput(ip); return(u.u_error==0); } /* * grow the stack to include the SP * true return if successful. */ grow(sp) char *sp; { register a, si, i; /*** doesn't do anything until we figure o u.u_error = EIO; ipc.ip_lock = 0; wakeup(&ipc); } /* * Code that the child process * executes to implement the command * of the parent process in tracing. */ procxmt() { register int i; register int *p; if (ipc.ip_lock != u.u_procp->p_pid) return(0); i = ipc.ip_req; ipc.ip_req = 0; wakeup(&ipc); switch (i) { /* read user I */ case 1: if (fuibyte(ipc.ip_addr) == -1) goto error; ipc.ip_data = fuiword(ipc.ip_addr); break; /* read user D */ case 2: if (fubyte(ipc.ip_addr) == # /* */ #include "param.h" #include "inode.h" #include "user.h" #include "buf.h" #include "conf.h" #include "systm.h" /* * Read the file corresponding to * the inode pointed at by the argument. * The actual read arguments are found * in the variables: * u_base core address for destination * u_offset byte offset in file * u_count number of bytes to read * u_segflg read to kernel/user */ readi(aip) struct inode *aip; { int *bp; int lbn, bn, on; register dn, n; register struct inode *ip; ip7) { i = ((bn>>7)&0177) - 7; /***/ if((nb=bap[i]) == 0) { if((nbp = alloc(d)) == NULL) { brelse(bp); return(NULL); } bap[i] = nbp->b_blkno; bdwrite(bp); } else { brelse(bp); nbp = bread(d, nb); } bp = nbp; bap = bp->b_addr; } /* * normal indirect fetch */ i = bn & 0177; /***/ if((nb=bap[i]) == 0 && (nbp = alloc(d)) != NULL) { nb = nbp->b_blkno; bap[i] = nb; bdwrite(nbp); bdwrite(bp); } else brelse(bp); rablock = 0; if(i < 127) /***/ rablock# /* */ #include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #include "inode.h" #include "reg.h" /* * Priority for tracing */ #define IPCPRI (-1) /* * Structure to access an array of integers. */ struct { int inta[]; }; /* * Tracing variables. * Used to pass trace command from * parent to child being traced. * This data base cannot be * shared and is locked * per user. */ struct { int ip_lock; int ip_req; int ip_addr; int ip_data; } ipc; /* * Send the specified sid by * the current signal. * The usual sequence is: * if(issig()) * psig(); */ psig() { register n, p, asp, aps; /***/ register *rp; rp = u.u_procp; n = rp->p_sig; rp->p_sig = 0; if((p=u.u_signal[n]) != 0) { u.u_error = 0; /***/ if(n != SIGSYS && n != SIGINS && n != SIGTRC) u.u_signal[n] = 0; /***/ aps = u.u_ar0[RPS]; /***/ asp = u.u_ar0[RSP]; /***/ if (u.u_nostack) { /***/ /* No user stack -- set up stack for signal routine */ /***/ u.u_nostack = 0; /***/ aps =| (1<<31); /***/-1) goto error; ipc.ip_data = fuword(ipc.ip_addr); break; /* read u */ case 3: i = ipc.ip_addr; if (i<0 || i >= (USIZE<<8)) /***/ goto error; ipc.ip_data = u.inta[i>>2]; /***/ break; /* write user I (for now, always an error) */ case 4: if (suiword(ipc.ip_addr, 0) < 0) goto error; suiword(ipc.ip_addr, ipc.ip_data); break; /* write user D */ case 5: if (suword(ipc.ip_addr, 0) < 0) goto error; suword(ipc.ip_addr, ipc.ip_data); break; /* write u */ case 6: p = = aip; if(u.u_count == 0) return; ip->i_flag =| IACC; if((ip->i_mode&IFMT) == IFCHR) { (*cdevsw[ip->i_addr[0].d_major].d_read)(ip->i_addr[0]); return; } do { lbn = bn = lshift(u.u_offset, -9); on = u.u_offset[1] & 0777; n = min(512-on, u.u_count); if((ip->i_mode&IFMT) != IFBLK) { dn = dpcmp(ip->i_size0&0377, ip->i_size1, u.u_offset[0], u.u_offset[1]); if(dn <= 0) return; n = min(n, dn); if ((bn = bmap(ip, lbn)) == 0) return; dn = ip->i_dev; } else { dn = ip->i_addr[0]; rablock = bn+1; } if (ip->i_lastr+1 == lbn) bp = breada(dn, bn, rablock); else bp = bread(dn, bn); ip->i_lastr = lbn; iomove(bp, on, n, B_READ); brelse(bp); } while(u.u_error==0 && u.u_count!=0); } /* * Write the file corresponding to * the inode pointed at by the argument. * The actual write arguments are found * in the variables: * u_base core address for source * u_offset byte offset in file * u_count number of bytes to write * u_segflg write to kernel/userlanguage copyin/copyout * is called. * If not, its done byte-by-byte with * cpass and passc. */ iomove(bp, o, an, flag) struct buf *bp; { register char *cp; register int n, t; n = an; cp = bp->b_addr + o; if(u.u_segflg==0 && ((n | cp | u.u_base)&03)==0) { /***/ if (flag==B_WRITE) cp = copyin(u.u_base, cp, n); else cp = copyout(cp, u.u_base, n); if (cp) { u.u_error = EFAULT; return; } u.u_base =+ n; dpadd(u.u_offset, n); u.u_count =- n; return; } if (flag==B_WRITE) { p = pbuff; do { *p++ = hexdigits[a%b]; } while (a =/ b); do { putchar(*--p); } while (p > pbuff); } /* * Print a character on console. * Attempts to save and restore device * status. * If the switches are 0, all * printing is inhibited. */ /*** note: this routine has been rewritten in assembler ***/ /* * Panic is called on unresolvable * fatal errors. * It syncs, prints "panic: mesg" and * then loops. */ panic(s) char *s; { panicstr = s; update(); printf("panic: %s\n", s); spl(7);pe() { register *ip, *rf, *wf; int r; ip = ialloc(rootdev); if(ip == NULL) return; rf = falloc(); if(rf == NULL) { iput(ip); return; } r = u.u_ar0[R0]; wf = falloc(); if(wf == NULL) { rf->f_count = 0; u.u_ofile[r] = NULL; iput(ip); return; } u.u_ar0[R1] = u.u_ar0[R0]; u.u_ar0[R0] = r; wf->f_flag = FWRITE|FPIPE; wf->f_inode = ip; rf->f_flag = FREAD|FPIPE; rf->f_inode = ip; ip->i_count = 2; ip->i_flag = IACC|IUPD; ip->i_mode = IALLOC; } /* * Read call directed to a pipe. nt = min(c, PIPSIZ-u.u_offset[1]); c =- u.u_count; writei(ip); prele(ip); if(ip->i_mode&IREAD) { ip->i_mode =& ~IREAD; wakeup(ip+2); } goto loop; } /* * Lock a pipe. * If its already locked, * set the WANT bit and sleep. */ plock(ip) int *ip; { register *rp; rp = ip; while(rp->i_flag&ILOCK) { rp->i_flag =| IWANT; sleep(rp, PPIPE); } rp->i_flag =| ILOCK; } /* * Unlock a pipe. * If WANT bit is on, * wakeup. * This routine is also used * to unlock inodes in general. */ prele(ip)# #include "param.h" #include "inode.h" #include "user.h" #include "systm.h" #include "buf.h" /* * Convert a pathname into a pointer to * an inode. Note that the inode is locked. * * func = function called to get next char of name * &uchar if name is in user space * &schar if name is in system space * flag = 0 if name is sought * 1 if name is to be created * 2 if name is to be deleted */ namei(func, flag) int (*func)(); { register struct inode *dp; register c; register char *cp, *cp1; /***/ */ writei(aip) struct inode *aip; { int *bp; int n, on; register dn, bn; register struct inode *ip; ip = aip; ip->i_flag =| IACC|IUPD; if((ip->i_mode&IFMT) == IFCHR) { (*cdevsw[ip->i_addr[0].d_major].d_write)(ip->i_addr[0]); return; } if (u.u_count == 0) return; do { bn = lshift(u.u_offset, -9); on = u.u_offset[1] & 0777; n = min(512-on, u.u_count); if((ip->i_mode&IFMT) != IFBLK) { if ((bn = bmap(ip, bn)) == 0) return; dn = ip->i_dev; } else dn = ip->i_addr[0]; i while(n--) { if ((t = cpass()) < 0) return; *cp++ = t; } } else while (n--) if(passc(*cp++) < 0) return; } /***/ for(;;) idle(); } /* * prdev prints a warning message of the * form "mesg on dev x/y". * x and y are the major and minor parts of * the device argument. */ prdev(str, dev) { printf("%s on dev %l/%l\n", str, dev.d_major, dev.d_minor); } /* * deverr prints a diagnostic from * a device driver. * It prints the device, block number, * and a hex word (usually some error * status register) passed as argument. */ deverror(bp, o1, o2) int *bp; { register *rbp; rbp = bp; prdev("err", rb*/ readp(fp) int *fp; { register *rp, *ip; rp = fp; ip = rp->f_inode; loop: /* * Very conservative locking. */ plock(ip); /* * If the head (read) has caught up with * the tail (write), reset both to 0. */ if(rp->f_offset[1] == ip->i_size1) { if(rp->f_offset[1] != 0) { rp->f_offset[1] = 0; ip->i_size1 = 0; if(ip->i_mode&IWRITE) { ip->i_mode =& ~IWRITE; wakeup(ip+1); } } /* * If there are not both reader and * writer active, return without * satisfying int *ip; { register *rp; rp = ip; rp->i_flag =& ~ILOCK; if(rp->i_flag&IWANT) { rp->i_flag =& ~IWANT; wakeup(rp); } } int eo, *bp; /* * If name starts with '/' start from * root; otherwise start from current dir. */ dp = u.u_cdir; if((c=(*func)()) == '/') dp = rootdir; iget(dp->i_dev, dp->i_number); while(c == '/') c = (*func)(); if(c == '\0' && flag != 0) { u.u_error = ENOENT; goto out; } cloop: /* * Here dp contains pointer * to last component matched. */ if(u.u_error) goto out; if(c == '\0') return(dp); /* * If there is another component, * dp must be a directory and * must f(n == 512) bp = getblk(dn, bn); else bp = bread(dn, bn); iomove(bp, on, n, B_WRITE); if(u.u_error != 0) brelse(bp); else if ((u.u_offset[1]&0777)==0) bawrite(bp); else bdwrite(bp); if(dpcmp(ip->i_size0&0377, ip->i_size1, u.u_offset[0], u.u_offset[1]) < 0 && (ip->i_mode&(IFBLK&IFCHR)) == 0) { ip->i_size0 = u.u_offset[0]; ip->i_size1 = u.u_offset[1]; } ip->i_flag =| IUPD; } while(u.u_error==0 && u.u_count!=0); } /* * Return the logical maximum * of the 2 argument# /* */ #include "param.h" #include "seg.h" #include "buf.h" #include "conf.h" /* * In case console is off, * panicstr contains argument to last * call to panic. */ char *panicstr; /* * Scaled down version of C Library printf. * Only %s %l %d (==%l) %x are recognized. * Used to print diagnostic information * directly on console tty. * Since it is not interrupt driven, * all system activities are pretty much * suspended. * Printf should not be used for chit-chat. */ printf(fmt,x1,x2,x3,x4,xp->b_dev); printf("bn %l st %x %x\n", rbp->b_blkno, o1, o2); } read. */ prele(ip); if(ip->i_count < 2) return; ip->i_mode =| IREAD; sleep(ip+2, PPIPE); goto loop; } /* * Read and return */ u.u_offset[0] = 0; u.u_offset[1] = rp->f_offset[1]; readi(ip); rp->f_offset[1] = u.u_offset[1]; prele(ip); } /* * Write call directed to a pipe. */ writep(fp) { register *rp, *ip, c; rp = fp; ip = rp->f_inode; c = u.u_count; loop: /* * If all done, return. */ plock(ip); if(c == 0) { prele(ip); u.u_count = 0; return; } /* * I/* */ char partab[] { 0001,0201,0201,0001,0201,0001,0001,0201, 0202,0004,0003,0205,0005,0206,0201,0001, 0201,0001,0001,0201,0001,0201,0201,0001, 0001,0201,0201,0001,0201,0001,0001,0201, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,have x permission. */ if((dp->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; goto out; } if(access(dp, IEXEC)) goto out; /* * Gather up name into * users' dir buffer. */ cp = &u.u_dbuf[0]; while(c!='/' && c!='\0' && u.u_error==0) { if(cp < &u.u_dbuf[DIRSIZ]) *cp++ = c; c = (*func)(); } while(cp < &u.u_dbuf[DIRSIZ]) *cp++ = '\0'; while(c == '/') c = (*func)(); if(u.u_error) goto out; /* * Set up to search a directory. */ u.u_offset[1] = 0; u.u_offset[0] = 0; us. */ max(a, b) char *a, *b; { if(a > b) return(a); return(b); } /* * Return the logical minimum * of the 2 arguments. */ min(a, b) char *a, *b; { if(a < b) return(a); return(b); } /* * Move 'an' bytes at byte location * &bp->b_addr[o] to/from (flag) the * user/kernel (u.segflg) area starting at u.base. * Update all the arguments by the number * of bytes moved. * * There are 2 algorithms, * if source address, dest address and count * are all even in a user copy, * then the machine 5,x6,x7,x8,x9,xa,xb,xc) char fmt[]; { register char *s; register *adx, c; adx = &x1; loop: while((c = *fmt++) != '%') { if(c == '\0') return; putchar(c); } c = *fmt++; if(c == 'd' || c == 'l' || c == 'x') printn(*adx, c=='x'? 16: 10); if(c == 's') { s = *adx; while(c = *s++) putchar(c); } adx++; goto loop; } /* * Print an unsigned integer in base b. */ printn(n, b) { char pbuff[16]; register char *p; register unsigned a; static char hexdigits[] "0123456789ABCDEF"; a = n;# /* */ #include "param.h" #include "systm.h" #include "user.h" #include "inode.h" #include "file.h" #include "reg.h" /* * Max allowable buffering per pipe. * This is also the max size of the * file created to implement the pipe. * If this size is bigger than 4096, * pipes will be implemented in LARG * files, which is probably not good. */ #define PIPSIZ 4096 /* * The sys-pipe entry. * Allocate an inode on the root device. * Allocate 2 file structures. * Put it all together with flags. */ pif there are not both read and * write sides of the pipe active, * return error and signal too. */ if(ip->i_count < 2) { prele(ip); u.u_error = EPIPE; psignal(u.u_procp, SIGPIPE); return; } /* * If the pipe is full, * wait for reads to deplete * and truncate it. */ if(ip->i_size1 == PIPSIZ) { ip->i_mode =| IWRITE; prele(ip); sleep(ip+1, PPIPE); goto loop; } /* * Write what is possible and * loop back. */ u.u_offset[0] = 0; u.u_offset[1] = ip->i_size1; u.u_cou0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0201 }; .u_segflg = 1; eo = 0; u.u_count = ldiv(dp->i_size1, DIRSIZ+2); bp = NULL; eloop: /* * If at the end of the directory, * the search failed. Report what * is appropriate as per flag. */ if(u.u_count == 0) { if(bp != NULL) brelse(bp); if(flag==1 && c=='\0') { if(access(dp, IWRITE)) goto out; u.u_pdir = dp; if(eo) u.u_offset[1] = eo-DIRSIZ-2; else dp->i_flag =| IUPD; return(NULL); } u.u_error = ENOENT; goto out; } /* * If offset is on a block boundary, * read the next directory block. * Release previous if it exists. */ if((u.u_offset[1]&0777) == 0) { if(bp != NULL) brelse(bp); bp = bread(dp->i_dev, bmap(dp, ldiv(u.u_offset[1], 512))); } /* * Note first empty directory slot * in eo for possible creat. * String compare the directory entry * and the current component. * If they do not match, go back to eloop. */ /*** bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2); ***/ cp1 = bp->b_addr+(u.u_offset[1]&0777)d_minor == 1 && lraddr(&addr, kisa)) || addr >= memtop) break; } while(u.u_error==0 && passc(*addr) >= 0); } mmwrite(dev) { char *addr; register c; if(dev.d_minor == 2) { c = u.u_count; u.u_count = 0; u.u_base =+ c; dpadd(u.u_offset, c); return; } for (;;) { addr = u.u_offset[1]; if ((c=cpass())<0 || u.u_error!=0) break; if ((dev.d_minor == 1 && lraddr(&addr, kisa)) || addr >= memtop) break; *addr = c; } } bp++; (bp-1)->m_addr = bp->m_addr; (bp-1)->m_size = bp->m_size; } } } else { if (a+size == bp->m_addr && bp->m_size) { bp->m_addr =- size; bp->m_size =+ size; } else if (size) do { t = bp->m_addr; bp->m_addr = a; a = t; t = bp->m_size; bp->m_size = size; bp++; } while (size = t); } } ->m_inodp == p) { dev = ip->m_dev; ino = ROOTINO; goto loop; } panic("no imt"); } p->i_count++; p->i_flag =| ILOCK; return(p); } if(ip==NULL && p->i_count==0) ip = p; } if((p=ip) == NULL) { printf("Inode table overflow\n"); u.u_error = ENFILE; return(NULL); } p->i_dev = dev; p->i_number = ino; p->i_flag = ILOCK; p->i_count++; p->i_lastr = -1; ip = bread(dev, ldiv(ino+15,8)); /***/ /* * Check I/O errors */ if (ip->b_flags&B_ERROR) { brelse(ip)much longer * than FIFO. */ itrunc(ip) int *ip; { register *rp, *bp, *cp; int *dp, *ep; rp = ip; if((rp->i_mode&(IFCHR&IFBLK)) != 0) return; for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--) if(*ip) { if((rp->i_mode&ILARG) != 0) { bp = bread(rp->i_dev, *ip); for(cp = bp->b_addr+512; cp >= bp->b_addr; cp--) if(*cp) { if(ip == &rp->i_addr[7]) { dp = bread(rp->i_dev, *cp); for(ep = dp->b_addr+512; ep >= dp->b_addr; ep--) if(*ep) free(rp->i_dev, *ep); brelsfilsys.hino.hinode.hproc.hreg.hsystm.htext.huser.hfio.ciget.cmalloc.cmem.cnami.cpartab.cpipe.cprf.crdwri.csig.csubr.cselch.hRsys1.cQsys2.cPsys3.cOsys4.cNsysent.cMtext.cLtrap.cKtty.cJselch.cREAD_MElp.cXrun; /***/ for (cp = &u.u_dent.u_name[-2]; cp < &u.u_dent.u_name[DIRSIZ];) /***/ *cp++ = *cp1++; /***/ u.u_offset[1] =+ DIRSIZ+2; u.u_count--; if(u.u_dent.u_ino == 0) { if(eo == 0) eo = u.u_offset[1]; goto eloop; } for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++) if(*cp != cp[u.u_dent.u_name - u.u_dbuf]) goto eloop; /* * Here a component matched in a directory. * If there is more pathname, go back to * cloop, otherwise return. */ if(bp != NULL) brelse(bp); if(flag==2 &# /* */ #include "param.h" /* * Structure of the coremap and swapmap * arrays. Consists of non-zero count * and base address of that many * contiguous units. *** (The coremap unit is 256 bytes, *** * the swapmap unit is 512 bytes) * The addresses are increasing and * the list is terminated with the * first zero count. */ struct map { char *m_size; char *m_addr; }; int freemem; /*** amount of core used ***/ extern struct map coremap; /***/ /* * Allocate size units from the given * map. Re  ; iput(p); return(NULL); } ip1 = ip->b_addr + 64*lrem(ino+15, 8); /***/ ip2 = &p->i_mode; while(ip2 < &p->i_addr[8]) *ip2++ = *ip1++; brelse(ip); return(p); } /* * Decrement reference count of * an inode structure. * On the last reference, * write the inode out and if necessary, * truncate and deallocate the file. */ iput(p) struct inode *p; { register *rp; rp = p; if(rp->i_count == 1) { rp->i_flag =| ILOCK; if(rp->i_nlink <= 0) { itrunc(rp); rp->i_mode = 0; ifree(rp->i_e(dp); } free(rp->i_dev, *cp); } brelse(bp); } free(rp->i_dev, *ip); *ip = 0; } rp->i_mode =& ~ILARG; rp->i_size0 = 0; rp->i_size1 = 0; rp->i_flag =| IUPD; } /* * Make a new file. */ maknode(mode) { register *ip; ip = ialloc(u.u_pdir->i_dev); if (ip==NULL) return(NULL); ip->i_flag =| IACC|IUPD; ip->i_mode = mode|IALLOC; ip->i_nlink = 1; ip->i_uid = u.u_uid; ip->i_gid = u.u_gid; wdir(ip); return(ip); } /* * Write a directory entry with * parameters left as side eff1msm.cUdsk.c_olddump.ocli.omsm.oolow.ocli.oclock.oconf.odata.odsk.odsp.odump.ofio.ofptrap.oiget.olong.olow.olp.omain.omalloc.omem.omsm.omt.onami.opartab.opipe.oprf.ordwri.osdev.oselch.osig.o& c=='\0') { if(access(dp, IWRITE)) goto out; return(dp); } bp = dp->i_dev; iput(dp); dp = iget(bp, u.u_dent.u_ino); if(dp == NULL) return(NULL); goto cloop; out: iput(dp); return(NULL); } /* * Return the next character from the * kernel string pointed at by dirp. */ schar() { return(*u.u_dirp++ & 0377); } /* * Return the next character from the * user string pointed at by dirp. */ uchar() { register c; c = fubyte(u.u_dirp++); if(c == -1) u.u_error = EFAULT; return(c); } turn the base of the allocated * space. * Algorithm is first fit. */ malloc(mp, size) struct map *mp; { register int a; register struct map *bp; for (bp = mp; bp->m_size; bp++) { if (bp->m_size >= size) { a = bp->m_addr; bp->m_addr =+ size; if ((bp->m_size =- size) == 0) do { bp++; (bp-1)->m_addr = bp->m_addr; } while ((bp-1)->m_size = bp->m_size); if (mp == &coremap) /***/ freemem =+ size; /***/ return(a); } } return(0); } /* * Free the previously alloca# #include "param.h" #include "systm.h" #include "user.h" #include "inode.h" #include "filsys.h" #include "conf.h" #include "buf.h" /* * Look up an inode by device,inumber. * If it is in core (in the inode structure), * honor the locking protocol. * If it is not in core, read it in from the * specified device. * If the inode is mounted on, perform * the indicated indirection. * In all cases, a pointer to a locked * inode structure is returned. * * printf warning: no inodes -- if the inode * strdev, rp->i_number); } iupdat(rp, time); prele(rp); rp->i_flag = 0; rp->i_number = 0; } rp->i_count--; prele(rp); } /* * Check accessed and update flags on * an inode structure. * If either is on, update the inode * with the corresponding dates * set to the argument tm. */ iupdat(p, tm) int *p; int *tm; { register *ip1, *ip2, *rp; int *bp, i; rp = p; if((rp->i_flag&(IUPD|IACC)) != 0) { if(getfs(rp->i_dev)->s_ronly) return; i = rp->i_number+15; /***/ bp = bread(rp->i_dev,ldects * to a call to namei. */ wdir(ip) int *ip; { register char *cp1, *cp2; u.u_dent.u_ino = ip->i_number; cp1 = &u.u_dent.u_name[0]; for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];) *cp1++ = *cp2++; u.u_count = DIRSIZ+2; u.u_segflg = 1; u.u_base = &u.u_dent.u_name[-2]; /***/ writei(u.u_pdir); iput(u.u_pdir); } slp.ostart.osubr.osys.otsys1.osys2.osys3.osys4.osysent.otext.otrace.otrap.otty.ovdu.o# /* * Memory special file * minor device 0 is physical memory * minor device 1 is kernel memory * minor device 2 is EOF/BITBUCKET */ /*** Rewritten for Interdata 7-8/32 *** Code is made simpler (and less portable!) by the assumption *** that all physical memory is contiguous and directly addressable. ***/ #include "param.h" #include "user.h" #include "conf.h" #include "seg.h" #include "systm.h" mmread(dev) { char *addr; if(dev.d_minor == 2) return; do { addr = u.u_offset[1]; if ((dev.ted space aa * of size units into the specified map. * Sort aa into map and combine on * one or both ends if possible. */ mfree(mp, size, aa) struct map *mp; { register struct map *bp; register int t; register int a; a = aa; if (mp == &coremap) /***/ freemem =- size; /***/ for (bp = mp; bp->m_addr<=a && bp->m_size!=0; bp++); if (bp>mp && (bp-1)->m_addr+(bp-1)->m_size == a) { (bp-1)->m_size =+ size; if (a+size == bp->m_addr) { (bp-1)->m_size =+ bp->m_size; while (bp->m_size) { ucture is full * panic: no imt -- if the mounted file * system is not in the mount table. * "cannot happen" */ iget(dev, ino) { register struct inode *p; register *ip2; int *ip1; register struct mount *ip; loop: ip = NULL; for(p = &inode[0]; p < &inode[NINODE]; p++) { if(dev==p->i_dev && ino==p->i_number) { if((p->i_flag&ILOCK) != 0) { p->i_flag =| IWANT; sleep(p, PINOD); goto loop; } if((p->i_flag&IMOUNT) != 0) { for(ip = &mount[0]; ip < &mount[NMOUNT]; ip++) if(ipiv(i,8)); /***/ ip1 = bp->b_addr + 64*lrem(i, 8); /***/ ip2 = &rp->i_mode; while(ip2 < &rp->i_addr[8]) *ip1++ = *ip2++; if(rp->i_flag&IACC) { *ip1++ = time[0]; *ip1++ = time[1]; } else ip1 =+ 2; if(rp->i_flag&IUPD) { *ip1++ = *tm++; *ip1++ = *tm; } bwrite(bp); } } /* * Free all the disk blocks associated * with the specified inode structure. * The blocks of the file are removed * in reverse order. This FILO * algorithm will tend to maintain * a contiguous free list ....sys.cconf.csdev.sparam.hslp.cconf.hseg.htty.htrace.slong.sfptrap.slow.sprintmain.c"dsk.cstart.sTmt.cdsp.cSunix.abuf.hbio.cvdu.ccli.clow.oodump.salloc.ccio.cfile.hclock.cdata.crm -f /tmp/* /usr/lpd/lock /etc/mount /dev/df0 /usr/source al /etc/mtab /etc/update : loop if $1x = x exit ld -x -r $1 mv a.out $1 shift goto loop 76 > |077 ? | |100 @ |101 A |102 B |103 C |104 D |105 E |106 F |107 G | |110 H |111 I |112 J |113 K |114 L |115 M |116 N |117 O | |120 P |121 Q |122 R |123 S |124 T |125 U |126 V |127 W | |130 X |131 Y |132 Z |133 [ |134 \ |135 ] |136 ^ |137 _ | |140 ` |141 a |142 b |143 c |144 d |145 e |146 f |147 g | |150 h |151 i |152 j |153 k |154 l |155 m |156 n |157 o | |160 p |161 q |162 r |163 s |164 t |165 u |166 v |167 w | |170 x |171 y |172 z |173 { |1D'xXP PA@,PA@tXp(Ї%Q(C0JX,&P,X -B00&PA@P@!(@ PA@%Q($Q,X(#@5PA$PX,XPA@`CX,XP@XPA$PX,&P,XPA@`CX,XP@fPA't$P$PPA@&t'tP@ PPA@&t#8@xPAXX@Y@ #@PA<'t$P PPA@&t't$PX@PPA@&t$'tP@ PPA@&tP@ %XP@ XP@ X !P@ %%Illegal block numberUsage: mkboot [ - baddr ] file devCan't open %sCan't write on %sSuperblock read errorAre you trying to clobber the file system??Write error %dRead error %dVolume label write error %d 0123456789ABCDEFCDEFLOSXcdeflosx::::z....8proto?fixup9extractt.rMAIN.fa.outl.outMAIN.oroot::0:0::/: rm::1:0::/usr/rm: mail::8:1::/usr/mail:NO_SHELL bin::0:root,rm other::1: 74 | |175 } |176 ~ |177 del| C @'tP@ PPA@&t C0X@ P@PA&C CX@ P@PA|X@P@  P@ 't$P$PPA@&t'tP@ PPA@&tC0X@ P@PA юp(p(ЇX,PX(PA@|$ PA@ $PA@tюp(p(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(C@"p(Ї,X( C0ɠ%#8PA@ C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ .......G008016024032040048056064072080088096104112120128 ....asciitabs &CP@ $ɠ.B0,&ӡɠ9B ɠ0B$ CP@ 'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C'@  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb 'xX(P X@ PPPA@&x #3&"$P@ CC@ P@ H&Y 3XD X@ #:Y@ #&X@  [@ X0B0 &# PA@ " }$H z0|Ȁ(A$p$&Ar$X&XHuӕ͐ՀAXPP`VH`!3&A>uӷ&q v "6p z5$Ȱ@ȰCPN`h'(A2$Ƞ0'=PP0-*P`$!; 0"!0"! root 0!r = ENXIO; /* yes, return error */ return; } tp = &cli[dev.d_minor]; /* get tty struct for terminal */ tp->t_dev = dev; /* set device number in tty struct */ if ((tp->t_state & ISOPEN) == 0) { tp->t_state = ISOPEN | CARR_ON | SSTART; if (tp->t_flags == 0) tp->t_flags = XTABS | LCASE | CRMOD | ECHO; tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_addr = &clistart; /* special output start routine */ cliparam(tp); /* enable read and set parms */ trace(0x1000,"cliopen rd:",rd|000 nul|001 soh|002 stx|003 etx|004 eot|005 enq|006 ack|007 bel| |010 bs |011 ht |012 nl |013 vt |014 np |015 cr |016 so |017 si | |020 dle|021 dc1|022 dc2|023 dc3|024 dc4|025 nak|026 syn|027 etb| |030 can|031 em |032 sub|033 esc|034 fs |035 gs |036 rs |037 us | |040 sp |041 ! |042 " |043 # |044 $ |045 % |046 & |047 ' | |050 ( |051 ) |052 * |053 + |054 , |055 - |056 . |057 / | |060 0 |061 1 |062 2 |063 3 |064 4 |065 5 |066 6 |067 7 | |070 8 |071 9 |072 : |073 ; |074 < |075 = |0....lockcfa00268dfa00268C P&A@ "  &# PA@ " X(#юp(p,Ї X@ B p_ttyp == 0) /* give a process to the tty */ u.u_procp->p_ttyp = tp; } /* * close routine: * - called only when last process using terminal releases it */ cliclose (dev) { register struct tty *tp; tp = &cli[dev.d_minor]; /* find tty struct for terminal */ wflushtty(tp); /* flush queues */ tp->t_state = 0; /* clear status */ oc(cliaddr[dev.d_minor], DISABLE | READ | BLOCK); /* disable read */ } /* * read, write, stty, gtty routines: * - call standard tty routines */ cliread(dev) { ttread(&cli[dev.d_minor]); } cliwrite(dev) { ttwrite(&cli[dev.d_minor]); } clisgtty(dev, v) { register struct tty *tp; tp = &cli[dev.d_minor]; ttystty(tp, v); if ( (v==0) && !(tp->t_state & BUSY)) /* if read and if ECHO, set hardware echo */ cliparam(tp); } /* * set device parameters * enable read; if ECHO, enable hardware echo. * */ cliparam(tp) struct tty *tp; { /*** oc(cliaddr[tp->t_dev.d_minor], ENABLE | READ | ((tp->t_flag & ECHO) ? U/5!'(.4:;* clistrto(tp); if (tp->t_outq.c_cc <= TTLOWAT && (tp->t_state&ASLEEP)) { tp->t_state =& ~ASLEEP; wakeup(&tp->t_outq); } } } else /* read complete interrupt */ { trace(0x1000, "rint", stat); c = rd(addr) & 0177; trace(0x1000, "c = ", c); ttyinput(c, tp); } trace(0x1000,"int exit ss:",ss(addr)); trace(0x1000,"t_state",tp->t_state); trace(0x1000,"addr",addr); } { register c; while ((c=cpass()) >= 0) lpcanon(c); } /* * lpcanon - character transformations */ lpcanon(ac) { register char c; register char *p; c = ac; if (c == '_') c =| 0x80; /* * Interdata line printer i/face * turns x'5f' into x'3c' ..... * * But it isn't smart enough to * regognize x'df', fortunately. */ if (lp.flag & RAW) { lpoutput(c); return; } if (lp.flag & LCASE) { /* Uppercase-only printer */ if (c>='a' at) { trace(02<<8,"lpint",stat); /*** if(stat & DU) printf("\nline printer offline\n"); else if (stat & NO_PAPER) printf("\nline printer paper out\n"); else { ***/ if(!(stat & (DU|NO_PAPER))) { lpstart(); if(lp.outq.c_cc <= LPLWAT && lp.state & ASLEEP) { trace(04<<8,"lpwakeup",lp.outq.c_cc); lp.state =& ~ASLEEP; wakeup(&lp); } } } /* * write a character to line printer */ lpoutput(c) { trace(02<<8,"lpoutput",c); spl(4); while(lp.outq.c_cc >= LPHWAT) { lp.state =| ASLEEP trace(020<<16, "interrupt", dev); trace(020<<16, "status", stat); if (!(bp = msmtab.d_actf) || !msmseekf) return; msmseekf = 0; if (stat & (BSY|UNS|UNREADY|SINC|OFFL)) { msmerror(bp, stat, msmdrive); return; } if (bp->b_flags & B_READ) { scmd = READ_GO; ccmd = READ|ENABLE; } else { scmd = GO; ccmd = WRITE|ENABLE; } trace(010<<16, "mcmd", ccmd); trace(010<<16, "head", msmhead); trace(010<<16, "sector", msmsector); oc(selchaddr[NSELCH], STOP); trace(010<<16, "bufstart", msmsaNBLOCK : BLOCK)); ***/ oc(cliaddr[tp->t_dev.d_minor], ENABLE | READ | BLOCK); return; } /* * * When the interface changes from read to write, an interrupt * is generated. This is where we enable the transmit side. * If busy is set , then a write is in progress and there is * nothing to do. * */ clistart(atp) struct tty *atp; { register struct tty *tp; tp = atp; if ( !(tp->t_state & BUSY)) { tp->t_state =| (WINIT | BUSY); /* set winit flag */ oc(cliaddr[tp->t_dev.d_minor], ENABLE | WRITE |# /* * Current Loop Interface Driver * */ #include "param.h" #include "conf.h" #include "proc.h" #include "tty.h" #include "user.h" #define NCLI 1 /* number of terminals */ char cliaddr[NCLI] { /* cli addresses */ 02 }; struct tty cli[NCLI]; /* common tty structure */ #define devmap(addr) &cli[addr-02] /* map phys addr => tty */ /* Current Loop Interface Command and Status Bits */ /* commands */ #define DISABLE 0200 #define ENABLE 0100 #define UNBLOCK 0040 #define BLOCK 0020 #define WRITE 001# /* * Line printer driver */ #include "param.h" #include "conf.h" #include "user.h" #include "tty.h" /* Configuration */ #define LPPRI 75 /* line printer wakeup priority */ #define LPLWAT 70 /* line printer low water mark */ #define LPHWAT 150 /* line printer high water mark */ #define LPWIDTH 131 /* page width (not 132, as lp auto prints on 132nd char */ #define LPDEPTH 60 /* lines per page */ int lpaddr 0x62; /* printer address */ /* Printer status & commands */ #define ENABLE 0x40&& c<='z') c =+ 'A'-'a'; else { p = "({)}!|^~'`"; while (*p++) if (c == *p++) { lpcanon(p[-2]); lp.ccc--; c = '-'; break; } } } switch(c&0x7f) { case '\t': lp.ccc = (lp.ccc + 8) & ~7; return; case FORM: case '\n': if(lp.mcc != 0 || lp.mlc != 0 || lp.flag & P_WASTE) { if(lp.mcc) { lpoutput('\r'); /* cause line to print */ } lp.mlc++; if(lp.mlc > lp.mxl && lp.mxl) c = FORM; lpoutput(c); if (c == FORM) lp.mlc = 0; lp.mcc =06<+17=,8d); trace(010<<16, "bufend", msmead); wdh(selchaddr[NSELCH], msmsad); wdh(selchaddr[NSELCH], msmead); wh(msmdrive, msmhead); oc(msmdrive, SETHEAD|DISARM); while ((ss(msmcntl)&IDLE) == 0) ; wd(msmcntl, msmsector); wh(msmcntl, (msmhead<<10)+msmcyl); wh(msmdrive, msmhead); oc(msmdrive, SETHEAD|DISARM); while ((ss(msmcntl)&IDLE) == 0) ; oc(msmcntl, ccmd); oc(selchaddr[NSELCH], scmd); } /* * selch interrupt routine * -selch interrupt will be followed by a controller interrupt * ( nothing to BLOCK ); /* enable write */ } } /* * second level output start routine * * This routine is called from cliint on write interrupt * to send a character. * */ clistrto(atp) struct tty *atp; { int ttrstrt(); register struct tty *tp; register c; tp = atp; /* get character to output */ c = getc(&tp->t_outq); if (c < 0) /* no more chars on outq, start reading */ { cliparam(tp); /* enable read */ return; } if (c > 0177) { /* timeout delay */ tp->t_state =| TIMEOUT; timeout(&ttrs0 #define READ 0004 /* status */ #define OV 0200 #define BRK 0040 #define BSY 0010 #define EX 0004 #define DU 0001 #define WINIT WOPEN /* waiting to change mode read->write */ /* * open routine: * called each time a process opens a terminal as a character file * * - if the terminal was previously inactive, set up the initial status * and arm interrupts */ cliopen(dev,flag) { register struct tty *tp; int clistart(); if (dev.d_minor >= NCLI) { /* minor device number too large ? */ u.u_erro #define DISARM 0xc0 #define NO_PAPER 0x40 #define INTLOCK 0x10 #define DU 0x01 struct { /* info about the printer */ struct clist outq; /* output char queue */ char flag; /* current mode */ char state; /* internal status */ int mcc; /* actual column posn */ int ccc; /* logical column posn */ int mlc; /* curr line # */ int mxc; /* max line width */ int mxl; /* max page depth */ } lp; #define P_WASTE ECHO /* if on, printer wastes paper */ #define IND XTABS /* if on, lines are indented 8 spac 0; } /* now fall through to '\r' code */ case '\r': lp.ccc = 0; if (lp.flag & IND) lp.ccc = 8; return; case '\b': if (lp.ccc > 0) lp.ccc--; return; case 0x07: lpoutput(c); /* ring bell, no char advance */ return; case ' ': lp.ccc++; return; case VTAB: if(lp.mcc) lpcanon('\n'); while(lp.mlc & 7) lpcanon('\n'); return; default: if ((c & 0x7f) < 0x20) /* non printing - ignore */ return; if(lp.ccc < lp.mcc) { lpoutput('\r'); /* cause overprint */; trace(04<<8,"lpsleep",lp.outq.c_cc); sleep(&lp, LPPRI); } putc(c, &lp.outq); lpstart(); spl(0); } /* * allow several line printer attributes to be dynamically altered */ lpsgtty(dev, av) int *av; { register *v; if(v=av) { *v++ = 0; v->lobyte = lp.mxc; v->hibyte = lp.mxl; v[1] = lp.flag; return(1); } v = u.u_arg; lp.mxc = (++v)->lobyte; lp.mxl = v->hibyte; lp.flag = v[1]; return(0); } ?@FLR>-3AGMStrt, tp, c&0177); } else { /* write character to device */ tp->t_state =| BUSY; wd(cliaddr[tp->t_dev.d_minor], c); trace(0x1000, "wrt", ss(cliaddr[tp->t_dev.d_minor])); } } /* interrupt handler */ cliint(addr,stat) int addr; int stat; { register struct tty *tp; register c; tp = devmap(addr); if ( !(tp->t_state & ISOPEN)) /* return if device not open */ return; if (tp->t_state & BUSY) /* if write enable or write complete */ { if (stat & BRK) /* if BRK key hit */ { trace(0x1000,"brk :",0); c = CINTR; /* set character to del */ tp->t_state =& ~(BUSY | WINIT); /* reset flags */ cliparam(tp); /* reset to read mode */ ttyinput(c, tp); } else if (tp->t_state & WINIT) { /* if WINIT, interrupt was write enable */ trace(0x1000, "WINIT", stat); tp->t_state =& ~(BUSY | WINIT); clistrto(tp); } else { /* else interrupt was write complete */ trace(0x1000, "wint", stat); tp->t_state =& ~BUSY; es */ #define FORM 0x0c #define VTAB 0x0b /* * open - line printer */ lpopen(dev, flag) { if(lp.state&ISOPEN || (ss(lpaddr)&(NO_PAPER|INTLOCK|DU))) { u.u_error = EIO; return; } trace(01<<8,"lpopen",0); lp.state = ISOPEN; if (lp.mxc == 0) { lp.mxc = LPWIDTH; lp.mxl = LPDEPTH; } oc(lpaddr, ENABLE); lpcanon(FORM); } /* * close - line printer */ lpclose(dev, flag) { lpcanon(FORM); trace(01<<8,"lpclose",0); lp.state = 0; } /* * user write to line printer */ lpwrite() lp.mcc = 0; } if (lp.ccc < lp.mxc) { while(lp.ccc > lp.mcc) { lpoutput(' '); lp.mcc++; } lpoutput(c); lp.mcc++; } lp.ccc++; } } /* * start transmission to printer */ lpstart() { register c; register s; trace(02<<8,"lpstart",lpaddr); trace(01<<8,"lpstat",ss(lpaddr)); while( (s = ss(lpaddr)) == 0 && (c = getc(&lp.outq)) >= 0 ) { trace(010<<8,"lpchar",c); wd(lpaddr, c); } trace(01<<8,"lpstat",s); } /* * line printer interrupt */ lpint(dev, stNBPT; msmsector = (bn % NBPT)<<1; msmsad = bp->b_addr; msmead = bp->b_addr + bp->b_bcount - 1; selchreq(NSELCH, &msmscq); } msmseek() { register stat; trace(010<<16, "seek", msmdrive); trace(010<<16, "cyl", msmcyl); msmseekf++; wh(msmdrive, msmcyl); oc(msmdrive, SETCYL|DISARM); oc(msmdrive, SEEK|ENABLE); } /* * disk interrupt routine * -disk interrupts only after a seek (I hope) * -check status, initiate read/write */ msmintr(dev,stat) { register struct buf *bp; register scmd, ccmd; # #include "param.h" #include "buf.h" #include "conf.h" #include "selch.h" /* * 67-mb 'MSM' disk driver */ /* Configuration */ #define NDSK 2 /* number of disks */ /* device addresses */ #define NSELCH 0 /* connected to selch 1 */ int msmcntl 0xfb; /* disk controller */ char msmaddr[NDSK] { /* disk drives */ 0xfc, 0xfd }; int msmseek(), msmscintr(); struct devtab msmtab; struct buf rmsmbuf; struct selchq msmscq { &msmseek, &msmscintr, 0 }; int msmdrive; int msmcyl; int msmhead; int msmsector; int msmsad, msmead; int msmseekf; int msmqlen; /* current length of i/o queue (for display only */ #define NBPC (32*5) /* blocks per cylinder */ #define NBPT 32 /* blocks per track */ #define NDSKERR 10 /* number of error retries */ /* logical device mapping */ struct dskmap { int dm_baddr; /* block offset */ int dm_nblk; /* number of blocks */ } msmap[] { 0, 60*NBPC, 60*NBPC, 60*NBPC, 120*NBPC, 702*NBPC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 822*NBPC }; /* disk drive status & do here? ) */ msmscintr(dev, stat) { register struct buf *bp; oc(selchaddr[NSELCH], STOP); } /* * disk controller interrupt routine * -check ending status, signal i/o done */ msmcintr(dev, stat) { register struct buf *bp; register struct dskmap *dm; trace(020<<16, "interrupt", dev); trace(020<<16, "status", stat); if (!(bp = msmtab.d_actf)) return; if (msmseekf) return; if (stat & CNTL_UNRCV) { oc(msmcntl, RESET); msmerror(bp, stat, msmcntl); return; } bp->b_resid = 0; /*sintr)(dev, stat); } ess */ char dskaddr[NDSK] { /* disk file addresses */ 0xc6, 0xc7 }; #define drivemap(dev) &dsk[dev.d_minor>>1] /* map minor dev => drive */ #define devmap(addr) &dsk[(addr-0xc6)>>4] /* map phys addr => drive */ /* Data areas */ int dskstart(), dskscintr(), dsknrdy(); struct buf rdskbuf; /* raw I/O buffer */ struct devtab dsktab; /* major device table (per controller) * d_active = controller busy flag * d_actf = ptr to dsk table for last * accessed drive */ struct dsk { /* disk READ)) bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; iodone(bp); return; } /* * Calculate cylinder/head/sector */ bp->b_cyl = bp->b_blkno / 24; if ((bp->b_sector = (bp->b_blkno<<1) % 48) >= 24) bp->b_sector += 32-24; /* * Put buffer on queue for drive */ dp = drivemap(bp->b_dev); spl(5); for (p1 = dp; (p2 = p1->av_forw) && (dp->dk_dir? (p2->b_cyl <= bp->b_cyl) : (p2->b_cyl >= bp->b_cyl) ); ) p1 = p2; bp->av_forw = p2; p1->av_forw = bp; /* * Start I/# /* * 10-MB cartridge disk driver: Multi-disc version * - overlapped seeks * - seeks ordered by 'FSCAN' algorithm */ #include "param.h" #include "buf.h" #include "conf.h" #include "selch.h" /* Configuration data */ #define NSELCH 0 /* attached to first selector channel */ #define NDRV 1 /* number of disk drives */ #define NDSK 2 /* number of disks */ #define NDSKBLK 9792 /* number of blocks on disk */ #define NDSKERR 10 /* number of error retries */ int cntladdr 0xb6; /* disk controller addrcommands */ #define BSY 0x20 #define UNS 0x10 #define UNREADY 0x08 #define SINC 0x02 #define OFFL 0x01 #define DISABLE 0x80 #define ENABLE 0x40 #define DISARM 0xc0 #define SETHEAD 0x20 #define SETCYL 0x10 #define SEEK 0x02 /* disk controller status & commands */ #define CNTL_UNRCV 0xc1 #define CYL_OV 0x10 #define IDLE 0x02 #define READ 0x01 #define WRITE 0x02 #define RESET 0x08 /* * disk strategy routine */ msmstrategy(abp) { register struct buf *bp; bp = abp; bp->b_resid = bp->b_bcount; i * Cylinder overflow */ if (stat & CYL_OV) { oc(msmcntl, RESET); oc(selchaddr[NSELCH], STOP); msmsad =+ (rdh(selchaddr[NSELCH])-msmsad+2)&~0377; trace(020<<16, "cyl ov", msmsad); msmsector = msmhead = 0; bp->b_resid = msmead - msmsad; dm = &msmap[bp->b_dev.d_minor&07]; if ((++msmcyl*NBPC) < dm->dm_baddr + dm->dm_nblk) { msmseek(); return; } else if ((bp->b_flags&(B_PHYS|B_READ)) != (B_PHYS|B_READ)) bp->b_flags =| B_ERROR; } msmtab.d_errcnt = 0; msmtab.d_active = 0; mX P PA@š&x C PPAXPPA@j4P C0X# XX &P@lX 8&YB0('tX@lPX PPA@o(&tPCX PPA@nPXP 8'x$P PXPXPAf&xXPA@q(@m!6X@|B0юp8p4ЇX4  X ` B0 X PX@ACX@|C0% P@PA@X@PX@|P[PAzP X ``C0PPA@j4C0X#XX B0PPA@r\P# PPA@nPtable (per drive) */ char d_active; /* drive busy flag */ char d_errcnt; /* error count (for recovery) */ int dk_cyl; /* current cylinder position */ int dk_dir; /* current direction of arm motion */ struct buf *av_forw; /* head of I/O queue for next pass */ struct buf *dk_actf; /* head of I/O queue for this pass */ } dsk[NDRV]; #define DSEEK 1 #define DIO 2 #define DNRDY 3 struct selchq dskscq { /* channel queue entry */ &dskstart, &dskscintr, 0 }; /* Redefined buffer fields */ #define b_cyl O */ if (!(dp->d_active || dsktab.d_active)) selchreq(NSELCH, &dskscq); spl(0); } /* * Disk startup routine * - start overlapped seeks on all drives * - check status of finished seeks * - start I/O transfer on 'next' drive (round robin) */ dskstart() { register struct dsk *dp, *idp; register struct buf *bp; register int file, stat; idp = 0; if ((dp = dsktab.d_actf) == 0) dsktab.d_actf = dp = dsk; trace(1<<16, "dstart", dp); do { /* for each drive */ /* * Start overlapped seeks dp->dk_cyl = -1; /* force seek */ continue; } idp = dp; break; } /* seek required */ if (stat & NOT_READY) { dp->d_active = DNRDY; timeout(&dsknrdy, dp, 1000); break; } if (stat & UNRCV) { dp->d_errcnt = NDSKERR; /* no retry */ dskerror(dp, stat, file); continue; } dp->d_active = DSEEK; wh(file, bp->b_cyl); oc(file, SEEK); trace(2<<16, "seek", file); trace(2<<16, "cyl", bp->b_cyl); break; } } while (dp != dsktab.d_actf); /* * Staf ((bp->b_dev.d_minor>>3) >= NDSK) { bp->b_flags =| B_ERROR; iodone(bp); return; } /* * Block no. too high -- looks like EOF for raw read, error otherwise */ if (bp->b_blkno >= msmap[bp->b_dev.d_minor&07].dm_nblk) { if ((bp->b_flags&(B_PHYS|B_READ)) != (B_PHYS|B_READ)) bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; spl(5); msmqlen = (msmqlen<<1) | 01; if (msmtab.d_actf == 0) msmtab.d_actf = bp; else msmtab.d_actl->av_forw = bp; msmtab.d_actl = bp; if (msmtasmtab.d_actf = bp->av_forw; msmqlen =>> 1; iodone(bp); selchfree(NSELCH); msmstart(); } msmerror(abp, stat, addr) struct buf *abp; { register struct buf *bp; bp = abp; deverror(bp, stat, addr); if (++msmtab.d_errcnt <= NDSKERR) { msmseek(); return; } msmtab.d_errcnt = 0; bp->b_flags =| B_ERROR; msmtab.d_active = 0; msmtab.d_actf = bp->av_forw; msmqlen =>> 1; iodone(bp); selchfree(NSELCH); msmstart(); } /* * 'Raw' disc interface */ msmread(dev) { physio(msmstrategy, &rmsmbuf, dev, 'x$P X PXPXPA&x@m#:XPA@q(C*T@!9XPA@p#XPA@p'xX@P X@PX P PA@š&xC T !;X@ X@P   @m!6X@|B0zюp4p(ЇX(U,#$X(#X,#юp(p(ЇX(U,#X(#X,#юp(p(ЇX0X(XZ,@lB0  V@xB0X4B0"'tPPX@xPA@ x&tC'tPX@xPPA@ &t #8j@mCvQ@xP@PA@„X@| P@|CJX av_back.integ #define b_sector b_resid.integ /* Disk file status & commands */ #define UNRCV 0x62 /* wrt chk|ill addr|seek inc */ #define ADDR_INTLK 0x10 #define WRT_PROT 0x80 #define NOT_READY 0x01 #define SEEK 0x42 /* Disk controller status & commands */ #define CNTL_UNRCV 0xe1 /* overrun|addr comp fail|def trk|data err */ #define OVERRUN 0x80 #define CYL_OV 0x10 #define READ 0x01 #define WRITE 0x02 /* * Disk strategy routine * - check block no. & translate to cylinder/head/sector * - pu on all drives */ if (++dp >= &dsk[NDRV]) dp = dsk; while (!dp->d_active) { if (!(bp = dp->dk_actf)) { if (!(bp = dp->av_forw)) break; else { dp->dk_actf = bp; dp->av_forw = 0; dp->dk_dir = ~dp->dk_dir; } } file = dskaddr[bp->b_dev.d_minor]; while ((stat = ss(file)) & ADDR_INTLK) ; if (bp->b_cyl == dp->dk_cyl) { /* seek done */ if (idp) break; /* check status from seek */ if (stat & ~WRT_PROT) { dskerror(dp, stat, file); rt next I/O transfer */ if (!idp) /* no I/O to start */ selchfree(NSELCH); else { dsktab.d_actf = idp; bp = idp->dk_actf; file = dskaddr[bp->b_dev.d_minor]; while (ss(file) & ADDR_INTLK) ; oc(selchaddr[NSELCH], STOP); wdh(selchaddr[NSELCH], bp->b_addr); wdh(selchaddr[NSELCH], bp->b_addr+bp->b_bcount-1); wh(file, bp->b_cyl); wd(cntladdr, bp->b_sector); if (bp->b_flags & B_READ) { oc(cntladdr, READ); oc(selchaddr[NSELCH], READ_GO); } else { oc(cntladdr, WRITE); oc(seb.d_active == 0) msmstart(); spl(0); } /* * start next disk i/o operation * - set up drive address, cylinder/head/sector address * - set up memory start & end addresses * - initiate seek */ msmstart() { register struct buf *bp; register stat; register bn; if (!(bp = msmtab.d_actf)) return; msmtab.d_active++; trace(010<<16, "mstart", bp); msmdrive = msmaddr[bp->b_dev.d_minor>>3]; bn = bp->b_blkno + msmap[bp->b_dev.d_minor&07].dm_baddr; msmcyl = bn / NBPC; bn =% NBPC; msmhead = bn / B_READ); } msmwrite(dev) { physio(msmstrategy, &rmsmbuf, dev, B_WRITE); } XZ4PCPX PA@nXXB0X8'PX XB0HX PA@IP!9PA@q($CXX$X." ,PPA@pC PA@q(PX PA@nPXXX8PX XB0FX PA@IPC0.XX$X PXPA@pPA@p#PA@q($P@lX#X XP@l #юp4p(Ї@l#:X(X@xC,X(PX@xPA@ B#j@m%C2%Q@|$Q@!5$Q@$Q@xX@|!3%#$#юp(p(ЇX@t buffer on queue for corresponding drive * - if controller free, call dskstart() to start I/O */ dskstrategy(bp) register struct buf *bp; { register struct dsk *dp; register struct buf *p1, *p2; trace(1<<16, "dstrategy", bp); if (bp->b_dev.d_minor >= NDSK) { bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; iodone(bp); return; } /* * Block no. too high -- looks like EOF for raw read, error otherwise */ if (bp->b_blkno >= NDSKBLK) { if ((bp->b_flags&(B_PHYS|B_READ)) != (B_PHYS|B_ECIOUDJPKQW  lchaddr[NSELCH], GO); } trace(2<<16, "dio", file); trace(2<<16, "sector", bp->b_sector); idp->d_active = DIO; dsktab.d_active++; } } /* * Disk not ready routine: * - restart disk every 10 seconds until it comes ready again * - (this should not be necessary: according the Interdata manual there * should be an interrupt when NRSRW drops) * * NOTE: * This will not work when multi-level interrupts are implemented. As * this routine is called from the clock interrupt, it may be out of sync wi^djY_ekZ`itialize and * validate before actual IO. * Called on all sorts of opens * and also on mount. */ openi(ip, rw) int *ip; { register *rip; register dev, maj; rip = ip; dev = rip->i_addr[0]; maj = rip->i_addr[0].d_major; switch(rip->i_mode&IFMT) { case IFCHR: if(maj >= nchrdev) goto bad; (*cdevsw[maj].d_open)(dev, rw); break; case IFBLK: if(maj >= nblkdev) goto bad; (*bdevsw[maj].d_open)(dev, rw); } return; bad: u.u_error = ENXIO; } /* * Check mode permission on inode point == NULL) { u.u_ar0[R0] = i; return(i); } u.u_error = EMFILE; return(-1); } /* * Allocate a user file descriptor * and a file structure. * Initialize the descriptor * to point at the file structure. * * no file -- if there are no available * file structures. */ falloc() { register struct file *fp; register i; if ((i = ufalloc()) < 0) return(NULL); for (fp = &file[0]; fp < &file[NFILE]; fp++) if (fp->f_count==0) { u.u_ofile[i] = fp; fp->f_count++; fp->f_offset[0] = 0; ectory */ char u_dbuf[DIRSIZ]; /* current pathname component */ char *u_dirp; /* current pointer to inode */ struct { /* current directory entry */ int u_ino; char u_name[DIRSIZ]; } u_dent; int *u_pdir; /* inode of parent directory of dirp */ int u_uisa[16]; /* prototype of segmentation addresses */ int u_ofile[NOFILE]; /* pointers to file structures of open files */ int u_arg[5]; /* arguments to current system call */ int u_tsize; /*** text size (*256) ***/ int u_dsize; /*** data siz/* * Text structure. * One allocated per pure * procedure on swap device. * Manipulated by text.c */ extern struct text { int x_daddr; /* disk address of segment */ int x_caddr; /* core address, if loaded */ int x_size; /*** size (*256) ***/ int *x_iptr; /* inode of prototype */ char x_count; /* reference count */ char x_ccount; /* number of loaded references */ } text[NTEXT]; op; /*** highest addr in physical memory */ extern int rootdev; /* dev of root see conf.c */ extern int swapdev; /* dev of swap see conf.c */ extern int swplo; /* block number of swap space */ extern int nswap; /* size of swap space */ extern int updlock; /* lock for sync */ extern int rablock; /* block to be read ahead */ extern int regloc[]; /***/ /* locs. of saved user registers (trap.c) */ # /* */ #include "param.h" #include "user.h" #include "filsys.h" #include "file.h" #include "conf.h" #include "inode.h" #include "reg.h" /* * Convert a user supplied * file descriptor into a pointer * to a file structure. * Only task is to check range * of the descriptor. */ getf(f) { register *fp, rf; rf = f; if(rf<0 || rf>=NOFILE) goto bad; fp = u.u_ofile[rf]; if(fp != NULL) return(fp); bad: u.u_error = EBADF; return(NULL); } /* * Internal form of close. * Decrement reference counter. * Mode is READ, WRITE or EXEC. * In the case of WRITE, the * read-only status of the file * system is checked. * Also in WRITE, prototype text * segments cannot be written. * The mode is shifted to select * the owner/group/other fields. * The super user is granted all * permissions except for EXEC where * at least one of the EXEC bits must * be on. */ access(aip, mode) int *aip; { register *ip, m; ip = aip; m = mode; if(m == IWRITE) { if(getfs(ip->i_dev)->s_ronly != 0) { u.u_error fp->f_offset[1] = 0; return(fp); } printf("no file\n"); u.u_error = ENFILE; return(NULL); } e (*256) ***/ int u_ssize; /*** stack size (*256) ***/ int u_sep; /* flag for I and D separation */ int u_qsav[2]; /* label variable for quits and interrupts */ int u_ssav[2]; /* label variable for swapping */ int u_signal[NSIG]; /* disposition of signals */ int u_utime; /* this process user time */ int u_stime; /* this process system time */ int u_cutime[2]; /* sum of childs' utimes */ int u_cstime[2]; /* sum of childs' stimes */ int *u_ar0; /* address of users saved R0 */ int u_prof/* * Random set of variables * used by more than one * routine. */ extern char canonb[CANBSIZ]; /* buffer for erase and kill (#@) */ extern int coremap[CMAPSIZ]; /* space for core allocation */ extern int swapmap[SMAPSIZ]; /* space for swap allocation */ extern int *rootdir; /* pointer to inode of root directory */ extern int cputype; /* type of cpu =40, 45, or 70 */ extern int execnt; /* number of processes in exec */ extern int lbolt; /* time of day in HZ not in time */ extern int time[2]; /* t/* * Location of the users' stored * registers relative to R0. * Usage is u.u_ar0[XX]. */ #define R0 0 #define R1 1 #define R2 2 #define R3 3 #define R4 4 #define R5 5 #define R6 6 #define R7 7 #define R8 (-10) #define R9 (-9) #define R10 (-8) #define R11 (-7) #define R12 (-6) #define R13 (-5) #define R14 (-4) #define R15 8 #define RF 8 #define RSP 7 #define RPS 9 #define RPC 10 on * file structure and call closei * on last closef. * Also make sure the pipe protocol * does not constipate. */ closef(fp) int *fp; { register *rfp, *ip; rfp = fp; if(rfp->f_flag&FPIPE) { ip = rfp->f_inode; ip->i_mode =& ~(IREAD|IWRITE); wakeup(ip+1); wakeup(ip+2); } if(rfp->f_count <= 1) closei(rfp->f_inode, rfp->f_flag&FWRITE); rfp->f_count--; } /* * Decrement reference count on an * inode due to the removal of a * referencing file structure. * On the last closei, switchout = EROFS; return(1); } if(ip->i_flag & ITEXT) { u.u_error = ETXTBSY; return(1); } } if(u.u_uid == 0) { if(m == IEXEC && (ip->i_mode & (IEXEC | (IEXEC>>3) | (IEXEC>>6))) == 0) goto bad; return(0); } if(u.u_uid != ip->i_uid) { m =>> 3; if(u.u_gid != ip->i_gid) m =>> 3; } if((ip->i_mode&m) != 0) return(0); bad: u.u_error = EACCES; return(1); } /* * Look up a pathname and test if * the resultant inode is owned by the * current user. * If not, try for super-user./* * The user structure. * One allocated per process. * Contains all per process data * that doesn't need to be referenced * while the process is swapped. *** The user block is USIZE*256 bytes * long; resides at virtual kernel *** loc x'e0000'; contains the system * stack per user; is cross referenced * with the proc structure for the * same process. */ extern struct user { int u_rsav[2]; /* save r5,r6 when exchanging stacks */ int u_fsav[25]; /*** save fp registers ***/ /* rsav and fsa[4]; /* profile arguments */ char u_intflg; /* catch intr from sys */ /***/ char u_nostack; /* Process has no user stack */ /* kernel stack per user *** extends from u + USIZE*256 * backward not to reach here */ } u; /* u_error codes */ #define EFAULT 106 #define EPERM 1 #define ENOENT 2 #define ESRCH 3 #define EINTR 4 #define EIO 5 #define ENXIO 6 #define E2BIG 7 #define ENOEXEC 8 #define EBADF 9 #define ECHILD 10 #define EAGAIN 11 #define ENOMEM 12 #define EACCES 13 #define ENOime in sec from 1970 */ extern int tout[2]; /* time of day of next sleep */ /* * The callout structure is for * a routine arranging * to be called by the clock interrupt * (clock.c) with a specified argument, * in a specified amount of time. * Used, for example, to time tab * delays on teletypes. */ extern struct callo { int c_time; /* incremental time */ int c_arg; /* argument to routine */ int (*c_func)(); /* routine */ } callout[NCALL]; /* * Mount structure. * One allocated on every mount/* * One structure allocated per active * process. It contains all data needed * about the process while the * process may be swapped out. * Other per process data (user.h) * is swapped with the process. */ extern struct proc { char p_stat; char p_flag; char p_pri; /* priority, negative is high */ char p_sig; /* signal number sent to this process */ char p_uid; /* user id, used to direct tty signals */ char p_time; /* resident time for scheduling */ char p_cpu; /* cpu usage for scheduling * to the close entry point of special * device handler. * Note that the handler gets called * on every open and only on the last * close. */ closei(ip, rw) int *ip; { register *rip; register dev, maj; rip = ip; dev = rip->i_addr[0]; maj = rip->i_addr[0].d_major; if(rip->i_count <= 1) switch(rip->i_mode&IFMT) { case IFCHR: (*cdevsw[maj].d_close)(dev, rw); break; case IFBLK: (*bdevsw[maj].d_close)(dev, rw); } iput(rip); } /* * openi called to allow handler * of special files to in * If permission is granted, * return inode pointer. */ owner() { register struct inode *ip; extern uchar(); if ((ip = namei(uchar, 0)) == NULL) return(NULL); if(u.u_uid == ip->i_uid) return(ip); if (suser()) return(ip); iput(ip); return(NULL); } /* * Test if the current user is the * super user. */ suser() { if(u.u_uid == 0) return(1); u.u_error = EPERM; return(0); } /* * Allocate a user file descriptor. */ ufalloc() { register i; for (i=0; ip_cpu == 0) pp->p_cpu--; if(++lbolt >= HZ) { if (clkflag) return; clkflag++; lbolt =- HZ; if(++time[1] == 0) ++time[0]; /***/ spl(0); if(time[1]==tout[1] && time[0]==tout[0]) wakeup(tout); if((time[1]&03) == 0) { runrun++; wakeup(&lbolt); } for(pp = &proc[0]; pp < &proc[NPROC]; pp++) if (pp->p_stat) { if(pp->p_time != 127) pp->p_time++; if((pp->p_cpu & 0377) > SCHMAG) pp->p_cpu =- SCHMAG; else pp->p_cpu = 0; if ((p/* * One file structure is allocated * for each open/creat/pipe call. * Main use is to hold the read/write * pointer associated with each open * file. */ extern struct file { char f_flag; char f_count; /* reference count */ int f_inode; /* pointer to inode structure */ char *f_offset[2]; /* read/write character pointer */ } file[NFILE]; /* flags */ #define FREAD 01 #define FWRITE 02 #define FPIPE 04 /* * The I node is the focus of all * file activity in unix. There is a unique * inode allocated for each active file, * each current directory, each mounted-on * file, text file, and the root. An inode is 'named' * by its dev/inumber pair. (iget/iget.c) * Data, from mode on, is read in * from permanent inode on volume. */ extern struct inode { char i_flag; char i_count; /* reference count */ int i_dev; /* device where inode resides */ int i_number; /* i number, 1-to-1 with device address */ /* * Inode structure as it appears on * the disk. Not used by the system, * but by things like check, df, dump. */ struct inode { int i_mode; char i_nlink; char i_uid; char i_gid; char i_size0; char *i_size1; int i_addr[8]; int i_atime[2]; int i_mtime[2]; int i_filler; /***/ }; /* modes */ #define IALLOC 0100000 #define IFMT 060000 #define IFDIR 040000 #define IFCHR 020000 #define IFBLK 060000 #define ILARG 010000 #define ISUID 04000 #define ISGID 02000 #define ISVTX 01000 #define IREAD 04# /*** unix system data areas ***/ #include "param.h" #include "proc.h" #include "buf.h" #include "inode.h" #include "file.h" #include "text.h" /* * mask & circular buffer for system trace routine */ extern trmask; /* now in low.s */ int trbuff[66] { 64<<16 }; struct proc proc[NPROC]; char canonb[CANBSIZ]; /* buffer for erase and kill (#@) */ int coremap[CMAPSIZ]; /* space for core allocation */ int swapmap[SMAPSIZ]; /* space for swap allocation */ int *rootdir; /* pointer to inode of root direc#include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #define UMODE 01<<8 /*** 'USER MODE' IN PSW == PROT BIT ***/ #define SCHMAG (HZ/6) /*** was 10 -- proportional to HZ? ***/ /* * clock is called straight from * the real time clock interrupt. * * Functions: * reprime clock * copy *switches to display * implement callouts * maintain user/system times * maintain date * profile * tout wakeup (sys sleep) * lightning bolt wakeup (every 4 sec) * alarm clock signals * jab the ri = pp->p_pri) > PUSER && pri <= 127) { /***/ setpri(pp); if ((pri = pp->p_pri) > 127) /***/ pri =- 256; /***/ /* * check whether other process is now * more deserving */ if (pp->p_stat == SRUN && pri < curpri) /***/ runrun++; /***/ } } if(runin!=0) { runin = 0; wakeup(&runin); } if((ps&UMODE) == UMODE) { clkflag = 0; u.u_ar0 = &r0; if(issig()) psig(); setpri(u.u_procp); } clkflag = 0; } } /* * timeout is called to arrange # #include "param.h" #include "tty.h" #include "systm.h" extern struct cblock *cfreelist; #define CBS (sizeof *cfreelist) /* * character-list manipulation routines */ /* * getc: * return the next character from the given clist. * if the clist is empty, return -1. */ getc(clist) struct clist *clist; { register struct clist *cl; register char c, *p; int sps; cl = clist; sps = spl(5); if ((p = cl->c_cf) == NULL) { cl->c_cl = NULL; spl(sps); return(-1); } c = *p; cl->c_cf = ++p; if int i_mode; char i_nlink; /* directory entries */ char i_uid; /* owner */ char i_gid; /* group of owner */ char i_size0; /* most significant of size */ char *i_size1; /* least sig */ int i_addr[8]; /* device addresses constituting file */ int i_lastr; /* last logical block read (for read-ahead) */ } inode[NINODE]; /* flags */ #define ILOCK 01 /* inode is locked */ #define IUPD 02 /* inode has been modified */ #define IACC 04 /* inode access time to be updated */ #define IMOUNT 010 /* inode is 00 #define IWRITE 0200 #define IEXEC 0100 tory */ int cputype; /* type of cpu =40, 45, or 70 */ int execnt; /* number of processes in exec */ int lbolt; /* time of day in HZ not in time */ int time[2]; /* time in sec from 1970 */ int tout[2]; /* time of day of next sleep */ int csw; /* copy of display switch value */ /* * Mount structure. * One allocated on every mount. * Used to find the super block. */ struct mount { int m_dev; /* device mounted */ int *m_bufp; /* pointer to superblock */ int *m_inodp; /* pointer to mounted on inscheduler */ clock(dev, stat, r0, r1, r2, r3, r4, r5, r6, asp, rf, ps, pc, nps) { register struct callo *p1, *p2; register struct proc *pp; static clkflag; /*** used to prevent reentry ***/ register pri; /***/ /* * display register */ display(pc); /* * callouts * if none, just return * else update first non-zero time */ if(callout[0].c_func == 0) goto out; p2 = &callout[0]; while(p2->c_time<=0 && p2->c_func!=0) p2++; p2->c_time--; /* * if lbolt being processed already,that * fun(arg) is called in tim/HZ seconds. * An entry is sorted into the callout * structure. The time in each structure * entry is the number of HZ's more * than the previous entry. * In this way, decrementing the * first entry has the effect of * updating all entries. */ timeout(fun, arg, tim) { register struct callo *p1, *p2; register t; int s; t = tim; p1 = &callout[0]; s = spl(7); while(p1->c_func != 0 && p1->c_time <= t) { t =- p1->c_time; p1++; } p1->c_time =- t; p2 = p1; w(--cl->c_cc <= 0) { cl->c_cf = cl->c_cl = NULL; p = --p & ~(CBS -1); p->c_next = cfreelist; cfreelist = p; } else if ((p & (CBS -1)) == 0) { p =- CBS; cl->c_cf = p->c_next; p->c_next = cfreelist; cfreelist = p; } spl(sps); return(c); } /* * putc: * put a character onto the given clist. * if there are no more cblocks available, return nonzero * otherwise return 0. */ putc(ch, clist) struct clist *clist; { register struct clist *cl; register char c, *p, *q; int sps; cl = clmounted on */ #define IWANT 020 /* some process waiting on lock */ #define ITEXT 040 /* inode is pure text prototype */ /* modes */ #define IALLOC 0100000 /* file is used */ #define IFMT 060000 /* type of file */ #define IFDIR 040000 /* directory */ #define IFCHR 020000 /* character special */ #define IFBLK 060000 /* block special, 0 is regular */ #define ILARG 010000 /* large addressing algorithm */ #define ISUID 04000 /* set user id on execution */ #define ISGID 02000 /* set group id on executi/* * Definition of the unix super block. * The root super block is allocated and * read in iinit/alloc.c. Subsequently * a super block is allocated and read * with each mount (smount/sys3.c) and * released with unmount (sumount/sys3.c). * A disk block is ripped off for storage. * See alloc.c for general alloc/free * routines for free list and I list. */ struct filsys { int s_isize; /* size in blocks of I list */ int s_fsize; /* size in blocks of entire volume */ int s_nfree; /* number of in corode */ } mount[NMOUNT]; /* * The callout structure is for * a routine arranging * to be called by the clock interrupt * (clock.c) with a specified argument, * in a specified amount of time. * Used, for example, to time tab * delays on teletypes. */ struct callo { int c_time; /* incremental time */ int c_arg; /* argument to routine */ int (*c_func)(); /* routine */ } callout[NCALL]; /* * in-core inode pool */ struct inode inode[NINODE]; struct file file[NFILE]; struct text text[NTEXT]; int just return */ if (clkflag) goto out; /* * callout */ spl(5); if(callout[0].c_time <= 0) { p1 = &callout[0]; while(p1->c_func != 0 && p1->c_time <= 0) { (*p1->c_func)(p1->c_arg); p1++; } p2 = &callout[0]; while(p2->c_func = p1->c_func) { p2->c_time = p1->c_time; p2->c_arg = p1->c_arg; p1++; p2++; } } /* * lightning bolt time-out * and time of day */ out: if((ps&UMODE) == UMODE) { u.u_utime++; if(u.u_prof[3]) incupc(pc, u.u_prof); } else u.u_hile(p2->c_func != 0) p2++; while(p2 >= p1) { (p2+1)->c_time = p2->c_time; (p2+1)->c_func = p2->c_func; (p2+1)->c_arg = p2->c_arg; p2--; } p1->c_time = t; p1->c_func = fun; p1->c_arg = arg; spl(s); } ist; c = ch; sps = spl(5); if ((p = cl->c_cl) == NULL) { if ((p = cfreelist) == NULL) { spl(sps); return(1); } cfreelist = p->c_next; p->c_next = NULL; cl->c_cc = 0; p =+ sizeof p->c_next; cl->c_cf = p; } else if ((p & (CBS -1)) == 0) { q = p-CBS; if ((p = cfreelist) == NULL) { spl(sps); return(1); } cfreelist = p->c_next; p->c_next = NULL; p =+ sizeof p->c_next; q->c_next = p; } *p++ = c; cl->c_cl = p; ++cl->c_cc; spl(sps); return(0); } = 0; wakeup(&fp->s_flock); } bp = getblk(dev, bno); clrbuf(bp); fp->s_fmod = 1; return(bp); nospace: fp->s_nfree = 0; prdev("no space", dev); u.u_error = ENOSPC; return(NULL); } /* * place the specified disk block * back on the free list of the * specified device. */ free(dev, bno) { register *fp, *bp, *ip; fp = getfs(dev); fp->s_fmod = 1; while(fp->s_flock) sleep(&fp->s_flock, PINOD); if (badblock(fp, bno, dev)) return; if(fp->s_nfree <= 0) { fp->s_nfree = 1; fp->s_free[0] = bread(dev, i+2); ip = bp->b_addr; for(j=0; j<128; j=+16) { /***/ ino++; if(ip[j] != 0) continue; for(k=0; ks_inode[fp->s_ninode++] = ino; if(fp->s_ninode >= 50) /***/ break; cont:; } brelse(bp); if(fp->s_ninode >= 50) /***/ break; } fp->s_ilock = 0; wakeup(&fp->s_ilock); if (fp->s_ninode > 0) goto loop; prdev("Out of inodes", dev); u.u_error = ENOSPC; return(NULL); } /* * mp < &mount[NMOUNT]; mp++) if(mp->m_bufp != NULL) { ip = mp->m_bufp->b_addr; if(ip->s_fmod==0 || ip->s_ilock!=0 || ip->s_flock!=0 || ip->s_ronly!=0) continue; bp = getblk(mp->m_dev, 1); ip->s_fmod = 0; ip->s_time[0] = time[0]; ip->s_time[1] = time[1]; bcopy(ip, bp->b_addr, 128); /***/ bwrite(bp); } for(ip = &inode[0]; ip < &inode[NINODE]; ip++) if((ip->i_flag&ILOCK) == 0) { ip->i_flag =| ILOCK; iupdat(ip, time); prele(ip); } updlock = 0; bflush(NODEV); }3,memtop end of core? bl dump.lp * * Write file mark, rewind tape & halt CPU * oc r2,mt.wf write file mark bal rf,dump.wt oc r2,mt.rw rewind tape bal rf,dump.wt li r0,y'8000' go into disabled wait state epsr r1,r0 b dump.rs if restarted, try again * * Subroutine to wait for 'No Motion' status on tape * dump.wt equ * ssr r2,r0 sense tape status thi r0,x'10' no motion? bz dump.wt no - loop br rf yes - return * * Mag tape commands * mt.cl db x'20' clear controller mt.rw db x'38' rewind tape mt.* * disk strategy routine */ dskstrategy(abp) { register struct buf *bp; bp = abp; bp->b_resid = bp->b_bcount; if (bp->b_dev.d_minor >= NDSK) { bp->b_flags =| B_ERROR; iodone(bp); return; } /* * Block no. too high -- looks like EOF for raw read, error otherwise */ if (bp->b_blkno >= NDSKBLK) { if ((bp->b_flags&(B_PHYS|B_READ)) != (B_PHYS|B_READ)) bp->b_flags =| B_ERROR; iodone(bp); return; } bp->av_forw = 0; spl(5); dskqlen = (dskqlen<<1) | 01; if (dsktab.d_actf == 0) d# /* */ #include "param.h" #include "systm.h" #include "filsys.h" #include "conf.h" #include "buf.h" #include "inode.h" #include "user.h" /* * iinit is called once (from main) * very early in initialization. * It reads the root's super block * and initializes the current date * from the last modified date. * * panic: iinit -- cannot read the super * block. Usually because of an IO error. */ iinit() { register *cp, *bp; (*bdevsw[rootdev.d_major].d_open)(rootdev, 1); bp = bread(rootdev, 1); c 0; } if(fp->s_nfree >= 50) { /***/ fp->s_flock++; bp = getblk(dev, bno); ip = bp->b_addr; *ip++ = fp->s_nfree; bcopy(fp->s_free, ip, 50); /***/ fp->s_nfree = 0; bwrite(bp); fp->s_flock = 0; wakeup(&fp->s_flock); } fp->s_free[fp->s_nfree++] = bno; fp->s_fmod = 1; } /* * Check that a block number is in the * range between the I list and the size * of the device. * This is used mainly to check that a * garbage file system has not been mounted. * * bad block on dev x/y -- not iFree the specified I node * on the specified device. * The algorithm stores up * to ***50*** I nodes in the super * block and throws away any more. */ ifree(dev, ino) { register *fp; fp = getfs(dev); if(fp->s_ilock) return; if(fp->s_ninode >= 50) /***/ return; fp->s_inode[fp->s_ninode++] = ino; fp->s_fmod = 1; } /* * getfs maps a device number into * a pointer to the incore super * block. * The algorithm is a linear * search through the mount table. * A consistency check of the * in wf db x'30' write file mark mt.bs db x'11' backspace mt.wr db x'22' write * * Selch commands * selch.st db x'08' stop selch selch.go db x'10' start selch * * Register save area * impur align 8 eregs das 16 register set 0 uregs das 16 register set 15 * dump.psw dc y'f0',dump1 dump.ad das 1 end sktab.d_actf = bp; else dsktab.d_actl->av_forw = bp; dsktab.d_actl = bp; if (dsktab.d_active == 0) dskstart(); spl(0); } /* * start next disk i/o operation * - set up file address, cylinder/head/sector address * - set up memory start & end addresses * - check disk status * - initiate seek */ dskstart() { register struct buf *bp; register stat; if (!(bp = dsktab.d_actf)) return; dsktab.d_active++; trace(01<<16, "dstart", bp); dskfile = dskaddr[bp->b_dev.d_minor]; dskcyl = bp->b_blp = getblk(NODEV); if(u.u_error) panic("iinit"); bcopy(bp->b_addr, cp->b_addr, 128); /***/ brelse(bp); mount[0].m_bufp = cp; mount[0].m_dev = rootdev; cp = cp->b_addr; cp->s_flock = 0; cp->s_ilock = 0; cp->s_ronly = 0; time[0] = cp->s_time[0]; time[1] = cp->s_time[1]; } /* * alloc will obtain the next available * free disk block from the free list of * the specified device. * The super block has up to ***50*** remembered * free blocks; the last of these is read to * obtain ***50*** moren range */ badblock(afp, abn, dev) { register struct filsys *fp; register char *bn; fp = afp; bn = abn; if (bn < fp->s_isize+2 || bn >= fp->s_fsize) { prdev("bad block", dev); return(1); } return(0); } /* * Allocate an unused I node * on the specified device. * Used with file creation. * The algorithm keeps up to * ***50*** spare I nodes in the * super block. When this runs out, * a linear search through the * I list is instituted to pick * up ***50*** more. */ ialloc(dev) { registe core free-block and i-node * counts. * * bad count on dev x/y -- the count * check failed. At this point, all * the counts are zeroed which will * almost certainly lead to "no space" * diagnostic * panic: no fs -- the device is not mounted. * this "cannot happen" */ getfs(dev) { register struct mount *p; register char *n1, *n2; for(p = &mount[0]; p < &mount[NMOUNT]; p++) if(p->m_bufp != NULL && p->m_dev == dev) { p = p->m_bufp->b_addr; n1 = p->s_nfree; n2 = p->s_ninode; if(n1 > 50 || entry dump,uregs,eregs extrn memtop r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 rf equ 15 * * Dump all of core to mag tape * pure dump equ * lpsw dump.psw reg set 15, disabled dump1 equ * stm r0,uregs save reg set 15 lis r0,0 reg set 0, disabled epsr r1,r0 stm r0,eregs save reg set 0 * * Set up tape * dump.rs equ * lhi r1,x'f0' selch address lhi r2,x'c5' magtape address oc r1,selch.st stop selch oc r2,mt.cl clear tape controller oc r2,mt.rw rewind tape bal rf,dump.wt oc r2,mt.wf write a file mark bkno / 24; if ((dsksector = (bp->b_blkno<<1) % 48) > 23) dsksector =+ 32-24; dsksad = bp->b_addr; dskead = bp->b_addr + bp->b_bcount - 1; selchreq(NSELCH, &dskscq); } dskseek() { register stat; trace(010<<16, "seek", dskfile); trace(010<<16, "cyl", dskcyl); while ((stat = ss(dskfile))&~WRT_PROT) { if (stat & ADDR_INTLK) continue; if (stat & NOT_READY) { selchfree(NSELCH); timeout(&dsknrdy, 0, 1000); return; } if (stat & UNRCV) { dsktab.d_errcnt = NDSKERR; dskerror(dsktab.d_actf, stat, dskfile); return; } } dskseekf++; wh(dskfile, dskcyl); oc(dskfile, SEEK); } /* * disk not ready routine * - retry I/O every 10 seconds until disk starts again */ dsknrdy() { selchreq(NSELCH, &dskscq); } /* * disk interrupt routine * -disk interrupts only after a seek (I hope) * -check status, initiate read/write */ dskintr(dev,stat) { register struct buf *bp; register scmd, ccmd; trace(020<<16, "interrupt", dev); trace(020<<16, "status", stat); if (!(bp = dsktab. . . . * * no space on dev x/y -- when * the free list is exhausted. */ alloc(dev) { int bno; register *bp, *ip, *fp; fp = getfs(dev); while(fp->s_flock) sleep(&fp->s_flock, PINOD); do { if(fp->s_nfree <= 0) goto nospace; bno = fp->s_free[--fp->s_nfree]; if(bno == 0) goto nospace; } while (badblock(fp, bno, dev)); if(fp->s_nfree <= 0) { fp->s_flock++; bp = bread(dev, bno); ip = bp->b_addr; fp->s_nfree = *ip++; bcopy(ip, fp->s_free, 50); /***/ brelse(bp); fp->s_flock r *fp, *bp, *ip; int i, j, k, ino; fp = getfs(dev); while(fp->s_ilock) sleep(&fp->s_ilock, PINOD); loop: if(fp->s_ninode > 0) { ino = fp->s_inode[--fp->s_ninode]; ip = iget(dev, ino); if (ip==NULL) return(NULL); if(ip->i_mode == 0) { for(bp = &ip->i_mode; bp < &ip->i_addr[8];) *bp++ = 0; fp->s_fmod = 1; return(ip); } /* * Inode was allocated after all. * Look some more. */ iput(ip); goto loop; } fp->s_ilock++; ino = 0; for(i=0; is_isize; i++) { bp = n2 > 50) { /***/ prdev("bad count", dev); p->s_nfree = 0; p->s_ninode = 0; } return(p); } panic("no fs"); } /* * update is the internal name of * 'sync'. It goes through the disk * queues to initiate sandbagged IO; * goes through the I nodes to write * modified nodes; and it goes through * the mount table to initiate modified * super blocks. */ update() { register struct inode *ip; register struct mount *mp; register *bp; if(updlock) return; updlock++; for(mp = &mount[0]; al rf,dump.wt oc r2,mt.bs backspace over the file mark bal rf,dump.wt * * Dump core in 8k blocks * lis r3,0 start at origin dump.lp equ * st r3,dump.ad start address wd r1,dump.ad+1 write address to selch wh r1,dump.ad+2 ahi r3,8191 end address st r3,dump.ad wd r1,dump.ad+1 write address to selch wh r1,dump.ad+2 oc r2,mt.wr start tape writing oc r1,selch.go start selch dump.ss ssr r1,r0 wait for selch btc x'8',dump.ss oc r1,selch.st stop selch bal rf,dump.wt ais r3,1 next core block c rd_actf) || !dskseekf) return; dskseekf = 0; if (stat & ~WRT_PROT) { dskerror(bp, stat, dskfile); return; } if (bp->b_flags & B_READ) { scmd = READ_GO; ccmd = READ; } else { scmd = GO; ccmd = WRITE; } trace(010<<16, "dcmd", ccmd); trace(010<<16, "sector", dsksector); oc(selchaddr[NSELCH], STOP); trace(010<<16, "bufstart", dsksad); trace(010<<16, "bufend", dskead); wdh(selchaddr[NSELCH], dsksad); wdh(selchaddr[NSELCH], dskead); wh(dskfile, dskcyl); wd(cntladdr, dsksector); oc(cntladdr, ccmd); oc(selchaddr[NSELCH], scmd); } /* * selch interrupt routine * -selch interrupt will be followed by a controller interrupt * (unless OVERRUN status is set) */ dskscintr(dev, stat) { register struct buf *bp; if (!(bp = dsktab.d_actf)) return; oc(selchaddr[NSELCH], STOP); if ((stat = ss(cntladdr))&OVERRUN) dskerror(bp, stat, cntladdr); } /* * disk controller interrupt routine * -check ending status, signal i/o done */ cntlintr(dev, stat) { register struct buf *bp; tra# #include "param.h" #include "buf.h" #include "conf.h" #include "selch.h" /* * 10-mb cartridge disk driver */ int dskseek(), dskscintr(), dsknrdy(); struct devtab dsktab; struct buf rdskbuf; struct selchq dskscq { &dskseek, &dskscintr, 0 }; int dskfile; int dskcyl; int dsksector; int dsksad, dskead; int dskseekf; int dskqlen; /* current length of i/o queue (for display only */ #define NDSK 4 /* number of disks */ #define NDSKBLK 9792 /* number of blocks on disk */ #define NDSKERR 10 /* number of error retries */ /* device addresses */ #define NSELCH 0 /* connected to first selch */ int cntladdr 0xb6; /* disk controller */ char dskaddr[NDSK] { /* disk files */ 0xc6, 0xc7, 0xd6, 0xd7 }; /* disk file status & commands */ #define UNRCV 0156 #define ADDR_INTLK 0020 #define WRT_PROT 0200 #define NOT_READY 0001 #define SEEK 0102 /* disk controller status & commands */ #define CNTL_UNRCV 0341 #define OVERRUN 0200 #define CYL_OV 0020 #define READ 0001 #define WRITE 0002 /ce(020<<16, "interrupt", dev); trace(020<<16, "status", stat); if (!(bp = dsktab.d_actf)) return; if (dskseekf) return; if (stat & CNTL_UNRCV) { dskerror(bp, stat, cntladdr); return; } bp->b_resid = 0; /* * Cylinder overflow */ if (stat & CYL_OV) { oc(selchaddr[NSELCH], STOP); dsksad =+ (rdh(selchaddr[NSELCH])-dsksad+2)&~0377; trace(020<<16, "cyl ov", dsksad); dsksector = 0; bp->b_resid = dskead - dsksad; if (++dskcyl < NDSKBLK/24) { dskseek(); return; } else if ((bp->b_flags&(B_PHYS|B_READ)) != (B_PHYS|B_READ)) bp->b_flags =| B_ERROR; } dsktab.d_errcnt = 0; dsktab.d_active = 0; dsktab.d_actf = bp->av_forw; dskqlen =>> 1; iodone(bp); selchfree(NSELCH); dskstart(); } dskerror(abp, stat, addr) struct buf *abp; { register struct buf *bp; bp = abp; deverror(bp, stat, addr); if (++dsktab.d_errcnt <= NDSKERR) { dskseek(); return; } dsktab.d_errcnt = 0; bp->b_flags =| B_ERROR; dsktab.d_active = 0; dsktab.d_actf = bp->av_forw; dskqlen =>> 1; iodone(bp); selchfree(NSELCH); dskstart(); } /* * 'Raw' disc interface */ dskread(dev) { physio(dskstrategy, &rdskbuf, dev, B_READ); } dskwrite(dev) { physio(dskstrategy, &rdskbuf, dev, B_WRITE); } dev, WF); } if (dev.d_minor & 04) { if (writing) mtcommand(dev, BR); } else mtcommand(dev, RW); mt->m_status = 0; } mtcommand(dev, command) { register struct buf *bp; trace(0100<<16, "mtcommand", command); bp = &cmtbuf; spl(5); while (bp->b_flags & B_BUSY) { bp->b_flags =| B_WANTED; sleep(bp, PRIBIO); } bp->b_flags =| B_BUSY | B_READ; spl(0); bp->b_dev = dev; bp->b_blkno = command; mtstrategy(bp); iowait(bp); if (bp->b_flags & B_WANTED) wakeup(bp); bp->b_flags = 0; } mtstrategy(abp) struct buf *abp; { register struct buf *bp; register struct tape *mt; register int *p; if ((bp = abp) != &cmtbuf) { mt = &tape[bp->b_dev.d_minor&03]; p = &mt->m_lastrec; if (bp->b_blkno > *p) { bp->b_flags =| B_ERROR; iodone(bp); return; } if (bp->b_blkno == *p && (bp->b_flags&B_READ)) { bp->b_resid = bp->b_bcount; clrbuf(bp); iodone(bp); return; } if ((bp->b_flags&B_READ) == 0) *p = bp->b_blkno + 1; } bp->av_forw = 0; spl(5); if (mtab.d_actf) mtab.d_actl->av_forw = bp; else mtab.d_actf = bp; mtab.d_actl = bp; if (mtab.d_active == 0) mtstart(); spl(0); } mtstart() { register struct tape *mt; register struct buf *bp; while (bp = mtab.d_actf) { mt = &tape[bp->b_dev.d_minor&03]; if (bp != &cmtbuf && (mt->m_status&ISDU)) { bp->b_flags =| B_ERROR; mtab.d_actf = bp->av_forw; iodone(bp); continue; } mt->m_status =& ~ISWRITING; if (bp == &cmtbuf) mtab.d_active = SCOM; else if (bp->b_blkno == mt->m_blkno) { mtab.d_active = SIO; if ((bp->b_flags&B_READ) == 0) { mt->m_status =| ISWRITING; /* * According to the Interdata tape manual, * when writing the first block it is necessary * to write a file mark first and backspace * over it. If this is not done, the block * is sometimes not written correctly. */ if (mt->m_status&ISBOT) mtab.d_active = SBOT; } } else if (bp->b_blkno > mt->m_blkno) mtab.d_active = SSFOR; else mtab.d_active = SSREV; selchreq(NSELCH# /* * Interdata 800 bpi mag tape driver * * This is a 'first attempt' at a driver, and should be thrown * away and rewritten. The major known problems are: * - it probably won't work for multiple transports * - attempting a backspace from loadpoint will hang up the controller * (this can be cleared manually by a reset/forward/reset/online * sequence) * - error checking, particularly for end-of-tape, is insufficient * */ #include "param.h" #include "conf.h" #include "user.h" #include "buf.h" #include "selch.h" /* Configuration */ #define NTAPES 1 #define NSELCH 0 /* connected to selch 0 */ char mtaddr[] { 0xc5 }; #define NMTERR 8 /* number of error retries */ int mtio(), mtscintr(); struct tape { int m_status; /* status of transport */ int m_blkno; /* current block position in file */ int m_lastrec; /* next record # at end of file */ } tape[NTAPES]; #define ISOPEN 01 #define ISDU 02 #define ISWRITING 04 #define ISBOT 010 struct devtab mtab; #define SCOM 1 #define SSFOR 2 #define SSREV 3 #define SIO 4 #define SBOT 5 struct selchq mtselchq { &mtio, &mtscintr, 0 }; struct buf rmtbuf, cmtbuf; int mtead; /* * Tape controller commands */ #define ENABLE 0x40 #define CLEAR 0x20 #define READ 0x21 #define WRITE 0x22 #define WF 0x30 #define RW 0x38 #define FF 0x23 #define BF 0x13 #define BR 0x11 #define OPEN 0xff /* * Tape status */ #define ERR 0x80 #define EOF 0x40 #define EOT 0x20 #define NMTN 0x10 #define BSY 0x04 #define DU 0x01 mtopen(dev, flag) { register struct tape *mt; register unit; if ((unit=dev.d_minor&03) >= NTAPES || (mt = &tape[unit])->m_status & ISOPEN) { u.u_error = ENXIO; return; } mt->m_status = mt->m_blkno = 0; mt->m_lastrec = 1000000; mtcommand(dev, OPEN); if (mt->m_status & ISDU) u.u_error = ENXIO; if (u.u_error == 0) mt->m_status =| ISOPEN; } mtclose(dev, flag) { register struct tape *mt; register writing; mt = &tape[dev.d_minor&03]; writing = 0; if (mt->m_status&ISWRITING) { writing++; mtcommand(dev, WF); mtcommand(, &mtselchq); return; } } mtio() { register struct buf *bp; register addr; register stat; trace(0100<<16, "mtio", mtab.d_active); if ((bp = mtab.d_actf) == 0) return; addr = mtaddr[bp->b_dev.d_minor&03]; switch(mtab.d_active) { case SCOM: if (bp->b_blkno == OPEN) { register struct tape *mt; mt = &tape[bp->b_dev.d_minor&03]; oc(addr, CLEAR); oc(addr, ENABLE); if ((stat = ss(addr))&DU) mt->m_status =| ISDU; if (stat&EOT) mt->m_status =| ISBOT; mtab.d_active = 0; } else oc(addr, bp->b_blkno); trace(0200<<16, "mtoc", bp->b_blkno); trace(0200<<16, "status", ss(addr)); mtab.d_actf = bp->av_forw; iodone(bp); selchfree(NSELCH); return; case SSREV: oc(addr, BR); trace(0200<<16, "mtoc", BR); trace(0200<<16, "status", ss(addr)); return; case SBOT: oc(addr, WF); trace(0200<<16, "mtoc", WF); trace(0200<<16, "status", ss(addr)); return; case SSFOR: case SIO: oc(selchaddr[NSELCH], STOP); wdh(selchaddr[NSELCH], bp->b_addr); wdh(selchaddr[NSELCH], bp->b_addr + bp->b_bcount - 1); trace(0200<<16, "mtrw", bp->b_addr); if ((bp->b_flags&B_READ) || mtab.d_active == SSFOR) { oc(addr, READ); oc(selchaddr[NSELCH], READ_GO); } else { oc(addr, WRITE); oc(selchaddr[NSELCH], GO); } } } mtscintr(dev, stat) { oc(selchaddr[NSELCH], STOP); mtead = (rdh(selchaddr[NSELCH])+1) & ~01; } mtintr(dev, stat) { register struct buf *bp; register struct tape *mt; register op; trace(0200<<16, "interrupt", dev); trace(0200<<16, "status", stat); /* * If NMTN status is not set, wait for another * interrupt. NMTN should be the last bit to set. */ if ((stat&NMTN) == 0) return; op = mtab.d_active; mtab.d_active = 0; if ((bp = mtab.d_actf) == 0) return; if (op == SCOM) { mtstart(); return; } selchfree(NSELCH); mt = &tape[bp->b_dev.d_minor&03]; mt->m_status =& ~(ISBOT|ISDU); if (stat&DU) { mt->m_status =| ISDU; mtab.d_actf = bp->av_forw; bp->b_flags =| B_ERROR; iodone(bp); mtstart(); return; } if (op == SSREV) mt->m_blkno--; else mt->m_blkno++; if ((stat&ERR) && op == SIO) { deverror(bp, stat, dev); if (++mtab.d_errcnt < NMTERR) { mtab.d_active = SSREV; selchreq(NSELCH, &mtselchq); return; } bp->b_flags =| B_ERROR; } if (op == SIO || (stat&(EOF|EOT)) && op == SSFOR) { mtab.d_errcnt = 0; mtab.d_actf = bp->av_forw; bp->b_resid = stat&(EOF|EOT) ? bp->b_bcount : bp->b_bcount - (mtead - bp->b_addr); iodone(bp); } mtstart(); } /* * Raw magtape interface */ mtread(dev) { mtseek(dev); physio(&mtstrategy, &rmtbuf, dev, B_READ); } mtwrite(dev) { mtseek(dev); physio(&mtstrategy, &rmtbuf, dev, B_WRITE); } /* * Kludge to ignore seeks on raw mag tape by making block no. look right */ mtseek(dev) { register struct tape *mt; mt = &tape[dev.d_minor&03]; mt->m_lastrec = (mt->m_blkno = lshift(u.u_offset, -9)) + 1; } /* * Stty call is used to issue commands to raw mag tape * First word is command function; other two must be 0 */ char mtcmds[8] { /* command functions */ FF, /* 0 - forward space file */ BF, /* 1 - back space file */ 0, /* 2 */ WF, /* 3 - write file mark */ READ, /* 4 - forward space record * (since there is no FR command, we simply * do a read without starting up the selch * and ignore the overrun error) */ BR, /* 5 - back space record */ 0, /* 6 */ RW /* 7 - rewind */ }; mtsgtty(dev, v) int *v; { register fn, cmd; register int *ap; /* Ignore gtty */ if (v) return; ap = u.u_arg; if ((fn = *ap) < 0 || fn > 7 || !(cmd = mtcmds[fn]) || ap[1] || ap[2]) { u.u_error = ENXIO; return; } mtcommand(dev, cmd); } r10 r11 r12 r13 r14r15sprfclock"L.1(L2display callout L3L4(L58spl L6L7dL8L9L10L11u L12incupc L13L14lbolt L15L1time L16Ztout L17wakeup L18runrun proc L19L20dL22\L23L24L25L26\setpri L27:L28\curpri L21\runin L29L30issig L31psig timeout"L.2,L33L34L35$L36.L37.L38RL32tdata.o*@adcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprftrbuff#proc$canonb$coremap$ swapmap$ root                           ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7eclock.o p(ЇXXPA@X@C0X !&X #3&"%Q X@B0n$PA@X@B XX C0X B X PXA&CX P C0X P X P &&CXTB0,$Q@X@C0@PXXPA@#$Q@X@t & !6 ' X@&P@dBX@B0$Q@Q@$Q@!5$Q@$PA@X@Y@B0X@Y@!9@PA@$T@B0@&@@PA@C C0 #6 &  #(  #$ ӫɠdC BɠB :PA@ӫɠ##ʠ B0Y@#@&@ʰ$C`@C0$@@PA@XTB02$P@0P@A@#4A@X@tPA@$P@юp(p,Ї X4$PA@PX C0X !%[&" X P X #3&"BX P X P X P 'CPX,P X0P XPA@ю p,y999Y99)()(9)I9adcladcr0r1r2r3r4r5r6r7r8r9 dir$ 0cputype$ 4execnt$ 8lbolt$ C6X@P@CD$PX@PA@BX@PX@PA@C $PX@PA@BX@PX@PA@CX@!hB*$CX@Z@ #6&CC`X@$ B0&X@P@X@XP@X@P C@X@X@t$C.A@%P@C' ) X@$#юp(ttttttttt(RVlcoreyxyx9iiiyxyx9Iiiiiiiii i  iiiiiii)9iyiiiiiiiiiiiiiiiyxyxiiiiii9ii9i9yi    ihihihyiiiadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfipc$signal"L.1(proc L2L3 B0& #7 B0  #%Pӽ$CɰBrX$PA@  't$P$PPA@&tC\'tXX P@ P$PA@&tXX C0F B02'x$P X PPX PA@&xB0PZ & X'x$P X PPX PA@&xB0J'tX PX&$P@PA@&tP  $ Cl@ PA@ю p,p8ЇX@ !7@P@ 'tX4P@ P$PA@&t@PA@X@PA@$@X@ $P@ 2ʰ$! B0& C0ӫɠ##ʠ #P@ 'B0X@ !9P@ A@CX@ P@'tX P@ P$PA@&tX PA@A@ C0  @`PA@$#юp8p8Ї$P $Q@X@#$P@" C( !6X !3P X Y@C0$CX !9@ PA@X@tP$ $   X P   X P X@P X P $ 4C&X#6 & "XX C0 &  & X@&@PA@X P@tXXX PPP@PA@PXB0N$ XP @`PA@'t$P$PPA@&t  $ CX@XP@PA@'tXXPXTP@(PA@&tXLP@5PA@X(P@>PA@@LPA@$C@P0PA@B0C$C$C$C$@mXTPTX,İ?B0jXXPA@$QXPA@ #3?İ?$YC&PA@P@4&CC.$YC$XXPA@P@4$QX&C't P@QP$PA@&tX@4P@X PA@#5$@m@mdC&@mC0XTPT@mP0Cf$CL$PX@tPA@Cf$C,$C&$C C'B BX@PX@tPA@A@#4A@X@tPA@юp(p(Ї$@@XPA@X(A$@юp(p(Їd@mюp(p(Їюp( zzzzzzz$*z06ztrappswUseg = %x PSW = %x %x SP = %x trap type %d trapsvc    Y))yadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfregloc#trap"L.1(L2dtrace L3L4hu L6L7zka6 L8printf L9(L105L11>L12Lpanic L13L5L14fptrap L15L16$L17*L180L196sysent L20fuiword fuword L21L22L23L24L25L26L27L28L29Qtrap1"L30NL31L32~L33psignal L1L34L35L36L10001issig L37psig setpri L.2(savu L38Dnosys"NL.3(L39bnullsys"lL.4(L40vsysent.o0YXihyx )(98IHYXihyx  )(98IH YXihyx                   adcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfsysent#nullsys rexit fork read write open close wait creat link unlink exec chdir gtime mknod chmod chown sbreak stat seek getpid smount sumount setuid getuid stime ptrace nosys fstat smdate stty gtty nice sslep sync kill getswit dup pipe times profil setgid getgid ssig sys1.o" L pDЇ$$P@PA@ C0X@B%P@PA@C$Q@%PA@P@PPA@B0XX$P$PX@8PA@P C0h$QX C0D$Q@8X &P PA@C0&$QX#'$@mC #3CC~$TC0$ &$Q" @4P@xP@|$P@$P@$@lPA@$@l@mB0$PX@4B0X@8Q@<$P@8C.X@4 !6$QCX@4#7$@mC.X@8C0$ B0 #8@mCX@8PX@X@hX @PX@8P@hX@t !7X@t$юp(p,Ї $PX@XX@tCj C0\ #6X B0N B0X Y B0<$C 2@n#8@n B0$QX@4PPA@$CX!5$@mю p,p(ЇC&X P&X@4PA@$Q@4Cюp(p(ЇX@4P@X@8P@X@swapmap malloc L4xL5Jpanic xccdec"swap L6L7\L8coremap mfree runout L9.wakeup L1.xfree"8L.2(u L11L12L13iput L10xalloc"L.38L14text L15L16:L18L19 L202L212L22xL172L23NL24gL25L26sexpand estabur readi L27savu swtch L.4(L29:L30:L28:alloc.o8pp(Ї$PX@P@X@A$PX@PA@%PA@@m#9@PA@'tPX PX PA@&tPA@P@X@P@X$ $ $ X P@X P@юp(p,Ї X,PA C0P PA@CX C X'P X PXC0'tX,PXPPA&tB0X B n & XPX,PA@XX P &'t2P & PPA@&tPA@$  PA@XPX,PA@PA@$  C,$P X,P@PA@@m$#ю p,p(ЇX(PA$  C0P PA@C'tX(PX,PPA&tB0X !'$P $P X 2Bt & X,PX(PA@XX P &'t2PP & PA@&t$P PA@$  PA@X,X&P P $ юp(p(ЇX(X,X & !%UBX0P@PA@$#$#юp(p8ЇX8PAF C0P PA@CX C rX'P XPXPX8PA@ !4$C~X B0$& 8 #&$P &" $  CRPA@C & $P$PXY CX&PX8PA@X$PXC$QX XB0n$P X PC:X <X@Y8B0X <X@YC0,$Q CXX&P PX 2#QCdPA@X 2#$QC$  PA@X B hX8P@PA@@m$#юp8p(ЇX(PA@ B0*X 2CX,X&P P$ юp(p(Ї`CbX C0TX Y(B0HXXXX2!%Ű2C $X(P@PA@$P $P  C&C@PA@юp(p(ЇX@B0$Q@`CX C0XX C0v B0l B0b B0X$PX PA@$ X@P X@P 'tPX PPA@&tPA@&C`C> B0*  @PPA@PA@L.3(L14\L15L13TL16L176bwrite L.4(L10000L19L20L18ialloc"L.58L22L23L24L25diget L26*L21L27VL286L29Jiput 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~  L30zL31dL33L34FL35:L36L37inode L10001L39:L38L32ZL40ifree"L.6(L41L.7(L43L44L46~L10002TL47xL48L42L45~L49update"L.8(updlock L50L51L52`L54ZL53ZL55fL56L58iupdat prele L57bflush conf.o PYXYXihyxYXYX )(98IHYXYXYXihYXYXYXyxYX )(98IHYXYXYXihadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfbdevsw#nulldev dskstrat dsktab mtopen mtclose mtstrate mtab msmstrat msmtab nblkdev$cdevsw#4vduopen vduclose vduread vduwrite vdusgtty mmread mmwrite dskread dskwrite nodev syopen syread sywrite sysgtty mtread mtwrite mtsgtty lpopen lpclose lpwrite lpsgtty msmread msmwrite nchrdev$fio.o`H(<`p(ЇX( BCX@ #3 #$ @m$#юp(p(ЇX( C0,XX P  &PA@ &PA@ B  PX PA ' юp(p(ЇX(Xӽ B fX `C@X,PPX@AC8X,PPX@AC@$P@0&Y 3X PA@юp(p(ЇX(XӽX `CTY@CfX,PPX@ACBY@C:X,PPX@AC@lessx8greatxFldiv#Llrem#Zlshift#frshiftnocarrymain.o3Hpp(Ї$P@X@X& U@C>PA@$Q@$Q@'tP$P@PA@&t&C'tX@$PX@$P@PA@&t@PA@@PA@@PA@@#PA@@:PA@PX@PA@P@'tX@PX@P@PA@&tA@X@XP@$P@$@@@@P@tA@A@A@$PX@PA@P@X@$PX@PA@P@X@A@C0P$ PA@'x$P $P$P$PA&x'tP$P@PA@&t#A@юp(p(ЇX@tXX@tX #4XX@@'B' T #3 # Z P Cюp(p0ЇXX0Z4Z8&Y@B &$X0B  0P &Q0CX0C0 X00P &$X4B  P &Q4CX4C0" X4P &Z4#$P &"Z8X8B Q8' P CX8C0"[8' X8P A $#$ @m%#юp0p(ЇX(#юp(Memory = %l.%l K RESTRICTED RIGHTS Use, duplication or disclosure is subject to restrictions stated in Contracts with Western Electric Company, Inc. and University of Wollongong. iy))))))y )9II)9Yy adcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfmain"L.1(updlock ka6 L2(memtop L3tclearseg maxmem freemem coremap mfree L4nL5printf L6L7L8L9#L10:min swplo nswap swapmap clkstart proc u cinit binit iinit rootdev iget rootdir newproc L11bexpand estabur"icode copyout L1hsched sureg"rL.2(L13uisa L14L15L10000L10001L12L.30L17jnseg"L18LL19xL20L21L22L23L24L25L26 L278L28bL16vL.4(L29malloc.oHx@p(ЇX(X C0bX U,BPXX,Q X [,P B0&X P @X P @ L7JL8Xcoremap L10nL1|L4rmfree"L.2(L12L13L14L15L16&L17"L18L19"L20L21TL22L23L26\L24tL25L11nami.o xp0ЇX@X0A/!4X@X PX PA@/!7X0A" B0X4#7$@mC@mB0 !4 CX `@#8@mC@PPA@B0/C0. C0(@mB0#&X0AC#$ &"/!7X0A"@mB0<$P@$P@$@l$P PX PA@P@|$PX@|B0xX#8XPA@X4B0L B0FPPA@B0P@X #9X P@#  $C$@mCzT@B0XX#8XPA@'t'tPX@PA@&tPPA@&tPX PA@PXXX @  C &&" Q@%Q@|X@B0X !6X@P CC"@  B0&CX#8XPA@X4B0$ B0PPA@B0@ CHX PPA@X@PXPA@ !4$CCPA@$#юp0p(ЇX@&P@#юp(p(ЇX@&P@PA@!6j@m #юp(iiii)ihiihihiiiiii)iiiiiIYiihihiiiiihihiih)iiiiiiiadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfnamei"L.10u L2&rootdir iget L3X4X PA@!4$C^X $XZ4PCPX PA@XXB0X8'PX XB0HX PA@P!9PA@$CXX$X." ,PPA@C PA@PX PA@PXXX8PX XB0FX PA@PC0.XX$X PXPA@PA@#PA@$P@X#X XP@ #юp4p(Ї@l#:X(X@xC,X(PX@xPA@#j@m%C2%Q@|$Q@!5$Q@$Q@xX@|!3%#$#юp(p(ЇX@|!4%Cf@l#8X@xC$X@xPA@#j@m%C*%Q@|$Q@!5$Q@$Q@x #юp(p(Ї@mюp(p(Їюp(p(ЇX(X,X0X P &&' 7юp(y  99   99yyyiyyyyyyyyyy)yyyyyyadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfbmap"L.14L22u L1L3TL4alloc L5dL6nL7L8bdwrite L9TL10&rablock L11NL12nL13L14L15bread L16rL17JL18(brelse L19jL20L21L22passc"L.2(L246L25bsubyte L26bL23L27|L10000L10001cpass"L.3(L29L28L30L31fubyte L32L33 nodev"&L.4(L34:nulldev"DL.5(L35Nbcopy"XL.6(L39nL37zL38~L36~bio.op!p d( Pp(ЇX,PX(PA$T #4 C4X P P P*X@APA2 #юp(p(ЇX($X,PPAB0DX,PPA$T B0(X P P P*X@AX0C0dX0PPAbB0NX0PPA$T #7PAVC(X P P P*X@A B0X,PPA#PA. #юp(p(ЇX(XX xP P PX@AB0PAPAC#8X P #PAHюp(p(ЇX(X@ #54`!7PA"CX P PA6юp(p(ЇX(X P PAюp(p(ЇX(@T #6PA@@T@40C0 X@40P@40@40PA@$T #4% $PA@T C0(4L21bL22L23\ttyinput L24^L25L26bL27^L28hL29^wakeup L30L31mL32rL33wL34L35dsk.o%dXp(ЇX('tP@PPA@&t B"X P X P ,PA@C X $&@B0X #7X P X P ,PA@CX$$PX$0$P ,!$Q , D$PA@X C06X C0X Y ##$#$CX Y #$#$#4CP P B0"@ 0B0@P$PA@$PA@юp(p(Ї$X@ P$P %W P ӡ@PA@Ð#2" X Y B02 B0ÐC0'tPPPAp&t%P C|CÐC0($ 'tPP:PA@&tCÐbC0$ 'tPPPA&tC $ X PPA@BPPA@'tP@PPA@&t'tX P@PPA@&t#CY@ CX #7X P P,$ X P PA@Aюp(p(ЇX(X'tX0PX,PPA@&t &  C $$ X P X P PA@юp(p(Ї'x$P X(P@ PPA@&xюp(p(Ї'x$P X(P@ P|PA@&xюp(rdstrategydstartseekcyldiosectorinterruptstatusinterruptstatuscylovi i9II9 IIII  II YYadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfcntladdr#dskaddr#rdskbuf$ dsktab$ 0dsk$ Ddskscq#dskstart"rdskscint"dskstrat"L.1(L2dtrace L3^iodone L1hL4L5L6spl L7L8(L10000L10001L10002 L10003L10004L10005L9\selchreq L.2(L11L12L15L16L17L18L19L20ss L21L22PL23Jdskerror"L24dsknrdy"timeout L25wh oc L26L27L13L14(L28~lpopenlpclose({)}!|^~'`lpstartlpstatlpcharlpstatlpintlpwakeuplpoutputlpsleep Yadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprflpaddr#4lp$lpopen"L.1(L10000.ss L2:u L1L3dtrace L4oc lpcanon"lpclose"L.2(L6L5lpwrite"L.3(L8cpass L9L7L.4(L114L12Llpoutput"L10TL13L14nL15L16L17tL18L19L21:L22L23L24L10001L25>L26L27 L286L29>L30ZL31^L32nL33rL34~L35L36L37L38L39L40L41.L42L43L20TL100038L10004\L10005Flpstart"^L.5(L45L46L47L48"getc L49wd L50L44Blpint"LL.6(L52L53L54L55wakeup L51L.7(L57spl L580L59L60sleep putc L56lpsgtty"L.8(L62L61*mem.ob08p,Ї /C0fX@P/B0X@PPA@B02XU@C$@mB0XPA@Cю p,p,Ї /B0,X@|$P@|Q@xP@PA@CdX@PA@BN@mB0B/B0X@PPA@B0XU@#XCю p, Iyadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfmmread"L.1,L1|L4u L10000Jkisa lraddr L3|memtop L2XL10001|passc mmwrite"L.2,L6dpadd L5,L7cpass L8,L10002msm.o`dp(ЇX(X P , BX P PA@CX@U$B (X #7X P PA@C^$P $PA@X@ P@ X@ T!5P@ T#X@ XP P@ X@ H!3A$PA@юp(p(ЇX@ TC0@ H&@ H'tP@PPA@&t@P@ X@Z$P@  P@  P@ X P@ X Z 'P@ @P$PA@юp(p(Ї'tX@ P@PPA@&t'tX@ P@PPA@&t$Q@ X@ PX@ PA@PX@ PA@BPX@ PA@юp(p(Ї'tX(P@PPA@&t'tX,P@ PPA@&tX@ TC0`X@ C0V$P@ ;T,C0"'tX@ PX,PPAT&tC $T #6pȰA#PȰB'tP@ PPA@&t'tX@ P@ PPA@&t'tX@ P@ PPA@&tHP@PA@'tX@ P@ PPA@&t'tX@ P@ 'PPA@&tX@ P@PA@X@ P@PA@X@ PX@ PA@PX@ PA@X@PA@!2" X@ PX@PA@X@  Z@ PX@PA@X@ PX@ PA@PX@ PA@X@PA@!2" PX@PA@P@PA@юp(p(ЇHP@PA@юp(p(Ї'tX(P@ .PPA@&t'tX,P@ 8PPA@&tX@ TC0X@ B0T,C08$PX@PA@'tX@PX,PPAP&tC@$P ,T,C0$PX@PA@HP@PA@@PA@[@ &Q@ 'tX@ P@ ?PPA@&t$P@ P@ X@ [@ P ,X@ &P@ X,Z, #AC`CX #7X P $@ I$@ HX P@ TX@ P@ PA@$PA@Atюp(p(ЇX('tX0PX,PPA@&t@ I&@ I !%ACN$@ IX P $@ HX P@ TX@ P@ PA@$PA@Aюp(p(Ї'x$P X(P@ \PPA@&xюp(p(Ї'x$P X(P@ \P~PA@&xюp(X%%%Kmstartseekcylinterruptstatusmcmdheadsectorbufstartbufendinterruptstatuscyl ovyy9I9999999y99yyyy99yy9yyiiadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfmsmcntl#msmaddr#msmtab$ Hrmsmbuf$ \msmscq#msmseek"msmscint"Xmsmdrive$ msmcyl$ msmhead$ msmsecto$ msmsad$ msmead$ msmseekf$ msmqlen$ msmap#msmstrat"L.1(L2>iodone L1L3~L4pspl L5L6L7msmstart"L.2(L8L9dtrace selchreq L.3(L11L12wh oc L10msmintr"L.4(L14L15 L13NL16.msmerror"|L17@L18HL19 L20 L21 selchadd L22 L23 'wdh L24ss L25wd L26L27&L.5(L28zmsmcintr"L.6(L30 .L31 8L29rL322L330rdh L34 ?L35L360L370selchfre L.7(deverror L39L38msmread"L.8(physio L40Pmsmwrite"ZL.9(L41mt.o f x Pp(Ї+C$ $T #7$@mCN$P P B@P PX(PA$T #5$@m@m!7X P юp(p(Ї+$ $$T C0*&0PX(PAb0PX(PAN+C0 C0PX(PA(C8PX(PA$P юp(p(Ї'tX,P@ P@PA@&t \$PA@$T C0"X @P PPA@CX P $PA@X(P X,P $PA.PA@@T #6PA@$P юp(p(ЇX( \C0$ &X $U C X P PA@CX $Y B0*$T C0 X P ,PA@PA@C^$T !6X $&P $P $PA@X@ $#7X@ (P #P@ $P@ (@ !3A$PA@юp(p(ЇX@ $C0$ \C0.$T C0$X P X P@ $PA@CX P \!7$@ CZX $Y B02$@ $T B0X P $T #5$@ CX $U #&$@ #$@ @ P$PA@#Cюp(p(Ї't@ P@ P@PA@&tX@ $C0@ @ CX $B0r$ PPA@@PPA@PA@ð#7X P ð #7X P $@ # X $PPA@'tX $P@ PPA@&t'tPA@P@ PPA@&tX P@ $PA@$PA@CPPA@'tP@ PPA@&t'tPA@P@ PPA@&tCf0PPA@'t0P@ PPA@&t'tPA@P@ PPA@&tCHP@PA@X P@PA@X Z 'P@PA@'tX P@ PPA@&t$T !8@ B0.!PPA@pP@PA@C*"PPA@PP@PA@C'!)!X@ юp(p(ЇHP@PA@@PA@&P@ юp(p(Ї'tX(P@ PPA@&t'tX,P@ PPA@&tT,C0zӰ@ $@ X@ $C0bɰ!5ACT$PA@$ X P $T,C04X P X P@ $X P PA@ACɰ!5%Q #$Q T,C0jɰB0b'tX(PX,PPA@&t@ &@ C"$@ @ P$PA@ClX P ɰC0`T,C0HɰB0@$@ X P@ $`T,#4X # X X@ [ P ,PA@Aюp(p(ЇX(PA~'x$P X(P@ ,PxPA@&xюp(p(ЇX(PA4'x$P X(P@ ,P.PA@&xюp(p(Ї+$ % P@PA@P &P юp(p(ЇX,B0F4XBB  @ #7X !4X #6$@m# PX(PAюp((J P #0!8mtcommandmtiomtocstatusmtocstatusmtocstatusmtrwinterruptstatus 9 Yy        u !"STLMNOPABCIJ 45/0-2.13689: d()) yyadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfmtaddr# tape$ mtab$ mtselchq# mtio"mtscintr"(rmtbuf$ ,cmtbuf$ \mtead$ mtopen"L.1(L100000L2t_flags&RAW)) { if (tp->t_state&SUSPEND) { tp->t_state =& ~SUSPEND; wakeup(&tp->t_outq); ttstart(tp); } } else ttyinput(c, tp); } vduxint(waddr, stat) { register struct tty *tp; register c; tp = &vdu[(waddr-vdubase)>>1]; if (!(tp->t_state & ISOPEN)) return; trace(0100, "wint", waddr); trace(0100, "stat", stat); tp->t_state =& ~BUSY; ttstart(tp); if (tp->t_outq.c_cc <= TTLOWAT && (tp->t_state&ASLEEP)) { tp->t_state =& ~ASLEEP; wakeup(1 /* command 2 */ #define CLKA 0000 #define CLKB 0100 #define CLKC 0200 #define CLKD 0300 #define CMD2 0070 /* Status */ #define CARR_OFF 0002 #define BSY 0010 /* * open routine: * called each time a process opens a terminal as a character file * * - if the terminal was previously inactive, set up the initial status * and arm interrupts */ vduopen(dev) { register struct tty *tp; if (dev.d_minor >= NVDU) { u.u_error = ENXIO; return; } tp = &vdu[dev.d_minor]; tp->t_dev = dev; if ((tp- radd + 1; oc(radd, cmd2); oc(radd, EN | DTR | CMD1); oc(wadd, EN | DTR | WRT | CMD1); stat = ss(radd); if ((stat&CARR_OFF) == 0) tp->t_state =| CARR_ON; trace(0100, "vduenab", stat); rd(radd); } /* * Disarm interrupts from PALS */ vdudisab(dev) { register radd, wadd; radd = vdubase + dev.d_minor*2; wadd = radd + 1; oc(radd, DIS | CMD1); oc(wadd, DIS | WRT | CMD1); trace(0100, "vdudisab", ss(radd)); } rablkno && !incore(dev, rablkno)) { rabp = getblk(dev, rablkno); if (rabp->b_flags & B_DONE) brelse(rabp); else { rabp->b_flags =| B_READ|B_ASYNC; rabp->b_bcount = 512; /***/ (*bdevsw[adev.d_major].d_strategy)(rabp); } } if (rbp==0) return(bread(dev, blkno)); iowait(rbp); return(rbp); } /* * Write the buffer, waiting for completion. * Then release the buffer. */ bwrite(bp) struct buf *bp; { register struct buf *rbp; register flag; rbp = bp; flag = rbp->b_flags; rbp->b_fla2$P $P T C0X P  &PA@PA BRX P $P &PA@Cz$P@X P@PA@X@P PAюp(p(ЇX(XX@|PA B0PAH$P@|C C,PA( @m$ PX@tPA@CX B0,X P PA$P &PA@Cn$P@X P@[@PPA@P@|[@|PA@PAT C0X P  &PA@Cюp(p(ЇX( C0  $PPA@C  юp(p(ЇX( C0 PA@юp(iyY&tp->t_outq); } } /* * Arm interrupts from PALS and set baud rate */ vduenab(atp) struct tp *atp; { register struct tp *tp; register radd, wadd; register cmd2, stat; switch ((tp = atp)->t_speeds&0377) { case B300: cmd2 = CLKA | CMD2; break; case B1200: cmd2 = CLKB | CMD2; break; case B2400: cmd2 = CLKC | CMD2; break; case B4800: cmd2 = CLKD | CMD2; break; default: /* Use low-core 'console' definition */ cmd2 = conscmd2; } radd = vdubase + tp->t_dev.d_minor*2; wadd =>t_state& ISOPEN) == 0) { tp->t_state = ISOPEN | SSTART; if (tp->t_flags == 0) tp->t_flags = XTABS | LCASE | CRMOD | ECHO; tp->t_erase = CERASE; tp->t_kill = CKILL; tp->t_addr = vdustart; vduenab(tp); } spl(4); while (!(tp->t_state&CARR_ON)) sleep(&tp->t_rawq, TTIPRI); spl(0); if (u.u_procp->p_ttyp == 0) u.u_procp->p_ttyp = tp; } /* * close routine: * - called only when last process using terminal releases it */ vduclose(dev) { register struct tty *tp; tp = &vdu[dev.d_minor]; ree buffers ***/ /* * Declarations of the tables for the magtape devices; * see bdwrite. */ extern int mtab; int httab; /* * The following several routines allocate and free * buffers with various side effects. In general the * arguments to an allocate routine are a device and * a block number, and the value is a pointer to * to the buffer header; the buffer is marked "busy" * so that no on else can touch it. If the block was * already in core, no I/O need be done; if it is * already busy, thgs =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI | B_AGE); rbp->b_bcount = 512; /***/ (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp); if ((flag&B_ASYNC) == 0) { iowait(rbp); brelse(rbp); } else if (flag & B_DELWRI) rbp->b_flags =| B_AGE; else geterror(rbp); } /* * Release the buffer, marking it so that if it is grabbed * for another purpose it will be written out before being * given up (e.g. when writing a partial block where it is * assumed that another write for the same block will soon fol )9YYadcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfpipe"L.1,rootdev ialloc L1falloc L2t_state = 0; vdudisab(dev); } /* * read, write, stty, gtty routines: * - call standard tty routines */ vduread(dev) { ttread(&vdu[dev.d_minor]); } vduwrite(dev) { ttwrite(&vdu[dev.d_minor]); } vdusgtty(dev, v) { register struct tty *tp; tp = &vdu[dev.d_minor]; ttystty(tp, v); /* Stty - reissue CMD 2 to change baud rate */ if (v == 0) vduenab(tp); } /* * vdustart routine - called when there might be something to send * to the terminal */ vdustart(atp) struct tty e process waits until it becomes free. * The following routines allocate a buffer: * getblk * bread * breada * Eventually the buffer must be released, possibly with the * side effect of writing it out, by using one of * bwrite * bdwrite * bawrite * brelse */ /* * Read in (if necessary) the block and return a buffer pointer. */ bread(dev, blkno) { register struct buf *rbp; rbp = getblk(dev, blkno); if (rbp->b_flags&B_DONE) return(rbp); rbp->b_flags =| B_READ; rbp->b_bcount = 512; /***/low). * This can't be done for magtape, since writes must be done * in the same order as requested. */ bdwrite(bp) struct buf *bp; { register struct buf *rbp; register struct devtab *dp; rbp = bp; dp = bdevsw[rbp->b_dev.d_major].d_tab; /***/ if (dp == &mtab || dp == &httab) bawrite(rbp); else { rbp->b_flags =| B_DELWRI | B_DONE; brelse(rbp); } } /* * Release the buffer, start I/O on it, but don't wait for completion. */ bawrite(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; 0wakeup prele"L4sleep readi writep"L.3(L10L11L9L12psignal L13Jmin writei L14L.4(L16L17L15 L.5(L19RL18Rselch.o0(p(Ї'tX,P@P PA@&tX(X #8Y,r-vdubase)>>1]; if (!(tp->t_state & ISOPEN)) return; trace(0100, "rint", raddr); trace(0100, "stat", stat); c = rd(raddr)&0177; trace(0100, "char", c); if (stat & CARR_OFF) { if (tp->t_state & CARR_ON) { signal(tp, SIGHUP); flushtty(tp); } tp->t_state =& ~CARR_ON; return; } if (!(tp->t_state & CARR_ON)) { tp->t_state =| CARR_ON; wakeup(&tp->t_rawq); return; } /* * Carousel DC4 / DC2 (suspend / resume) signals */ if (c == '\024' && !(tp->t_flags&RAW)) tp->t_state =|# #include "param.h" #include "conf.h" #include "tty.h" #include "user.h" #include "proc.h" /* * Vdu driver -- local terminal on PALS * */ #define NVDU 16 /* number of local terminals */ int vdubase 0x10; /* lowest PALS address */ extern char conscmd2; /* PALS command 2 for 'console' */ struct tty vdu[NVDU]; int vdustart(), vdurint(), vduxint(), ttrstrt(); /* * PALS commands & status bits */ /* command 1 */ #define DIS 0200 #define EN 0100 #define DTR 0040 #define WRT 0002 #define CMD1 000*atp; { register struct tty *tp; register c, waddr; tp = atp; waddr = 2*tp->t_dev + vdubase + 1; trace(040, "vdustart", waddr); if ((tp->t_state&(TIMEOUT|BUSY|SUSPEND|CARR_ON)) != CARR_ON || (c = getc(&tp->t_outq)) < 0) return; if (c > 0177) { tp->t_state =| TIMEOUT; timeout(ttrstrt, tp, c&0177); } else { tp->t_state =| BUSY; c =| partab[c]&0200; wd(waddr, c); trace(0100, "wrt", ss(waddr)); } } vdurint(raddr, stat) { register struct tty *tp; register char c; tp = &vdu[(radd (*bdevsw[dev.d_major].d_strategy)(rbp); iowait(rbp); return(rbp); } /* * Read in the block, like bread, but also start I/O on the * read-ahead block (which is not allocated to the caller) */ breada(adev, blkno, rablkno) { register struct buf *rbp, *rabp; register int dev; dev = adev; rbp = 0; if (!incore(dev, blkno)) { rbp = getblk(dev, blkno); if ((rbp->b_flags&B_DONE) == 0) { rbp->b_flags =| B_READ; rbp->b_bcount = 512; /***/ (*bdevsw[adev.d_major].d_strategy)(rbp); } } if ( rbp->b_flags =| B_ASYNC; bwrite(rbp); } /* * release the buffer, with no I/O implied. */ brelse(bp) struct buf *bp; { register struct buf *rbp, **backp; register int sps; rbp = bp; if (rbp->b_flags&B_WANTED) wakeup(rbp); if (bfreelist.b_flags&B_WANTED) { bfreelist.b_flags =& ~B_WANTED; wakeup(&bfreelist); } if (rbp->b_flags&B_ERROR) rbp->b_dev.d_minor = -1; /* no assoc. on error */ sps = spl(6); if(rbp->b_flags & B_AGE) { backp = &bfreelist.av_forw; (*backp)->av_back = rbp; rbp { register struct buf *bp; register struct devtab *dp; extern lbolt; trace(0x2000, "getblk", blkno); if (dev >= 0 && dev.d_major >= nblkdev) /***/ panic("blkdev"); loop: if (dev < 0) dp = &bfreelist; else { dp = bdevsw[dev.d_major].d_tab; if(dp == NULL) panic("devtab"); for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) { if (bp->b_blkno!=blkno || bp->b_dev!=dev) continue; spl(6); if (bp->b_flags&B_BUSY) { bp->b_flags =| B_WANTED; sleep(bp, PRIBIO+1); spl(0); associated with a buffer. */ clrbuf(bp) int *bp; { register *p; register c; p = bp->b_addr; c = 128; /***/ do *p++ = 0; while (--c); } /* * Initialize the buffer I/O system by freeing * all buffers and setting all device buffer lists to empty. */ binit() { register struct buf *bp; register struct devtab *dp; register int i; struct bdevsw *bdp; bfreelist.b_forw = bfreelist.b_back = bfreelist.av_forw = bfreelist.av_back = &bfreelist; for (i=0; ihe device * A buffer, which will always be a special buffer * header owned exclusively by the device for this purpose * The device number * Read/write flag * Essentially all the work is computing physical addresses and * validating them. */ physio(strat, abp, dev, rw) struct buf *abp; int (*strat)(); { register struct buf *bp; register char *base; register int nb; int ts; bp = abp; base = u.u_base; /* * Check odd base, odd count, and address wraparound */ if (base&01 || u.u_count&01 ||/* * Each buffer in the pool is usually doubly linked into 2 lists: * the device with which it is currently associated (always) * and also on a list of blocks available for allocation * for other use (usually). * The latter list is kept in last-used order, and the two * lists are doubly linked to make it easy to remove * a buffer from one list when it was found by * looking through the other. * A buffer is on the available list, and is liable * to be reassigned to another disk block, if and only for recovery) */ struct buf *b_forw; /* first buffer for this dev */ struct buf *b_back; /* last buffer for this dev */ struct buf *d_actf; /* head of I/O queue */ struct buf *d_actl; /* tail of I/O queue */ }; /* * This is the head of the queue of available * buffers-- all unused except for the 2 list heads. */ extern struct buf bfreelist; /***/ /* * These flags are kept in b_flags. */ #define B_WRITE 0 /* non-read pseudo-flag */ #define B_READ 01 /* read when I/O occurs */ #define B_DONE # /* */ #include "param.h" #include "user.h" #include "buf.h" #include "conf.h" #include "systm.h" #include "proc.h" #include "seg.h" /* * This is the set of buffers proper, whose heads * were declared in buf.h. There can exist buffer * headers not pointing here that are used purely * as arguments to the I/O routines to describe * I/O to be done-- e.g. swbuf, just below, for * swapping. */ char buffers[NBUF][516]; /***/ struct buf swbuf1; struct buf swbuf2; struct buf bfreelist; /*** queue of f goto loop; } spl(0); notavail(bp); return(bp); } } spl(6); if (bfreelist.av_forw == &bfreelist) { bfreelist.b_flags =| B_WANTED; sleep(&bfreelist, PRIBIO+1); spl(0); goto loop; } spl(0); notavail(bp = bfreelist.av_forw); if (bp->b_flags & B_DELWRI) { bp->b_flags =| B_ASYNC; bwrite(bp); goto loop; } bp->b_flags = B_BUSY; bp->b_back->b_forw = bp->b_forw; bp->b_forw->b_back = bp->b_back; bp->b_forw = dp->b_forw; bp->b_back = dp; dp->b_forw->b_back = bp; dp->b_forwb_dev = -1; bp->b_addr = buffers[i]; bp->b_back = &bfreelist; bp->b_forw = bfreelist.b_forw; bfreelist.b_forw->b_back = bp; bfreelist.b_forw = bp; bp->b_flags = B_BUSY; brelse(bp); } i = 0; for (bdp = bdevsw; bdp->d_open; bdp++) { dp = bdp->d_tab; if(dp) { dp->b_forw = dp; dp->b_back = dp; } i++; } nblkdev = i; } /* * swap I/O */ swap(blkno, coreaddr, count, rdflg) { register struct buf *bp; bp = &swbuf1; if(bp->b_flags & B_BUSY) if((swbuf2.b_flags&B_WANTED) == 0) base>=base+u.u_count) goto bad; ts = (u.u_tsize+255) & ~0377; /***/ if (u.u_sep) ts = 0; nb = base>>8; /***/ /* * Check overlap with text. (ts and nb now * in 256-byte clicks) *** */ if (nb < ts) goto bad; /* * Check that transfer is either entirely in the * data or in the stack: that is, either * the end is in the data or the start is in the stack * (remember wraparound was already checked). */ if (((base+u.u_count)>>8) >= ts+u.u_dsize /***/ && nb < (14<<8)) /**** if it is not marked BUSY. When a buffer is busy, the * available-list pointers can be used for other purposes. * Most drivers use the forward ptr as a link in their I/O * active queue. * A buffer header contains all the information required * to perform I/O. * Most of the routines which manipulate these things * are in bio.c. */ extern struct buf /***/ { int b_flags; /* see defines below */ struct buf *b_forw; /* headed by devtab of b_dev */ struct buf *b_back; /* " */ struct buf *av_f02 /* transaction finished */ #define B_ERROR 04 /* transaction aborted */ #define B_BUSY 010 /* not on av_forw/back list */ #define B_PHYS 020 /* Physical IO potentially using UNIBUS map */ #define B_MAP 040 /* This block has the UNIBUS map allocated */ #define B_WANTED 0100 /* issue wakeup when BUSY goes off */ #define B_AGE 0200 /* delayed write for correct aging */ #define B_ASYNC 0400 /* don't wait for I/O completion */ #define B_DELWRI 01000 /* don't write till block leaves available list */ ->av_forw = *backp; *backp = rbp; rbp->av_back = &bfreelist; } else { backp = &bfreelist.av_back; (*backp)->av_forw = rbp; rbp->av_back = *backp; *backp = rbp; rbp->av_forw = &bfreelist; } rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE); spl(sps); } /* * See if the block is associated with some buffer * (mainly to avoid getting hung up on a wait in breada) */ incore(adev, blkno) { register int dev; register struct buf *bp; register struct devtab *dp; dev = adev; dp = bdevsw[adev = bp; bp->b_dev = dev; bp->b_blkno = blkno; return(bp); } /* * Wait for I/O completion on the buffer; return errors * to the user. */ iowait(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; spl(6); while ((rbp->b_flags&B_DONE)==0) sleep(rbp, PRIBIO); spl(0); geterror(rbp); } /* * Unlink a buffer from the available list and mark it busy. * (internal interface) */ notavail(bp) struct buf *bp; { register struct buf *rbp; register int sps; rbp = bp; sps = spl(6); rbp->av_back bp = &swbuf2; spl(6); while (bp->b_flags&B_BUSY) { bp->b_flags =| B_WANTED; sleep(bp, PSWP+1); } bp->b_flags = B_BUSY | B_PHYS | rdflg; bp->b_dev = swapdev; bp->b_bcount = count<<8; /*** 256 bytes/block ***/ bp->b_blkno = blkno; bp->b_addr = coreaddr<<8; /*** 256 b/block ***/ /*** bp->.b_xmem = (coreaddr>>10) & 077; ***/ (*bdevsw[swapdev.d_major].d_strategy)(bp); spl(6); while((bp->b_flags&B_DONE)==0) sleep(bp, PSWP); if (bp->b_flags&B_WANTED) wakeup(bp); spl(0); bp->b_flags =& ~(B_/ goto bad; /*** *** check for passing end of stack ***/ if ((base+u.u_count)>>8 >= (14<<8)+u.u_ssize) goto bad; spl(6); while (bp->b_flags&B_BUSY) { bp->b_flags =| B_WANTED; sleep(bp, PRIBIO+1); } bp->b_flags = B_BUSY | B_PHYS | rw; bp->b_dev = dev; /* * Compute physical address by simulating * the segmentation hardware. */ bp->b_addr = base; /***/ lraddr(&bp->b_addr, uisa); /***/ bp->b_blkno = lshift(u.u_offset, -9); bp->b_bcount = u.u_count; /***/ bp->b_error = 0; u.u_porw; /* position on free list, */ struct buf *av_back; /* if not BUSY*/ int b_dev; /* major+minor device name */ int b_bcount; /*** transfer count (bytes) ***/ char *b_addr; /* low order core address */ char *b_xmem; /* high order core address */ char *b_blkno; /* block # on device */ char b_error; /* returned after I/O */ char *b_resid; /*** bytes not transferred after error ***/ } buf[NBUF]; /* * Each block device has a devtab, which contains private state stuff * and 2 list headsC08X"X,$P X #7XP$#P$P #5XAюp(p(ЇX('tX P@P PA@&tXC0XP #5XAюp(p(Ї'tX(P@P PA@&t'tX,P@P PA@&tX(XC0X,PX(PXAюp(schrequestschfreeinterruptstatus.d_major].d_tab; for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) if (bp->b_blkno==blkno && bp->b_dev==dev) return(bp); return(0); } /* * Assign a buffer for the given block. If the appropriate * block is already associated, return it; otherwise search * for the oldest non-busy buffer and reassign it. * When a 512-byte area is wanted for some random reason * (e.g. during exec, for the user arglist) getblk can be called * with device NODEV to avoid unwanted associativity. */ getblk(dev, blkno) ->av_forw = rbp->av_forw; rbp->av_forw->av_back = rbp->av_back; rbp->b_flags =| B_BUSY; spl(sps); } /* * Mark I/O complete on a buffer, release it if I/O is asynchronous, * and wake up anyone waiting for it. */ iodone(bp) struct buf *bp; { register struct buf *rbp; rbp = bp; trace(0x4000, "iodone", rbp); /*** if(rbp->b_flags&B_MAP) mapfree(rbp); ***/ rbp->b_flags =| B_DONE; if (rbp->b_flags&B_ASYNC) brelse(rbp); else { rbp->b_flags =& ~B_WANTED; wakeup(rbp); } } /* * Zero the core BUSY|B_WANTED); return(bp->b_flags&B_ERROR); } /* * make sure all write-behind blocks * on dev (or NODEV for all) * are flushed out. * (from umount and update) */ bflush(dev) { register struct buf *bp; loop: spl(6); for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) { if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) { bp->b_flags =| B_ASYNC; notavail(bp); bwrite(bp); goto loop; } } spl(0); } /* * Raw I/O. The arguments are * The strategy routine for trocp->p_flag =| SLOCK; (*strat)(bp); spl(6); while ((bp->b_flags&B_DONE) == 0) sleep(bp, PRIBIO); u.u_procp->p_flag =& ~SLOCK; if (bp->b_flags&B_WANTED) wakeup(bp); spl(0); bp->b_flags =& ~(B_BUSY|B_WANTED); u.u_count = bp->b_resid; /***/ geterror(bp); return; bad: u.u_error = EFAULT; } /* * Pick up the device's error number and pass it to the user; * if there is an error but the number is 0 set a generalized * code. Actually the latter is always true because devices * don't yet re: the b_forw/b_back list, which is doubly linked * and has all the buffers currently associated with that major * device; and the d_actf/d_actl list, which is private to the * device but in fact is always used for the head and tail * of the I/O queue for the device. * Various routines in bio.c look at b_forw/b_back * (notice they are the same as in the buf structure) * but the rest is private to each device driver. */ struct devtab { char d_active; /* busy flag */ char d_errcnt; /* error count (adcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfselchadd#selchtab$selchreq"L.1(L2dtrace L3@L4RL1L5LL6nL7tL8selchfre"L.2(L10L9L11selchint"L.3(L13L14L15vL12vsys.o\p(ЇAC0(X,PX 8P:X@AC0$@mX,PX@P@X@Aюp(p(ЇAC0X 8P:X@Aюp(p(ЇAnC0X 8P:X@ Aюp(p(ЇA4C0$X,PX 8P:X@Aюp(p(ЇX@tX !5$@m #юp(adcladcr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfsyopen"L.1(syttyp",L2 * fuword(i) - fetch a word from user address * subyte(i,a) - store byte at user address * suword(i,a) - store word at user address * * - if is an illegal address (or write-protected for subyte or suword) * the routine returns (-1). * fubyte equ * fuibyte equ * l r1,0(sp) user address bal r6,lrau relocate btcqu * lcs r0,1 return -1 br rf eject * * clearseg(i) : clear block number in kernel space to zeroes * clearseg equ * l r1,0(sp) block no. sll r1,8 block origin address lis r0,0 lhi r2,63*adc start at last word clearlp equ * st r0,0(r1,r2) clear a word sis r2,4 back up bnm clearlp repeat br rf * * copyseg (i,j) : copy kernel block number into kernel block * copyseg equ * l r2,4(sp) target block no. sll r2,8 block origin l r1,0(sp) source block no. sll r1,8 lhi r3,63*adc start at in cc lranwp equ * ni r1,y'fff00' segment origin ar r1,r0 add offset b lraset * unmapped address lrabad equ * lis r2,8 set C bit * set condition code lraset equ * epsr r0,r0 current psw nhi r0,-16 mask off old cond code or r0,r2 set new cond code epsr r2,r0 set new psw br r6 endc title 7/32 unix -- kernel-process switching routines * * savu(a) * - save current kernel process stack environment * in location * savu equ * l r1,0(sp) location st sp,0(r1) save stack ptr st r14,adcu get physical address btc x'e',incupcx illegal or write-protected -- error * * increment profile counter * lis r0,1 am r0,0(r1) increment counter in buffer br rf * * memory fault -- turn off profiling * incupcx equ * lis r0,0 zero prof scale st r0,12(r4) to turn off profiling br rf title 7/32 unix - set processor level * * spl(n) * * - sets 'processor level' to (i.e. only devices with * priority >n may interrupt * - returns previous value of processor level * note: * as currently ick lhi r2,x'6c' addr of pic rhr r2,r3 read interval ras1 wh r2,stclk.a restart clock ssr r2,r4 btc 8,ras1 oc r2,stclk.b lhi r5,x'fff' max interval sr r5,r3 real current clock interval am r5,sytim add to system time br r6 return endc end start spl L6VL7sleep flushtty"L5cinit"L.5(L9L10L11L12L13L14nchrdev L8L.6(L16getc L17$L18$L19:wakeup L20nL21~L15canon"L.7,L23L24L25L22 x'c',illaddr illegal address lb r0,0(r1) fetch byte br rf * fuword equ * fuiword equ * l r1,0(sp) user address bal r6,lrau relocate btc x'c',illaddr illegal address - exit lhl r0,0(r1) fetch word as 2 halfwords exhr r0,r0 ... in case not on word boundary lhl r1,2(r1) ... (8/32) or r0,r1 br rf * subyte equ * suibyte equ * l r1,0(sp) user address bal r6,lrau relocate btc x'e',illaddr illegal or protected address - exit l r0,4(sp) byte to be stored stb r0,0(r1) store it lis r0,0 normal rett last word copyslp equ * l r0,0(r1,r3) move a word st r0,0(r2,r3) sis r3,4 back up bnm copyslp repeat lis r0,0 br rf title 7/32 unix -- user-kernel address space mapping * * lraddr - C interface to lra * * lraddr(aaddr, seg) * char **addr; /* pointer to unrelocated address */ * int seg[]; /* pointer to copy of MAC segmentation registers */ * * - replaces *addr by relocated address * - returns condition code from lra instruction * lraddr equ * l r5,0(sp) pointer to virtual addr l r1,0(r5) virtu(r1) save stack base br rf * * retu(a) * - restore previously-saved kernel process stack environment * from ppda at block number -- not address -- * - reset kernel seg reg e to map to address , thus * switching the 'current process' * retu equ * l r1,0(sp) block number sll r1,8 convert to address lr r0,r1 oi r0,usize*y'100000'+x'10' length = usize li r3,ps.disb-ps.rp disable the mac epsr r2,r3 l r4,ka6 set as kernel ppd segment st r0,0(r4) l sp,0(r1) restore stack ptr l r14,adc(r1) rmplemented, spl(0) enables interrupts, and any * nonzero processor level disables all interrupts. eventually * the pdp-11 processor level mechanism should be emulated more * closely, probably by using interdata system queue. * spl equ * lis r0,0 epsr r1,r1 current psw status thi r1,ps.io immediate interrupts enabled? bnz spl.new yes - skip lis r0,1 no - 'previous level' is 1 spl.new equ * nhi r1,x'ffff'-ps.io mask off immediate interrupts l r2,0(sp) new processor level bnz spl.epsr nonzX(P $ X, $PA@APA@# @XPA@юp(p(ЇX(LȰ2X  !5PA$' ;юp(p(ЇX($P $ ##Y@ #@&@@C0" B0$@@PAZюp(p(ЇX(ӽɰ#% # d ##Y@ #(@&@юp(p,Ї C$@&@P@PA$PA@%LTC0 B0 B0  #%Pӽ$CɰB0(@&@$ C@,PA@ю p,p8ЇX@ʠ!7@LP@ʠ@PA@TX@`PA@b$@X@ʠ$P@ʠ2ʰ$T!L B0& C0ӫɠ##ʠ #P@ʠ'B0X@ʠ!9P@ʠA@TCX@ʠP@ X PA@bA@ C0  @`PA@$#юp8p8Ї$P $Q@X@#$P@" LTC( !6X !3P X Y@C0$CX !9@7PA@X@tP$ $   X P   X P X@P X P $ urn br rf * suword equ * suiword equ * l r1,0(sp) user address bal r6,lrau relocate btc x'e',illaddr illegal or write protected - exit l r0,4(sp) word to be stored sth r0,2(r1) store it as 2 halfwords exhr r0,r0 ... in case not on word boundary sth r0,0(r1) ... (8/32) lis r0,0 normal return br rf * * copyin (uaddr, kaddr, n) * copyout (kaddr, uaddr, n) * - copy bytes from/to user address to/from kernel * address * * - must be a multiple of wordsize * copyin equ * l r1,al address l r2,4(sp) pointer to seg regs bal r6,lra relocate st r1,0(r5) change virtual to real address nhi r0,15 isolate cond code in new psw br rf * lra: load 'real' address * input: r1 - address in user program space * r2 - address of segmentation regs * output: r1 - corresponding address in kernel space * cc - condition code set as in real lra instruction * uses: r0 * * lrau : entry point using user seg regs (uisa0) * lrau equ * la r2,uisa0 use uisa0 for seg regs lra equ * ifnz LRA lestore stack base * * switch to new ppd segment * la r1,kisa0 set new seg regs into bal r6,addrsw hardware mac regs epsr r0,r2 enable mac again br rf * * aretu(a) * - restore kernel process stack environment from alternate * location , in the current per-process data area * aretu equ * l r1,0(sp) location l sp,0(r1) restore stack ptr l r14,adc(r1) restore stack base br rf title incupc -- update execution profile buffer * * incupc (pc, prof) * struct \( * int base; int length; int offset;ero - skip ohi r1,ps.io zero - enable interrupts again spl.epsr equ * epsr r2,r1 load new psw status br rf title i/o instruction routines ss equ * sense status l r1,0(sp) ssr r1,r0 br rf * oc equ * output command l r1,0(sp) oc r1,7(sp) br rf * wd equ * write data l r1,0(sp) wd r1,7(sp) br rf * wh equ * write halfword l r1,0(sp) wh r1,6(sp) br rf * wdh equ * write 3 bytes l r1,0(sp) wd r1,5(sp) wh r1,6(sp) br rf * rd equ * read data l r1,0(sp) rdr r1,r0 br rf * rh equ * read halfword P@PATC$PA@XXX #7 !3ZP@TPA@B0$PA@LTC0 B0 C0x C0l$CɰB%LTC> B0& #7 B0  #%Pӽ$CɰBrX$PA@  't$P$PPA@C&tC\XX C0F B02'x$P X PPX PA@f&xB0PZ & X'x$P X PPX PA@f&xB0J'tX PX&$P@PA@Z&tP  A@CX dC 0PA 0@ 0P PA@C$PA@PPAJChPAюp(p(ЇX(X,C0(X 4P & .  / X $P $C4PA84X P 4&  .  /X P $$#юp(p(ЇXXPA@X@C0X !&X #3&"%Q X@HB0n$PA@X@B XX C0X B X PXA&CX P C0X P X P &&CXTB0,$Q@X@C0@PXXPA@#$Q@X@t & !64C&X#6 & "XX C0 &  & X@&@PA@TX P@tXXX PPP@TPA@PXB0N$ XP @`PA@T't$P$PPA@C&t  $ Ci_flag =& ~ILOCK; u.u_cdir = iget(rootdev, ROOTINO); u.u_cdir->i_flag =& ~ILOCK; /* * make init process * enter scheduling loop * with system process */ if(newproc()) { expand(USIZE+3); estabur(0, 2, 1, 0); copyout(icode, 0, 256); /*** icode had better be <= 256 bytes long! ***/ /* * Return goes to loc. 0 of user init * code just copied out. */ return; } schebanner " " Banner Unix date echo pr \ param.h \ buf.h \ conf.h \ file.h \ filsys.h \ ino.h \ inode.h \ proc.h \ reg.h \ seg.h \ selch.h \ systm.h \ text.h \ tty.h \ user.h pr \ dump.s \ long.s \ low.s \ sdev.s \ start.s \ trace.s pr *.c dc offset of f.p. reg save area (u_fsav) dsav equ 8*4+fsav offset of d.p. reg save area (u_fsav[8]) fsaved equ 8*8+dsav offset of 'f.p. regs saved' flag (u_fsav[24]) * trap psw's and pointers fpregs ds 8*4 floating-point regs psw.mmo ds 8 machine malfunction old psw dc 0,0 - psw.ii dc ps.trap illegal instruction new psw dc trap.ii psw.mm dc 0 machine malfunction new psw dc trap.mm dc 0,0 - psw.af dc ps.trap arith fault new psw dc trap.af * '50' sequence for magtape load org low+x'50' + ) / 5 $ * 0 6 1 7 8 > D J 9 ? E K : @ F L ; A G M ' X@&P@dBX@HB0$Q@HQ@$Q@!5$Q@$PA@X@Y@B0X@Y@!9@PA@ $T@B0@&@@PA@ LTC C0 #6 &  #(  #$ ӫɠdC BɠB :PA@!ӫɠ##ʠ B0Y@ #@&@ʰ$C`@C0$@@PA@ XTB02$P@H0P@A@#4A@X@tPA@!$P@Hюp(p,Ї X4$PA@PX C0X # #include "param.h" #include "user.h" #include "systm.h" #include "proc.h" #include "seg.h" #include "inode.h" #include "buf.h" #include "text.h" extern int freemem; extern icode(); /*** bootstrap program to load init process ***/ /* * Initialization code. * Called from *** start.s *** * soon as a stack and segmentation * have been established. * Functions: * clear and free user core *** start clock * hand craft 0th process * call all initialization routines * fork - process 0 to schedule * d(); } /* * Load the user hardware segmentation * registers from the software prototype. * The software registers must have * been setup prior by estabur. */ sureg() /***/ { register *up, *rp, a, t; a = (u.u_procp->p_addr) << 8; if ((up=u.u_procp->p_textp) != NULL) t = (up->x_caddr)<<8; up = &u.u_uisa[16]; rp= &uisa->r[16]; while (--up >= &u.u_uisa[0]) *--rp = *up + (*up & SEGWP ? t : a); } /* * Set up software prototype segmentation * registers to implement the 3 pseudo * text,data,dc extrn start,dump extrn dispint,trap,clock extrn selchint,cntlintr,dskintr extrn mtintr extrn vdurint,vduxint extrn lpint extrn msmcintr,msmintr extrn swtch,runrun extrn proc extrn u * psw bit definitions ps.wait equ x'8000' wait state ps.io equ x'4000' immediate interrupt mask ps.mm equ x'2000' machine malfunction interrupt mask ps.af equ x'1000' arith fault interrupt mask ps.il equ x'0800' multi level interrupts (8/32) ps.rp equ x'0400' memory relocation / protection ps.sq equ x'0200' systeal x'300' b x'80' org low+x'60' b start lsu start address b dump dump start address org low+x'78' LSU addresses consaddr db y'10' device address of 'system console' conscmd2 db x'38' pals command 2 for 'system console' org low+x'80' dc sq &(system queue) dc z(pf.psw) &(power-fail psw save area) dc z(pf.regs) &(power-fail reg save area) psw.sqs dc ps.trap system queue service new psw dc trap.sq psw.mf dc ps.trap memory fault new psw dc trap.mf * svc table psw.svc dc ps.trap svc new psw title Interdata unix low-core initialization * conditional assembly switches FPREGS equ 0 if 1, floating-point regs must be saved DPREGS equ 0 if 1, double-precision regs must be saved PIC equ 0 if 1, include precision interrupt clock timing * (must also be defined in start.s) entry kisa0,uisa0,ka6 entry kisa,uisa entry addrsw,ksp entry consaddr,conscmd2 entry trmask entry memtop,consdev,rootdev,swapdev,swplo,nswap entry savfp ifnz PIC entry sytim,utime,itime entry stclk.a,stclk.b enB0X &#7PA@" &Cfюp(p8ЇX8$]<@ &$]<B0' PA@ *юp8p(ЇX(P@ʜA@HX(P@PA$PA@A@T"юp(p(Ї'x/P .PX(P@PAt&xюp(p(ЇX(X P@PA'xX0P X,PX $P@PA&xюp(p(ЇX@tX,BrA@B0$PA@X(P $ X, $PA@@C0$@@PAnA@A@B0DC4$PA@ - process 1 execute bootstrap * * panic: no clock -- neither clock responds * loop at loc 6 in user mode -- /etc/init * cannot be executed. */ main() { extern schar; register i, *p; register m; /***/ /* * zero and free all of core */ updlock = 0; m = ((*ka6 & SEGMASK) >> 8) + USIZE; /*** Start of user memory ***/ for (i = m; (i<<8) < memtop; i++) { clearseg(i); maxmem++; freemem++; mfree(coremap, 1, i); } printf("Memory = %l.%l K\n", maxmem/4, (maxmem%4)*25); printf("RESTRIstack segment sizes passed * as arguments. * The argument sep specifies if the * text and data+stack segments are to * be separated. */ estabur(nt, nd, ns, sep) { register a, *ap, *dp; if(sep) goto err; else if(nseg(nt)+nseg(nd)+nseg(ns) > 15) goto err; if(nt+nd+ns+USIZE > maxmem) goto err; a = 0; ap = &u.u_uisa[0]; while(nt >= 256) { *ap++ = (a<<8) | (255<<20) | SEGPRES|SEGWP; a =+ 256; nt =- 256; } if(nt) { *ap++ = (a<<8) | ((nt-1)<<20) | SEGPRES|SEGWP; } a = USIZE; whim queue service mask ps.prot equ x'0100' protect mode ps.ureg equ x'00f0' user register set * psw definitions ps.user equ ps.io+ps.mm+ps.af+ps.rp+ps.prot+ps.ureg ps.idle equ ps.wait+ps.io+ps.mm+ps.af+ps.rp+ps.ureg ps.kern equ ps.io+ps.mm+ps.af+ps.rp+ps.ureg ps.disb equ ps.mm+ps.af+ps.rp+ps.ureg ps.trap equ ps.mm+ps.af * register definitions r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 r7 equ 7 r8 equ 8 r9 equ 9 ra equ 10 rb equ 11 rc equ 12 rd equ 13 re equ 14 rf equ 15 sp equ r7 tit status dc z(trap.isv) svc 0 dc z(trap.isv) svc 1 dc z(trap.isv) svc 2 dc z(trap.isv) svc 3 dc z(trap.isv) svc 4 dc z(trap.isv) svc 5 dc z(trap.isv) svc 6 dc z(trap.isv) svc 7 dc z(trap.isv) svc 8 dc z(trap.isv) svc 9 dc z(trap.isv) svc 10 dc z(trap.isv) svc 11 dc z(trap.isv) svc 12 dc z(trap.isv) svc 13 dc z(trap.svc) svc 14 - system call ifnz PIC dc z(trap.tim) svc 15 else dc z(trap.isv) svc 15 endc dc 0,0,0,0,0 * interrupt service pointer table org isp initialize unused ble disk dc z(int.dsk) org 2*x'c7'+isp fixed disk dc z(int.dsk) * msm disc interrupts org 2*x'fb'+isp controller dc z(int.mcnt) org 2*x'fc'+isp drive 0 dc z(int.mdsk) org 2*x'fd'+isp drive 1 dc z(int.mdsk) * magtape interrupts org 2*x'c5'+isp tape transport 1 dc z(int.mt) * pals interrupts org 2*x'10'+isp local vdu's dc z(int.vdur),z(int.vdux) tty0 dc z(int.vdur),z(int.vdux) tty1 dc z(int.vdur),z(int.vdux) tty2 dc z(int.vdur),z(int.vdux) tty3 dc z(int.vdur),z(int.vdux) tty4 dc z(int !%[&" X P X #3&"BX P X P X P 'CPX,P X0P XPA@ю p,p(Ї'xXXP XTPXLP@8PA@&x@IPA@юp(@@$@\  Ax Ap yAh$0P0@@@0P0@@@ HFB;A(&1Y0@B $A A Cp "3 80"p(Ї,X(&P(ӱɰ%C0 C0|PA@CX(&P(ӱɰd#8ɰl#5ɰxB0"ɰx!6P#$ PX PA2ɰsCTED RIGHTS\n\n"); printf("Use, duplication or disclosure is subject to\n"); printf("restrictions stated in Contracts with Western\n"); printf("Electric Company, Inc."); printf(" and University of Wollongong.\n"); maxmem = min(maxmem, MAXMEM); mfree(swapmap, nswap, swplo); /* * start the clock */ clkstart(); /* * set up system process */ proc[0].p_addr = (*ka6 & SEGMASK) >> 8;; proc[0].p_size = USIZE; proc[0].p_stat = SRUN; proc[0].p_flag=| SLOAD|SSYS; u.u_procp = &proc[0]; /* le(nd >= 256) { *ap++ = (a<<8) | (255<<20) | SEGPRES; a =+ 256; nd =- 256; } if(nd) { *ap++ = (a<<8) | ((nd-1)<<20) | SEGPRES; a =+ nd; } while(ap < &u.u_uisa[15]) { *ap++ = 0; } a =+ ns; while(ns >= 256) { a =- 256; ns =- 256; *--ap = (a<<8) | (255<<20) | SEGPRES; } if(ns) { a =- ns; *--ap = (a<<8) | ((ns-1)<<20) | SEGPRES; } sureg(); return(0); err: u.u_error = ENOMEM; return(-1); } /* * Return the arg/256 rounded up. */ nseg(n) { return((n+255)>>8); } le low-core reserved locations * Note: This code should be absolute, since it is loaded into * physical low core. Unfortunately the assembler doesn't handle absolute * code, so it must be faked as pure. * org 0 start at physical low core pure (not really -- see note above) low equ * * reserved memory location definitions isp equ low+x'd0' interrupt-service pointer table mac.r0 equ low+x'300' memory-access controller seg regs mac.rs equ low+x'340' memory-access controller status reg fsav equ 2*aentries to ignore interrupts nlist do 256 dc z(int.null) list * do 256 * dc z(int.null) listing suppressed * display console interrupt org 2*x'01'+isp address 01 dc z(int.disp) * line printer interrupt org 2*x'62'+isp dc z(int.lp) * clock interrupts org 2*x'6d'+isp line frequency clock dc z(int.lfc) * selector channel interrupt org 2*x'f0'+isp ** selch dc z(int.sch) * disk controller interrupt org 2*x'b6'+isp disk controller dc z(int.dcnt) * disk interrupts org 2*x'c6'+isp remova.vdur),z(int.vdux) tty5 dc z(int.vdur),z(int.vdux) tty6 dc z(int.vdur),z(int.vdux) tty7 dc z(int.vdur),z(int.vdux) ttya dc z(int.vdur),z(int.vdux) ttyb dc z(int.vdur),z(int.vdux) ttyc dc z(int.vdur),z(int.vdux) ttyd dc z(int.vdur),z(int.vdux) ttye dc z(int.vdur),z(int.vdux) ttyf dc z(int.vdur),z(int.vdux) ttyg dc z(int.vdur),z(int.vdux) ttyh title low-core data areas * fixed area - should not be moved * used for emergency patching and 'ps' command org mac.r0+x'100' skip mac area dc a(proc) address of proc table for 'ps' command trmask dc 0 mask for execution trace memtop dc 256*1024 max possible memory (changed to actual amount of * memory by start.s) consdev dc 0 console device number (major/minor) rootdev dc y'0200' root filesystem device number swapdev dc y'0200' swap area device number swplo dc 8000 first block in swap area (must be >0) nswap dc 1600 number of blocks in swap area * hardware-dependent area pf.psw ds 8 power-fail psw save area pf.regs ds 32*4 power-fail reg sareg switch to user regs epsr r0,rc ni r1,x'c' make sure offset is legal l r0,sytim(r1) load requested time value lpsw nr.psw exit quickly without telling anyone endc * common trap routine trapx equ * lh r2,0(r6) get trap code epsr rd,rd current psw li rb,ps.kern new psw: kernel mode, enabled la rc,trap b call go call c trap handler title interrupt transfer vector int.null equ * unknown device lpswr r0 ignore interrupt int.disp equ * display console la rc,dispint b int int.lp eqinterval to user time am r5,utime increment user time endc la r1,kisa0 kernel seg regs bal r6,addrsw switch address space b nkernel * else trap from kernel mode -- get stack pointer from register set f kernel equ * ifnz PIC thi re,ps.wait bz kernel2 not in wait am r5,itime if wait add currnt interval to idle time b kernel3 kernel2 am r5,sytim if kernel and not wait increment sys time kernel3 equ * endc st rd,nr.psw set up resume psw la r1,nkernel st r1,nr.psw+adc lr r1,rd curtore status of interrupted process ifnz FPREGS!DPREGS l r0,u+fsaved f.p. registers saved? bz nofp lis r0,0 st r0,u+fsaved ifnz FPREGS lme r0,u+fsav restore floating-point regs endc ifnz DPREGS lmd r0,u+dsav restore double floating-point regs endc nofp equ * endc noswtch equ * li r0,ps.disb disable interrupts epsr r1,r0 l rf,10*adc(sp) restore link reg stm r8,8*adc+nr.regs save r8-rf lm r8,2*adc(sp) save r0-sp stm r8,nr.regs lm re,11*adc(sp) old psw ahi sp,14*adc pop stacgo to 1st level handler title format preprocessors *--------------register & register instructions ifnz SPFPT xer equ * srls ec.s,1 force r1 to multiple-of-4 boundary nhi ec.s,x'1c' ar ec.s,r4 address of pseudo register ar ed,ed r2*2 nhi ed,x'1c' force r2 to multiple-of-4 boundary ar ed,r4 address of pseudo-register go.to.it l eb,handlr(sp) br eb go to 2nd level handler endc ifnz DPFPT xdr equ * nhi ec.s,x'38' force r1 to multiple-of-8 boundary slls ed,2 r2*4 nhi ed,x'38' force r2 to m C I O P < B H N V \ b Q W ] c R X ^ d S Y _ e T Z ` f U [ a g h n t z i o u { j p v | k q w } l r x ~ m s y  qve area sq dc 0,0 system queue (unused) * mac segmentation registers kisa0 equ * kernel mode seg regs dc 0,0,0,0,0,0,0,0 dc 0,0,0,0,0,0,0,0 kisae equ *-8 seg e uisa0 equ * user mode seg regs dc 0,0,0,0,0,0,0,0 dc 0,0,0,0,0,0,0,0 kisa dc a(kisa0) ptr to kernel seg regs uisa dc a(uisa0) ptr to user seg regs ka6 dc a(kisae) ptr to per-process segment * non-reentrant save area for address-space switching align 4 ksp ds 4 kernel mode stack pointer save nr.intp ds 4 interrupt handler address saveu * line printer interrupt la rc,lpint b int int.lfc equ * line frequency clock la rc,clock b int int.sch equ * selector channel la rc,selchint b int int.dcnt equ * disk controller la rc,cntlintr b int int.dsk equ * disk file la rc,dskintr b int int.mcnt equ * msm disk controller la rc,msmcintr b int int.mdsk equ * msm disk drive la rc,msmintr b int int.mt equ * mag tape la rc,mtintr b int int.vdur equ * local vdu input la rc,vdurint b int int.vdux equ * local vdu output larent psw ohi r1,ps.ureg switch to reg set f epsr r0,r1 st sp,ksp save stack pointer lpsw nr.psw back to reg set 0 nkernel equ * * enable memory relocation / protection ohi rd,ps.rp enable mac epsr r0,rd * save psw & status on kernel stack l sp,ksp get kernel stack pointer shi sp,14*adc space for 14 words stm re,11*adc(sp) save old psw st rb,13*adc(sp) save new psw st r2,0(sp) save dev code st r3,adc(sp) save status * switch to user register set, and save regs st rc,nr.intp save routinek * if previous mode was user, switch back to user address space thi re,ps.prot user mode? bz kernel1 no - stay in kernel mode epsr rd,rd current psw nhi rd,x'ffff'-ps.rp disable memory access controller epsr r0,rd la r1,uisa0 user seg regs bal r6,addrsw kernel1 equ * * return to previous status st sp,ksp save kernel stack pointer ni re,y'ffffffff'-ps.wait turn off 'wait' bit stm re,nr.psw save return psw ifnz PIC * read the pic and restart * update sys time lhi r0,x'6c' pic addr rultiple-of-8 boundary ai ec.s,32(r4) make up the register's physical addr ai ed,32(r4) l eb,handlr(sp) br eb go to second levle handler endc *--------------register & memory instruction ifnz SPFPT xes equ * lis r0,1 if store type instruction b xe1 * xe equ * lis r0,0 set load type instruction xe1 sth r0,lsflag srls ec.s,1 force r1 to multiple-of-4 boundary nhi ec.s,x'1c' ar ec.s,r4 address of pseudo - register endc ifnz DPFPT b xd.2 xds equ * enter here if store type instruction li title fptrap -- 7/32 unix floating-point emulator entry fptrap extrn uisa0,lra * * The following equates are used to generate single and/or double * precision versions. * Note that the same flags must also be defined in param.h * SPFPT equ 1 if 1, simulate single-precision f.p. DPFPT equ 1 if 1, simulate double-precision f.p. LRAI equ 0 if 1, lra instruction available SIGBUS equ 10 SIGFPT equ 8 SIGINS equ 4 r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 sp equ 7 e8 equ 8 e9 equ 9 ea nr.psw ds 8 psw save nr.regs ds 16*4 register save title trap transfer vector trap.mm equ * machine malfunction btc 6,trap.mp lm re,psw.mmo get saved old psw bal r6,trapx dc h'4' trap.mp equ * memory parity error lm re,psw.mmo get saved old psw b trap.mf trap.af equ * arithmetic fault bal r6,trapx dc h'8' trap.mf equ * memory fault lis r0,0 st r0,mac.rs clear mac status register bal r6,trapx dc h'0' trap.ii equ * protect mode / illegal instruction bal r6,trapx dc h'1' trap.isv rc,vduxint b int * common interrupt routine int equ * lr re,r0 move psw to correct regs lr rf,r1 epsr rd,rd current psw nhi rd,x'ffff'-ps.il all interrupt levels off (8/32) epsr r0,rd li rb,ps.disb new psw: kernel mode, disabled b call go call c interrupt-handler title call -- interface to c trap / interrupt handlers * input: re-rf - old psw & loc * rd - current (interrupt) psw status * rc - interrupt routine address * rb - interrupt routine psw status * r2 - de address st sp,ksp save stack pointer ohi rd,ps.ureg switch to user regs epsr r0,rd stm r0,nr.regs save all regs l sp,ksp restore stack pointer lm r8,nr.regs stack regs r0-sp stm r8,2*adc(sp) * reload user high regs ( to be saved by standard c linkage ) * and call c trap handler lm r8,8*adc+nr.regs restore regs r8-rf st rf,10*adc(sp) stack link reg l r1,nr.intp trap routine address l r0,13*adc(sp) new psw epsr r2,r0 balr rf,r1 call trap routine * on return from trap routine, check whethehr r0,r1 read current interval sc2 wh r0,stclk.a restart ssr r0,r4 btc 8,sc2 oc r0,stclk.b lhi r5,x'fff' max interval sr r5,r1 am r5,sytim add real interval to sys time endc lm r0,nr.regs restore all regs lpsw nr.psw back to previous mode * save floating point registers (also called from trap.c) savfp equ * ifnz FPREGS!DPREGS l r0,u+fsaved f.p. regs saved? bnzr rf lis r0,1 st r0,u+fsaved ifnz FPREGS stme r0,u+fsav save single-precision regs endc ifnz DPREGS stmd r0,u+dss r0,1 set flag b xd1 xd equ * lis r0,0 set load type instruction xd1 sth r0,lsflag nhi ec.s,x'38' force r1 to multiple-of-8 boundary ai ec.s,32(r4) endc xd.2 equ * lhl e9,0(r5) get 1st address h/w thi e9,x'8000' bnz rx2 rx2 format thi e9,x'4000' bz rx1 rx1 format *--------------rx3 ais ef.loc,2 update location counter ais r5,2 update real pc as well exhr eb,e9 address to bits 0-15 of eb lhl ea,0(r5) get 2nd address h/w or eb,ea merge address parts ni eb,y'ffffff' retain 24 bit add equ 10 eb equ 11 ec equ 12 ed equ 13 ee equ 14 ef equ 15 e9.x equ 9 ec.s equ 12 ee.stat equ 14 ef.loc equ 15 * register usage: r0,r1,r2,r6 scratch * r3 address of users saved r8 ( see reg.h ) * r4 address of users fp regs in ppda * r5 real pc in kernal segment * ed (rd) real destination addr * * * stack data area definition * data struc handlr ds adc gregs ds 8*adc ends title entry sequence *--------------pre-processor fptrap equ * shi sp,data allocate local variables on stack stm e8,greequ * illegal supervisor call bal r6,trapx dc h'10' trap.svc equ * supervisor call lr r3,rd 'stat' is effective svc arg address bal r6,trapx dc h'6' trap.sq equ * system queue service bal r6,trapx dc h'4' ifnz PIC trap.tim equ * svc 15 request 10us clock * return in users r0 the current value of * sytim , utime , or itime * user must supply in r1 one of 0,4,8 to get * the corresponding value of the above stm re,nr.psw save old psw for quick return epsr rc,rc current ps ohi rc,ps.uvice address ( or trap code ) * r3 - device status ( or svc arg address ) call equ * ifnz PIC * read and restart the pic (precision interrupt clock) lhi r0,x'6c' addr of pic rhr r0,r1 read current interval sc1 wh r0,stclk.a restart clock ssr r0,r4 btc 8,sc1 oc r0,stclk.b lhi r5,x'fff' max interval sr r5,r1 current clock interval endc * if trap from user mode, switch to kernel address space thi re,ps.prot user mode? bz kernel no - kernel already ifnz PIC * add new r higher-priority process * is now ready to run l r1,11*adc(sp) old psw thi r1,ps.prot user mode ? bz noswtch no - don't switch kernel process switch equ * li r0,ps.disb disable interrupts epsr r1,r0 lb r1,runrun higher-priority process waiting? lr r1,r1 bz nswtch no - restore interrupted process li r0,ps.kern enable interrupts epsr r1,r0 ifnz FPREGS!DPREGS bal rf,savfp save floating-point regs endc bal rf,swtch reschedule cpu to new process b switch check again nswtch equ * * resav save double-precision regs endc endc br rf title addrsw -- switch address space * input: r1 = &(new segmentation register values) * r6 = return address * must be called with mac & interrupts disabled addrsw equ * lhi r4,15*adc start at last reg seglp equ * l r0,0(r1,r4) next seg value st r0,mac.r0(r4) store in mac reg sis r4,adc back up bnm seglp repeat for all seg regs br r6 ifnz PIC title strclk and stpclk -- start and stop pic stclk.a dc x'2fff' 10us precision and maress nhi ed,x'f' test 1st index register bz rx3nondx no index rx3.2 lb ed,grtab(ed) offset from users saved r8 a eb,0(r3,ed) users saved rx lr ed,e9 srls ed,8 rx2 to bits 28-31 of ed lr e9,eb partially completed address *--------------rx1, rx2 indexing enter here rx1 la e8,rx3.5 prepare exit address nhi ed,x'f' do indexing bz noindex no 2nd indexing for rx3 rx1.1 equ * * rx3.4 lb ed,grtab(ed) offset from users saved r8 a e9,0(r3,ed) users saved rx * no-indexgs(sp) save r8-r15 just like c lis r0,SIGINS set to return error if not fp opcode * on first instruction stb r0,laflag look ahead flag l r3,data(sp) addr of users saved r0 ( see reg.h ) * lm ee.stat,9*adc(r3) old psw shi r3,10*adc adjust to point to users saved r8 * so all offsets are +ve l r4,data+4(sp) pointer to users fp regs * fptrap1 equ * look ahead entry ( see nofault ) lr r1,ef.loc make pc real wrt kernal seg regs la r2,uisa0 mac registers ifnz LRAI lra r1,0(r2) else bal r6,lra load real addr endc * btc x'd',sigbuse if pc not valid ( not present or * not executable ) lr r5,r1 save real pc * *--------------the simulated instruction interpretation lb e8,0(r5) opcode lb ed,1(r5) r1 & r2 field lr ec.s,ed r1 into source register srls ec.s,2 r1*4 ais ef.loc,2 update location counter ais r5,2 update real pc lb e8,opcodes(e8) pointer to vector tables l e9,vectab1(e8) 1st level handler pointer l e8,vectab2(e8) second level handler pointer sta e8,handlr(sp) br e9 * * exit here if non-floating point opcode * flt.iih equ * crash equ * sis ef.loc,2 set pc back to the instruction lb r0,laflag return code b creturn *--------------happy end errfree equ * nofault equ * lis r0,0 stb r0,laflag set return code for subsequent non-fp * opcodes b fptrap1 look ahead at next instruction. * * common exit point * creturn equ * stm ee.stat,19*adc(r3) store revised psw back * into users saved regs lm e8,gregs(sp) restore callers regs ahi sp,data remove temporariexr ea,e9.x merge exponent and a ni ea,y'ffffff' xr ea,e9.x le.6 bm stm store a with appropriate status bp stp b sta *-----------------------------store a with minus status stm ais ee.stat,1 set l flag b sta go store a *-----------------------------store a with plus status stp ais ee.stat,2 set g flag *-----------------------------just plain store a sta st ea,0(ec.s) store a b dpfinal get out *-----------------------------underflow underflo ais ee.stat,4 set v flag *-------------------rs fp r bl stmeloop b nofault *-----------------------------load multiple floating lme equ * lmeloop equ * l ea,0(ed) move memory st ea,0(ec.s) to register ais ed,4 ais ec.s,4 done? clhi ec.s,32(r4) bl lmeloop b nofault title de *-----------------------------divide by zero div.by.0 ais ee.stat,12 set c and v flags l ea,0(ec.s) b sta *-----------------------------divide floating de equ * ni ee.stat,-16 clear cc l eb,0(ed) get divisor ti eb,y'00ffffff' bz div.by.0 out if divisor=0 l egisters exhr ed,eb nhi e9.x,x'7f00' strip off signs nhi ed,x'7f00' sr e9.x,ed a exp minus b exp bz aese.3 b if equal bm aese.4 b if b > a clhi e9.x,x'600' a>>b? bnl aese.sta srls e9.x,6 lr ed,eb save b exp ni eb,y'ffffff' strip b's exponent srl eb,0(e9.x) adjust b lr e9.x,ea save a exp ni ea,y'ffffff' strip a's exponent *-----------------------------a > b agb xr ed,e9.x effective add or subtract? bnm aese.2 b if add sr ea,eb subtract bz sta if zero, go store it b le.4a else go r nhi ee.stat,-16 zero current cc ar ed,ed r2 is floating reg nhi ed,x'1c' force it even ar ed,r4 address of pseudo reg l ea,0(ed) get floating number lr eb,ea magnitude to b slls eb,8 left justified lb e9.x,0(ed) exponent to x (low byte) ni e9.x,x'7f' dump sign si e9.x,x'40' is there an integer part? bnp fxrzero b if no lis ed,8 compare exponent with 8 sr ed,e9.x bm fxrovf exit if number too big bnz fxr.1 go adjust number unless exp=8 lr eb,eb exp=8 but it could still be too big bning rx1 & rx2 join here noindex lr r1,e9 destination addr la r2,uisa0 mac regs ifnz LRAI lra r1,0(r2) else bal r6,lra load real address endc btc x'c',sigbuse send illegal adddress msg to user bfc x'2',noindx1 if not write protected lh r0,lsflag bz noindx1 if load type instuction b sigbuse else illegal address noindx1 lr ed,r1 real address returned form lra br e8 goto rx3.5 or fldr or flr.2 rx3.5 ais ef.loc,2 update location counter ais r5,2 update real pc as well ni ed,y'fffffffc' forcs from stack br ef exit back to trap.c title ste and ce ifnz SPFPT *-----------------------------store floating ste l ea,0(ec.s) move reg st ea,0(ed) to memory b nofault else ok *-----------------------------compare floating ce equ * ni ee.stat,-16 clear current condition code l ea,0(ec.s) get source l eb,0(ed) and destn bnm ce.2 b if dest 0+ lr ea,ea both minus? bm ce.1 b if so *-----------------------------plus always greater than minus stps ais ee.stat,2 set g flag b dpfinal get ou----------store zero stz xr ea,ea clear a b sta go store a title me *-----------------------------multiply floating me equ * ni ee.stat,-16 clear current cc l ea,0(ec.s) fetch a bz sta exit if zero l eb,0(ed) load b bz stz exit if zero lr e9.x,ea exponent to x ni ea,y'ffffff' xr e9.x,ea zero x's fraction field ar e9.x,eb add exponents bc me.c go to me.2 if c=v bno me.2 b me.1 me.c bo me.2 *-----------------------------carry out of exponent field me.1 ti e9.x,y'40000000' test for oveea,0(ec.s) now get dividend bz sta out if dividend=0 lr e9.x,ea prepare to subtract exponents oi e9.x,y'ffffff' eliminate any chance of borrow sr e9.x,eb a exponent minus b exponent bc de.c go to de.2 if c=v bno de.2 b de.1 else de.1 de.c bo de.2 *-----------------------------borrow out of exponent field de.1 ti e9.x,y'40000000' check for underflow bz underflo b de.3 go adjust exponent *-----------------------------no borrow out of exponent field de.2 ti e9.x,y'40000000' test for overflnormalize *-----------------------------a >> b aese.sta lr ea,ea b le.6 *-----------------------------effective add aese.2a lr e9.x,ed (b>a enters here) aese.2 ar ea,eb add ti ea,y'f000000' carry? bz le.5 if no, go store srl ea,4 normalize aese.2b ai e9.x,y'1000000' bump exponent bfc 12,le.5 go store if no overflow *-----------------------------overflow overflo xi e9.x,y'80000000' restore valid sign *-----------------------------overflow entry if sign is ok overflo2 li ea,y'7fffffff' largesm fxr.2 b if it is ok fxrovf ais ee.stat,4 set v flag li eb,y'7fffffff' set number as big as possible lr ea,ea bp fxrstore b fxr.2a fxr.1 slls ed,2 prepare to adjust srl eb,0(ed) adjust fxr.2 lr ea,ea test sign bp fxrstore fxr.2a xi eb,-1 ais eb,1 b fxrstore fxrzero xr eb,eb zero b fxrstore lr eb,eb test sign of number bz fxr.6 b if zero bm fxr.5 b if minus ais ee.stat,2 set g flag b fxr.6 fxr.5 ais ee.stat,1 set l flag fxr.6 equ * * srls ec.s,2 was r1 * 4 lb r1,grtab(ec.s) offset frome onto a full-word boundary * ed contains destination addr in program space l e8,handlr(sp) br e8 go to 2nd level handler *--------------rx2 rx2 sll e9,17 get the relative address sra e9,17 with an appropriate sign ai e9,2(ef.loc) adjust it within physical space b rx1 *--------------no indexing for rx3 * rx3nondx lr r1,eb make destination addr real la r2,uisa0 mac regs ifnz LRAI lra r1,0(r2) else bal r6,lra make addr real endc btc x'c',sigbuse address is illegal bfc x'2',rt *-----------------------------both minus ce.1 sr eb,ea generate b-a bm stms b if a> b bp stps b if b>a b dpfinal exit if equal *-----------------------------dest plus ce.2 lr ea,ea test source bnm ce.3 branch if both plus *-----------------------------minus always less than plus stms ais ee.stat,9 b dpfinal get out *-----------------------------both plus ce.3 sr ea,eb generate a-b bm stms b if a>b bp stps b if b>a b dpfinal exit if equal title le *----------------------------rflow bnz overflo b me.3 *-----------------------------no carry out of exponent field me.2 ti e9.x,y'40000000' test for underflow bz underflo me.3 si e9.x,y'40000000' restore excess-64 notation ni eb,y'ffffff' clear b's expoment slls eb,7 adjust a and b for best precision slls ea,7 lr ed,ea xr ea,ea mr ea,ed ti ea,y'3c000000' test result magnitude bz me.4 b if only 2-place shift reqd ahi ea,32 me.3a srls ea,6 shift right by 6 b le.5 merge exp and store result *---------------------------ow bnz overflo2 de.3 ai e9.x,y'40000000' restore excess-64 notation li ed,y'ffffff' put b magnitude in divisor reg ti eb,y'00f00000' operand should be normalized bz dpfinal nr ed,eb slls ed,6 xr eb,eb prepare for divide ni ea,y'ffffff' get rid of a exponent dr ea,ed divide. lr ea,eb ti ea,y'3c000000' test top digit bnz de.4 branch unless zero ais ea,2 round ti ea,y'3c000000' did rounding cause carry? bnz de.4a b if yes srls ea,2 normalize (2 bits) b le.5 go store result *----------t possible number ais ee.stat,4 set v bit or ea,e9.x merge sign with number b le.6 go store with proper status *-----------------------------equal exponents aese.3 lr e9.x,ea save exponents lr ed,eb ni ea,y'ffffff' isolate magnitudes ni eb,y'ffffff' clr ea,eb if a=b pretend a>b bnl agb b bga *-----------------------------b exp > a exp aese.4 clhi e9.x,-x'500' b>>a? bnl aese.5 b if no lr ea,eb else go store b b le.6 *-----------------------------a must be adjusted aese.5 ar e9.x,ed users saved r8 st eb,0(r3,r1) put into users saved general reg * b nofault title flr *-----------------------------flr preprocessing flr.1 srls ec.s,1 source reg nhi ec.s,x'1c' word boundary ar ec.s,r4 address of pseudo reg * nhi ed,x'f' lb ed,grtab(ed) offset from users saved r8 l ed,0(r3,ed) general register * * note: in this case only, ed contains the value of the second * operand, not its address!! * *-----------------------------float (convert to real) flr.2 nhi ee.stat,-16 lr ea,ed x3no1 if not write protected lh r0,lsflag bz rx3no1 if load type instruction b sigbuse else bus error rx3no1 lr ed,r1 real address 2 b rx3.5 *--------------termination logic dpfinal equ * ti ee.stat,4 did overflow occur ? bz nofault nope ti ee.stat,x'1000' is af interrupt enabled ? bz nofault oh no * sigfpte equ * li r0,SIGFPT indicate arith error to trap.c b creturn * * * exit here if illegal address was encountered * sigbuse equ * * li r0,SIGBUS indicate bus error to trap.c b creturn -load floating le equ * ni ee.stat,-16 clear current cc l ea,0(ed) get datum to be loaded ti ea,y'f00000' normalized already? bz le.2 branch if no lr ea,ea test sign bm stm store with proper status b stp *-----------------------------number needs to be normalized le.2 ti ea,y'ffffff' test for zero bz stz lr e9.x,ea exponent to x le.4 slls ea,4 adjust left 1 digit si e9,y'1000000' decrement exponent btc 12,underflo b if underflow le.4a ti ea,y'f00000' normalized yet? bz le.4 b if no le.5 --only shift by 2, result is small me.4 ais ea,2 round ti ea,y'3c000000' did rounding cause another digit? bnz me.3a b if yes si e9.x,y'1000000' else adjust exponent btc 12,underflo srls ea,2 normalize b le.5 merge exp and store result title stme and lme *-----------------------------store multiple floating stme equ * stmeloop equ * l ea,0(ec.s) move reg st ea,0(ed) store in user's address space * ais ed,4 ais ec.s,4 bump reg counter cli ec.s,32(r4) dont forget that r4 has pointer to use-------------------large quotient de.4 ahi eb,32 round de.4a srls ea,6 normalize (6 bits) b aese.2b go test for overflow title ae and se *-----------------------------add floating ae equ * l eb,0(ed) pick up b b aese enter common process *-----------------------------subtract floating se equ * l eb,0(ed) pick up b xi eb,y'80000000' reverse sign *-----------------------------add and subtract common process aese l ea,0(ec.s) pick up a ni ee.stat,-16 clear cc exhr e9.x,ea exponents to work rcomplement exponent difference sr ed,e9.x srls ed,6 lr e9.x,ea save a exp ni ea,y'ffffff' strip exponent from a srl ea,0(ed) adjust a lr ed,eb save b exp ni eb,y'ffffff' strip b exponent *-----------------------------b > a bga xr e9.x,ed effective add or subtract? bnm aese.2a b if effective add sr eb,ea subtract bz stz if zero, go store it lr ea,eb else put reault in "a" registers lr e9.x,ed b le.4a and go normalize title fxr *-----------------------------fix (convert to integer) fx get number to float bz sta out if zero bm flr.3 b if minus li e9.x,y'46000000' get starter exponent b flr.4 flr.3 li e9.x,y'c6000000' negative number xi ea,-1 ai ea,1 flr.4 ti ea,y'ff000000' normalized to 6 digits? bz le.4a <= 6 digits, go finish normalization ai e9.x,y'1000000' > 6 digits, shift right srls ea,4 and fix exponent b flr.4 try again * since everything is done at this point, fxr.10 (see the * instruction modification routines section) returns directly * to nofault. endc title load and store double-precision floating ifnz DPFPT *--------------load double-precision floating ld equ * nhi ee.stat,-16 clear current condition code l e9,4(ed) l e8,0(ed) ti e8,y'f00000' is it normalized? bz normlize ld.50 lr e8,e8 bm stmd datum is -ve *--------------positive number - flag g stpd ais ee.stat,2 set g flag st e9,4(ec.s) st e8,0(ec.s) b dpfinal *--------------negative number - flag l stmd ais ee.stat,1 set l flag *--------------zero or exception stad or v set - underflow slls e8,4 a1 rll e9,4 a2 slls ed,4 mask ti e8,y'f00000' bz norm.05 needs more ... lr eb,e9 save a2 nr e9,ed result2 xr eb,e9 separate most significant of old a2 or e8,eb fraction a1 ar e8,ea attach sign and exponent bm stmd -ve b stpd +ve not zero *--------------a1 fraction zero norm.10 lr e9,e9 a2 ? 0 bz stzd forced x'0000000000000000' si e8,y'6000000' cater for 6 x digits from a1 btc 12,underfld c or v set - underflow rrl e9,8 norm.15 ti e9,y'f00000' poue of a's exponent nhi ed,x'7f00' value of b's exponent sr ec,ed bz adsd.60 exponents are equal bm adsd.70 ab (magnitudes) bnl adsd.55 a>>b (magnitudes) *--------------a > b adsd.03 srls ec,6 st ea,expb b's exponent shi ec,24 test if shifted more or less than 6x bnm adsd.40 shift 6 or more hex digits ni ea,y'ffffff' b1 ahi ec,24 srl eb,0(ec) rrl ea,0(ec) lhi ed,-1 construct a mask srl ed,0(ec) lr ec,ea nr ea,ed adjusted b1 xr ec,ea t'lea' b1 - strip off sign & exponent ni e8,y'ffffff' a1 xr ec,e8 result's exponent clr e8,ea a compared to b bc adsd.65 a < b btc 3,adsd.12 a > b clr e9,eb bnc adsd.12 a > or = b adsd.65 lr ea,e8 a1 to b1 l e8,expb b1 to a1 lr ed,e9 a2 to save lr e9,eb b2 to a2 lr eb,ed a2 to b2 st ec,expb a's exponent becomes b's lr ec,e8 new a's exponent ni e8,y'ffffff' strip off the new exponent xr ec,e8 b adsd.12 *--------------a < b adsd.70 clhi ec,-x'd00' bl adsd.80 a< b , set flag g b dpfinal * cd.10 l e8,0(ec.s) a1 bnm cd.20 a is +ve cd.15 ais ee.stat,9 a < b , set flags l & c b dpfinal * cd.20 clr e8,ea a ? b , both identical signs bc cd.15 a < b btc 3,cd.5 a > b l e9,4(ec.s) a2, a1 = b1 cl e9,4(ed) a2 ? b2 bc cd.15 a2 < b2, a < b btc 3,cd.5 a > b b dpfinal cd.30 clr e8,ea a -ve, b -ve bc cd.5 ba l e9,4(ec.s) cl e9,4(ed) bc cd.5 b2a b dpfinal title add and subtract doubl50 store the result adsd.20 lr e9,e9 bz stad result is zero b adsd.17 *--------------effective addition adsd.25 l ec.s,source restore source address ar e9,eb a2+b2=r2 bnc adsd.30 ais e8,1 a1+1:=a1 adsd.30 ar e8,ea a1+b1=r1 bz stzd result is zero l ed,exp ti e8,y'f000000' bnz adsd.35 or e8,ed no change in exponent 's value bm stmd b stpd adsd.35 ai ed,y'1000000' increase exponent's value btc 12,adsd.85 overflow srls e9,4 rrl e8,4 lr eb,e8 ni e8,y'ffffff' result1 (r1) xr eb,e8 the o a1 fraction ar ed,ea a-exp + b-exponent bc md.04 if c=v go to md.08 bno md.08 b md.06 md.04 bo md.08 *--------------carry out of exponent field md.06 ti ed,y'40000000' test for overflow bz md.10 si ed,y'1000000' test if potentially o.k. ti ed,y'40000000' bnz md.75 no, overflow ni ea,y'ffffff' potential overflow xr ed,ea retain excess-128 notation and ais ed,1 set potential overflow flag b md.12 *--------------no carry out of exponent field md.08 ti ed,y'40000000' must be gt or eq 64 alized thi e8,1 test potential overflow flag bnz md.70 overflow ar e8,ee lr e9,ef * restore saved values md.35 lm ee.stat,status l ec.s,source b ld.50 test if -ve or +ve *--------------normalize the result of multiplication md.40 thi e8,1 test the potential overflow flag bz md.42 no overflow detected earlier sis e8,1 no test for underflow, * no further exponent adjustment, * just clear the flac.s) a2 l e8,0(ec.s) a1 bz stzd result is zero lr ed,e8 get exponent oi ed,y'ffffff' eliminate any chance of borrow sr ed,ea subtract exponents bc dd.04 bno dd.08 b dd.06 dd.04 bo dd.08 *--------------borrow out of exponent field dd.06 ti ed,y'40000000' check for underflow bnz dd.10 ai ed,y'1000000' test if potentially o.k. ti ed,y'40000000' bz underfld definitely underflow ni ed,y'ff000000' pure exponent in ed ais ed,1 set potential underflow flag b dd.12 *--------------no borrow outffff' ais ee.stat,4 set v flag or e8,ed get an appropriate sign bm stmd -ve b stpd +ve *--------------underflow underfld ais ee.stat,4 set v flag xr e8,e8 zeroise the number xr e9,e9 b stad title normalization *--------------normalization of double-precision floating normlize equ * ti e8,y'ffffff' test if a1=zero bz norm.10 lhi ed,-1 lr ea,e8 get exponent ni e8,y'ffffff' separate fraction xr ea,e8 separate sign & exponent norm.05 si ea,y'1000000' decrement exponent btc 12,underfld ce-precision floating *--------------add double-precision floating ad equ * nhi ee.stat,-16 clear current condition code l eb,4(ed) b2 l ea,0(ed) b1 b adsd.00 *--------------subtract double-precision floating sd equ * nhi ee.stat,-16 clear current condition code l eb,4(ed) b2 l ea,0(ed) b1 xi ea,y'80000000' reverse sign *--------------add and subtract common sequence adsd.00 l e9,4(ec.s) a2 l e8,0(ec.s) a1 st ec.s,source exhr ec,e8 a's exponent exhr ed,ea b's exponent nhi ec,x'7f00' valleast significant digit of r1 or e9,eb result2 (r2) or e8,ed add exponent bm stmd b stpd *--------------a>b, continued 1 adsd.40 srl eb,24 6 or more hex digits difference slls ea,8 b1 or eb,ea new b2 xr ea,ea zero to b1 lr ec,ec bz adsd.05 no more adjustments to b1 srl eb,0(ec) new adjusted b b adsd.05 *--------------a >> b adsd.55 l ec.s,source lr e8,e8 bm stmd b stpd *--------------a's exp = b's exp adsd.60 st ea,expb preserve b1 lr ec,e8 a's sign and exponent ni ea,y'ffffffbz underfld underflow, < 64 md.10 ni ea,y'ffffff' clear b's exponent xr ed,ea retain result of exp. manipulation md.12 si ed,y'40000000' restore excess-64 notation ni e8,y'ffffff' clear a's exponent stm ec.s,source save: ec...source address * ed...exponent with potential * overflow flag on/off * ee,ef...the instruction's psw * multiply both a and b bg b md.43 md.42 si e8,y'1000000' result is to be normalizedp btc 12,md.45 underflow md.43 slls ee,4 r1*16 := r1 ar e8,ee r1+exponent rll ef,4 r2*16 := r2 lr e9,ef r2 nhi ef,x'f' retain the most sign digit of r2 xr e9,ef clear rubbish ar e8,ef most sign digit of r2 times 16 rll ed,4 bring in another hex digit lr ef,ed nhi ef,x'f' or e9,ef * restore saved values b md.35 md.45 lm ee.stat,status underflow due to normalization l ec.s,source b underfld *--- of exponent field dd.08 ti ed,y'40000000' test for overflow bnz dd.75 yes, overflow dd.10 ni ed,y'ff000000' dd.12 ai ed,y'40000000' resultant exponent * with the potential underflow * flag set or reset ni e8,y'ffffff' clear a's exponent ni ea,y'ffffff' clear b's exponent stm ec.s,source save: ec...source address * ed...exponent with potential * underflow flag on/off * ee,ef...the instruction's psw xr ee,ee zero to result1 xr ef,ef zero to result2 li ec,y'1000000' * divide by repeated subtraction. * hexadecimal digits are basic * sources for decision-making and * the arithmetics clr e8,ea a1 ? b1 bc dd.30 a1 < b1 btc 3,dd.20 a1 > b1 clr e9,eb a2 ? b2 bcd.60 lm ee.stat,status l ec.s,source l ed,exp b overfld * division by zero dd.70 ais ee.stat,12 c and v flags b dpfinal dd.75 xr e8,ea lr ed,e8 b overfld * underflow dd.80 lm ee.stat,status l ec.s,source b underfld title float register - double-precision *--------------fldr pre-process fldr.00 equ * nhi ed,x'f' r2 is general register lb ed,grtab(ed) offset from user's saved r8 l ed,0(r3,ed) contents of general register * * noteficant x digits lr eb,e8 slls eb,8 adjust 6 most signif x digits or eb,e9 construct number's magnitude lr ea,ea examine effective exponent bz fxdr.07 no adjustment required slls ea,2 multiply by 4 to get no of bits srl eb,0(ea) result's magnitude fxdr.07 lr e8,e8 bp fxdr.15 +ve result fxdr.08 equ * xhi eb,-1 complement the bit pattern ais eb,1 complement the number fxdr.10 ais ee.stat,1 -ve result, set l flag b fxdr.6 fxdr.15 ais ee.stat,2 +ve result, set g flag fxdr.17 b fxdr.6 go store double-precision dac ld,cd,ad,sd,md,dd rr floating dac flt.iih fxdr dac fldr fldr dac y'80000000'+std std dac ld,cd,ad,sd,md,dd rx floating dac y'80000000'+stmd.00 stmd dac lmd lmd endc ifz DPFPT do 17 dac crash endc title operation code table *--------------opcode table align 4 opcodes do 5 db 0,0,0,0,0,0,0,0 ifnz SPFPT single-precision db 4,8,12,16,20,24,28,32 else db 0,0,0,0,0,0,0,0 endc db 0,0,0,0,0,0,0,0 ifnz DPFPT double-precision db lv,lv+4,lv+8,lv+12,lv+16,lv+20,lv+24,l title unix double-precision integer arithmetic subroutines entry dpadd,dpcmp entry ldiv,lrem entry lshift r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 sp equ 7 re equ 14 rf equ 15 * * dpadd(long, addend) * int long[2], addend; * * - add integer addend to double-integer long * dpadd equ * l r1,0(sp) ptr to first operand l r0,4(sp) second operand am r0,4(r1) add to low-order part bfcr x'c',rf no overflow or carry - return lis r0,1 add carry to high-order part am r0,0(r1) br rfer part br rf * end dd.30 a2 < b2 btc 3,dd.20 a2 > b2 lr ee,ec a=b, result's obvious b dd.40 *--------------a>b dd.20 sr e9,eb current a2-b2 = c2 bnc dd.22 sis e8,1 a1-1 := a1, no chance of borrow dd.22 sr e8,ea current a1-b1 = c1 ar ef,ec clr e8,ea a1 ? b1 bc dd.30 a1b1 clr e9,eb a2?b2 bnc dd.20 a2> or = b2 *--------------ab1 clr e9,eb a2?b2 bnc dd.20 a2 > or = b2 b dd.30 *--------------result build-up dd.40 l e8,exp ti ee,y'f000000' does it need normalization ? bnz dd.45 yes thi e8,1 test the potential underflow flag bnz dd.80 underflow b dd.icant x digits or e8,ea result1 ti e8,y'f00000' needs normalization? bz normlize lr e8,e8 bm stmd b stpd *--------------negative integer fldr.20 xhi ea,-1 complement the bit pattern ais ea,1 complement the -ve number li e8,y'c8000000' starter exponent - negative mantissa b fldr.10 title fix register - double-precision *--------------fix register double-precision (convert to integer) fxdr equ * nhi ee.stat,-16 clear current condition code slls ed,2 multiply by 4 to get floating reg nhi eral reg * b nofault endc title vector tables vectab1 dac flt.iih illegals all have a code of 0 ifnz SPFPT single-precision dac xer,xer,xer,xer,xer,xer rr floating dac y'80000000'+fxr fxr dac y'80000000'+flr.1 flr dac xes rx floating (store) dac xe,xe,xe,xe,xe,xe rx floating dac y'80000000'+xes stme dac y'80000000'+xe lme endc ifz SPFPT do 17 dac flt.iih endc lv equ *-vectab1 ifnz DPFPT double-precision dac xdr,xdr,xdr,xdr,xdr,xdr rr floating dac y'80000000'+fxdr fxdr dac y'80000000 used by: ad,sd *--------------work areas * * offsets from users saved r8 of users * general registers. * see reg.h for additional info * we cant use reg.h exactly because offsets * must be +ve * grtab equ * db 10*adc r0 db 11*adc r1 db 12*adc r2 db 13*adc r3 db 14*adc r4 db 15*adc r5 db 16*adc r6 db 17*adc r7 - sp db 0*adc r8 db 1*adc r9 db 2*adc r10 db 3*adc r11 db 4*adc r12 db 5*adc r13 db 6*adc r14 db 18*adc r15 lsflag dc h'0' load/sto br rf * greater or equal - check very large diff great equ * bnz greatx high order part? chi r0,512 or gt than limit? bnpr rf greatx equ * lhi r0,512 br rf * * ldiv (dividend, divisor) * * - divide unsigned integer dividend by signed divisor * ldiv equ * lis r0,0 l r1,0(sp) d r0,4(sp) lr r0,r1 quotient br rf * * lrem (dividend, divisor) * lrem equ * lis r0,0 l r1,0(sp) d r0,4(sp) br rf * * lshift (long, n) * integer long[2]; * * - shift double-integer to the left n bits * - n may be negatpure dtrace equ * * * get first 4 chars of message label * l r1,label(sp) message pointer lb r2,0(r1) first byte exbr r2,r2 lb r0,1(r1) second byte stbr r0,r2 exhr r2,r2 move to upper half of word lb r0,2(r1) third byte stbr r0,r2 exbr r2,r2 lb r0,3(r1) fourth byte stbr r0,r2 * * put message & value in trace buffer * la r4,trbuff point to trace buffer tr.abl equ * abl r2,0(r4) add to bottom of list bfc 4,tr.ablok no overflow - continue lis r0,0 else reset buffer to 'empty' sth r0,2(r4) st50 and off we go... dd.45 rrl ee,4 normalize, r1/16 srls ef,4 r2/16 lr ed,ee separate the least signif digit of r ni ee,y'ffffff' xr ed,ee ar ef,ed thi e8,1 test the potential underflow flag bz dd.55 not set - increase exponent's value sis e8,1 reset the flag dd.50 or e8,ee everything's o.k. lr e9,ef lm ee.stat,status l ec.s,source lr e8,e8 bm stmd b stpd dd.55 ai e8,y'1000000' increase the exponent value bfc 12,dd.50 it is not an overflow * overflow dd,x'38' force it on & bytes boundary ai ed,32(r4) add fwa of double precision regs l e8,0(ed) a1 l e9,4(ed) a2 exhr ea,e8 nhi ea,x'7f00' separate exponent shi ea,x'4000' is there an integer part? bnp fxdr.30 no srls ea,8 pure exponent sis ea,8 bp fxdr.25 number is too big xhi ea,-1 complement the bit pattern ais ea,1 complement the number ti e8,y'800000' is the number potentially too big? bnz fxdr.20 yes *--------------final conversion to integer fxdr.05 srl e9,24 move two least signi'+fldr.00 fldr dac xds rx floating (store) dac xd,xd,xd,xd,xd,xd rx floating dac y'80000000'+xds stmd dac y'80000000'+xd lmd endc ifz DPFPT do 17 dac flt.iih endc *--------------second level vector table vectab2 dac flt.iih shouldn't ever get here ifnz SPFPT single-precision dac le,ce,ae,se,me,de rr floating dac flt.iih fxr dac flr.2 flr dac y'80000000'+ste ste dac le,ce,ae,se,me,de rx floating dac y'80000000'+stme stme dac lme lme endc ifz SPFPT do 17 dac crash endc ifnz DPFPTre type instruction laflag db 0 look ahead flag * align 4 source das 1 save area for source address * used by: ad,sd,md,dd exp das 1 save area for result's exponent * used by: ad,sd,md,dd status das 2 save area for the user's psw * used by: md,dd ***************the order of source, exp & status should not be changed expb das 1 auxiliary area for b's exponent * used by: ive (right-shift) * - return low-order word of result * lshift equ * l r1,0(sp) ptr to arg 1 l r0,0(r1) high order part l r1,4(r1) low order part l r2,4(sp) no. of shifts bm rshift negative - shift right sll r1,0(r2) shift left lr r0,r1 return low order part br rf * rshift equ * srls r1,1 shift low order part srls r0,1 shift high order part bnc nocarry if carry ... oi r1,y'80000000' move carry bit to loworder nocarry equ * ais r2,1 count shifts bm rshift repeat lr r0,1 return low ord r0,4(r4) b tr.abl try again tr.ablok equ * l 3,value(sp) value abl r3,0(r4) add to bottom of list * * test whether this trace is masked on * l r0,mask(sp) get mask n r0,trmask check with trace control word bzr rf no bits on - return * * display message on system console * shi sp,32+12 save regs first stm r8,12(sp) la r0,tr.fmt message format st r0,0(sp) st r1,4(sp) message st r3,8(sp) value bal rf,printf display it on console lm r8,12(sp) restore regs ahi sp,32+12 br rf return * * format for display * tr.fmt equ * db c'%s %x',x'0a',0 db * end RASE '#' /* default special characters */ #define CEOT 004 #define CKILL '@' #define CQUIT 034 /* FS, cntl shift L */ #define CINTR 0177 /* DEL */ /* limits */ #define TTHIWAT 100 #define TTLOWAT 60 #define TTYHOG 256 /* modes */ #define HUPCL 01 #define XTABS 02 #define LCASE 04 #define ECHO 010 #define CRMOD 020 #define RAW 040 #define ODDP 0100 #define EVENP 0200 #define NLDELAY 001400 #define TBDELAY 006000 #define CRDELAY 030000 #define VTDELAY 040000 #define BREAK (01<<16) /* Use BREAK for interrrk:char{acter} /usr/lib/quiz/inca:inca:succ[essor|] /usr/lib/quiz/collectives:ind{ividuals}:coll{ective} /usr/lib/quiz/misspell:mis{spell}:right /usr/lib/quiz/poetry:poem-line:next:poem:author /usr/lib/quiz/u.s.:u.s.-state:cap[ital|]:abbr[ev[iation|]|] /usr/lib/quiz/u.s.pres:[u.s.-|]pres[ident|]:term:succ[essor|] /* * Used to dissect integer device code * into major (driver designation) and * minor (driver parameter) parts. */ struct { char pad_0; /***/ char pad_1; /***/ char d_major; /***/ char d_minor; /***/ }; /* * Declaration of block device * switch. Each entry (row) is * the only link between the * main unix code and the driver. * The initialization of the * device switches is in the * file conf.c. */ extern struct bdevsw /***/ { int (*d_open)(); int (*d_close)(); int (*d_strategy)(); i and check that the reason for * sleeping has gone away. */ sleep(chan, pri) { register *rp, s; rp = u.u_procp; if(pri >= 0) { if(issig()) goto psig; s = spl(6); rp->p_wchan = chan; rp->p_stat = SWAIT; rp->p_pri = pri; spl(0); if(runin != 0) { runin = 0; wakeup(&runin); } swtch(); if(issig()) goto psig; } else { s = spl(6); rp->p_wchan = chan; rp->p_stat = SSLEEP; rp->p_pri = pri; spl(0); swtch(); } spl(s); return; /* * If priority was low (>=0) and error while swapping. * this is the one panic that should be * handled in a less drastic way. Its * very hard. */ sched() { struct proc *p1; register struct proc *rp; register a, n; /* * find user to swap in * of users ready, select one out longest */ goto loop; sloop: runin++; sleep(&runin, PSWP); loop: spl(6); n = -1; for(rp = &proc[0]; rp < &proc[NPROC]; rp++) if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && rp->p_time > n) { p1 = rp; n = rp->p_time; } if(n == -1) { /* * A clist structure is the head * of a linked list queue of characters. * The characters are stored in 4-word * blocks containing a link and ***12*** characters. * The routines getc and putc (cio.c) * manipulate these structures. */ struct clist { int c_cc; /* character count */ int c_cf; /* pointer to first block */ int c_cl; /* pointer to last block */ }; /* * The structure of a character block in a clist */ struct cblock { struct cblock *c_next; char info[12]; /***/ }; /* * A tty upt, not RUBOUT */ /* Baud rates */ #define B300 7 #define B600 8 #define B1200 9 #define B1800 10 #define B2400 11 #define B4800 12 #define B9600 13 /* Hardware bits */ #define DONE 0200 #define IENABLE 0100 /* Internal state bits */ #define TIMEOUT 01 /* Delay timeout in progress */ #define WOPEN 02 /* Waiting for open to complete */ #define ISOPEN 04 /* Device is open */ #define SSTART 010 /* Has special start routine at addr */ #define CARR_ON 020 /* Software copy of carrier-present */ #define B/* * INTERDATA SOFTWARE USER SEGMENTATION REGISTERS */ extern int *uisa; extern int *kisa; /* * masks for selecting parts of segmentation register */ #define SEGMASK 03777400 /* segment start address */ #define SEGEP 0200 /* execute protect */ #define SEGIP 0100 /* write-interrupt protect */ #define SEGWP 040 /* write protect */ #define SEGPRES 020 /* present */ /* * structure used to address * a sequence of integers. */ struct { int r[]; }; extern int *ka6; /* pointer to seg reg for u segment nt *d_tab; } bdevsw[]; /* * Nblkdev is the number of entries * (rows) in the block switch. It is * set in binit/bio.c by making * a pass over the switch. * Used in bounds checking on major * device numbers. */ extern int nblkdev; /***/ /* * Character device switch. */ extern struct cdevsw /***/ { int (*d_open)(); int (*d_close)(); int (*d_read)(); int (*d_write)(); int (*d_sgtty)(); } cdevsw[]; /* * Number of character switch entries. * Set by cinit/tty.c */ extern int nchrdev; /***/ * there has been a signal, * execute non-local goto to * the qsav location. * (see trap1/trap.c) */ psig: aretu(u.u_qsav); } /* * Wake up all processes sleeping on chan. */ wakeup(chan) { register struct proc *p; register c, i; c = chan; p = &proc[0]; i = NPROC; do { if(p->p_wchan == c) { setrun(p); } p++; } while(--i); } /* * Set the process running; * arrange for it to be swapped in if necessary. */ setrun(p) { register struct proc *rp; register pri; /***/ rp = p; runout++; sleep(&runout, PSWP); goto loop; } /* * see if there is core for that process */ spl(0); rp = p1; a = rp->p_size; if((rp=rp->p_textp) != NULL) if(rp->x_ccount == 0) a =+ rp->x_size; if((a=malloc(coremap, a)) != NULL) goto found2; /* * none found, * look around for easy core */ spl(6); for(rp = &proc[0]; rp < &proc[NPROC]; rp++) if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && (rp->p_stat == SWAIT || rp->p_stat==SSTOP)) goto found1; /* * no easy core, * structure is needed for * each UNIX character device that * is used for normal terminal IO. * The routines in tty.c handle the * common code associated with * these structures. * The definition and device dependent * code is in each driver. (kl.c dc.c dh.c) */ struct tty { struct clist t_rawq; /* input chars right off device */ struct clist t_canq; /* input chars after erase and kill */ struct clist t_outq; /* output list to device */ int t_flags; /* mode, settable by stty call */ int *t_addr; USY 040 /* Output in progress */ #define ASLEEP 0100 /* Wakeup when output done */ #define SUSPEND 0200 /*** suspend transmission (buffer full) ***/ */ rp->p_wchan = 0; rp->p_stat = SRUN; if ((pri = rp->p_pri) > 127) /***/ pri =- 256; /***/ if(pri < curpri) /***/ runrun++; if(runout != 0 && (rp->p_flag&SLOAD) == 0) { runout = 0; wakeup(&runout); } } /* * Set user priority. * The rescheduling flag (runrun) * is set if the priority is higher * than the currently running process. */ setpri(up) { register *pp, p; /***/ register n; pp = up; p = (pp->p_cpu & 0377)/16; /***/ p =+ PUSER + ( (n = pp->p_nice) > 127 ? n-256 : n ); if(p > 127if this process is deserving, * look around for * oldest process in core */ if(n < 3) goto sloop; n = -1; for(rp = &proc[0]; rp < &proc[NPROC]; rp++) if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && (rp->p_stat==SRUN || rp->p_stat==SSLEEP) && rp->p_time > n) { p1 = rp; n = rp->p_time; } if(n < 2) goto sloop; rp = p1; /* * swap user out */ found1: spl(0); rp->p_flag =& ~SLOAD; xswap(rp, 1, 0); goto loop; /* * swap user in */ found2: trace(01, "sswap", p1->p_pid);/* device address (register or startup fcn) */ char t_delct; /* number of delimiters in raw q */ char t_col; /* printing column of device */ char t_erase; /* erase character */ char t_kill; /* kill character */ char t_state; /* internal state, not visible externally */ char t_char; /* character temporary */ int t_speeds; /* output+input line speed */ int t_dev; /* device name */ }; extern char partab[]; /* ASCII table: parity, character class */ #define TTIPRI 10 #define TTOPRI 20 #define CE/usr/lib/quiz/murders:victim:killer /usr/lib/quiz/europe:[country-|]Europe:cap[ital|] /usr/lib/quiz/america:[country-|]America:cap[ital|] /usr/lib/quiz/africa:[country-|]Africa:cap[ital|] /usr/lib/quiz/midearth:[country-|]M[iddle-Earth|E]:cap[ital|] /usr/lib/quiz/sov:sov[ereign|]:cen[t[ury|]|]:succ[essor|] /usr/lib/quiz/seq-easy:seq[uence|]-easy:next:name /usr/lib/quiz/seq-hard:seq[uence|]-hard:next:name /usr/lib/quiz/posneg:pos[itive|]:neg[ative|] /usr/lib/quiz/bard:Shakespeare[-line[s|]|]|line[s|]:next:wo...indexamericaafricabardcollectiveseuropeincapoetry posneg seq-easy seq-hard midearth misspellmurderssovu.s.presu.s.# /* */ #include "param.h" #include "user.h" #include "proc.h" #include "text.h" #include "systm.h" #include "file.h" #include "inode.h" #include "buf.h" #include "seg.h" /* * Give up the processor till a wakeup occurs * on chan, at which time the process * enters the scheduling queue at priority pri. * The most important effect of pri is that when * pri<0 a signal cannot disturb the sleep; * if pri>=0 signals will be processed. * Callers of this routine must be prepared for * premature return,) p = 127; if(p > curpri) runrun++; pp->p_pri = p; } /* * The main loop of the scheduling (swapping) * process. * The basic idea is: * see if anyone wants to be swapped in; * swap out processes until there is room; * swap him in; * repeat. * Although it is not remarkably evident, the basic * synchronization here is on the runin flag, which is * slept on and is set once per second by the clock routine. * Core shuffling therefore takes place once per second. * * panic: swap error -- IO if((rp=p1->p_textp) != NULL) { if(rp->x_ccount == 0) { if(swap(rp->x_daddr, a, rp->x_size, B_READ)) goto swaper; rp->x_caddr = a; a =+ rp->x_size; } rp->x_ccount++; } rp = p1; if(swap(rp->p_addr, a, rp->p_size, B_READ)) goto swaper; mfree(swapmap, (rp->p_size+1)/2, rp->p_addr); /***/ rp->p_addr = a; rp->p_flag =| SLOAD; rp->p_time = 0; goto loop; swaper: panic("swap error"); } /* * This routine is called to reschedule the CPU. * if the calling process is not in RUN state, * arrangements for it to restart must have * been made elsewhere, usually by calling via sleep. */ swtch() { int dummy[4]; /*** savu callers must have same stack frame ***/ static struct proc *p; register i, n; register struct proc *rp; register pri; /***/ if(p == NULL) p = &proc[0]; trace(010, "swtch", dummy[11]); /* * Remember stack of caller */ savu(u.u_rsav); /* * Switch to scheduler's stack */ retu(proc[0].p_addr); loop: runrun = 0; rp = p; p = NULL; n = 128; /* * Sat this is the value that newproc's * caller in the new process sees. */ newproc() { int a1, a2; struct proc *p, *up; register struct proc *rpp; register *rip, n; p = NULL; /* * First, just locate a slot for a process * and copy the useful info from this process into it. * The panic "cannot happen" because fork has already * checked for the existence of a slot. */ retry: mpid++; if(mpid < 0) { mpid = 0; goto retry; } for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { if(rpp->p_stacate it * and copy the image, taking care to reset registers to account * for the fact that the system's stack has moved. * If there is no core, arrange for the process to be swapped * out after adjusting the size requirement-- when it comes * in, enough core will be allocated. * Because of the ssave and SSWAP flags, control will * resume after the swap in swtch, which executes the return * from this stack level. * * After the expansion, the caller will take care of copying * the user's stack tow8_,`00CC@C@ 48 (000:B:B:B:B:B:B:B:B:B:B:B:B:B:B:B:B' ,C T $B0n @\C0, . !8ݒ#"'C / C0ɰC0C4 @ƔC0( @Ɣ #6$T $C0 @\#4ӻ@Ɣ'ҽ&ސ#CPPݒ&UCP P&A@6"$#ю p,p(ЇX,X(X$ !5#2$ B08#5B0*!5$P#$PPA@ PACX !PACC0A!Z!# PPA@6 !8 #5B0*PA@pPPA@6!6 ,& ,C0 0B0PPAPA~юp(p,Ї X0X,!7 T $C0 B0($T $C0P PA - = &proc[NPROC]) rp = &proc[0]; if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { if ((pri = rp->p_pri) > 127) /***/ pri =- 256; /***/ if(pri < n) { /***/ p = rp; n = pri; /***/ } } } while(--i); /* * If no process is runnable, idle. */ if(p == NULL) { p = rp; idle(); goto loop; } rp = p; curpri = n; /* * Switch to stack of the new process and set up * his segmentation registt == NULL && p==NULL) p = rpp; if (rpp->p_pid==mpid) goto retry; } if ((rpp = p)==NULL) panic("no procs"); /* * make proc entry for new proc */ rip = u.u_procp; up = rip; rpp->p_stat = SRUN; rpp->p_flag = SLOAD; rpp->p_uid = rip->p_uid; rpp->p_ttyp = rip->p_ttyp; rpp->p_nice = rip->p_nice; rpp->p_textp = rip->p_textp; rpp->p_pid = mpid; rpp->p_ppid = rip->p_pid; rpp->p_time = 0; /* * make duplicate entries * where needed */ for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOards or away from the data area. */ expand(newsize) { int i, n; register *p, a1, a2; int dummy[2]; /*** savu callers must have same stack frame ***/ p = u.u_procp; n = p->p_size; p->p_size = newsize; a1 = p->p_addr; if(n >= newsize) { mfree(coremap, n-newsize, a1+newsize); return; } savu(u.u_rsav); a2 = malloc(coremap, newsize); if(a2 == NULL) { savu(u.u_ssav); xswap(p, 1, n); p->p_flag =| SSWAP; swtch(); /* no return */ } p->p_addr = a2; for(i=0; iX@2(B0XPA@!$CX P@2($P $P &PCBðB0:ʠX@2(B0XPA@!$C8X P@2($P &Pers. */ trace(010, "retu", rp->p_pid); retu(rp->p_addr); sureg(); /* * If the new process paused because it was * swapped out, set the stack level to the last call * to savu(u_ssav). This means that the return * which is executed immediately after the call to aretu * actually returns from the last routine which did * the savu. * * You are not expected to understand this. */ if(rp->p_flag&SSWAP) { rp->p_flag =& ~SSWAP; aretu(u.u_ssav); } /* * The value returned here has manyFILE];) if((rpp = *rip++) != NULL) rpp->f_count++; if((rpp=up->p_textp) != NULL) { rpp->x_count++; rpp->x_ccount++; } u.u_cdir->i_count++; /* * Partially simulate the environment * of the new process so that when it is actually * created (by copying) it will look right. */ savu(u.u_rsav); rpp = p; u.u_procp = rpp; rip = up; n = rip->p_size; a1 = rip->p_addr; rpp->p_size = n; a2 = malloc(coremap, n); /* * If there is not enough core for the * new process, swap out the curren+); mfree(coremap, n, a1); retu(p->p_addr); sureg(); }  2((0 0CVB0@ T $B04 0C0& 0 0 PA@pPA@:#PPA@юp(p(ЇX([@<<2, 0C0'tX(P@tP@PA@ &t'tX,P@yP@PA@ &t 0 0PA@:X p_stat = SIDL; rpp->p_addr = a1; savu(u.u_ssav); xswap(rpp, 0, 0); rpp->p_flag =| SSWAP; rip->p_stat = SRUN; } else { /* * There is core, so just copy. */ rpp->p_addr = a2; while(n--) copyseg(a1++, a2++); } u.u_procp = rip; return(0); } /* * Change the size of the data+stack regions of the process. * If the size is shrinking, it's easy-- just release the extra core. * If it's growing, and there is core, just allo  t cdp\VilkonjmUY[^WX  e f g h i j k m ] _ ` a c S T W Y Z [  Q U $X(PX PX@Aюp(p(ЇX($PA@!X C0( 0@ 0P PA@CPAt$PA@!юp(p(Ї+&2B X@2(P P@2("$X #5&ʰ"P@Lюp(p(ЇX( & PA@|!"  PA@|!" PA@p 0? 0 PA@p$PA@!PA@|!"$ ,PA@!юp(p,Ї X,$PA@! ,B0$ 0!4$C$ PPA@C$PA@!ݒPA@|Bɰ!8 ,XA&CܔX P C0X P X P &&CXTB0,$Q@X@C0@PXXPA@!#$Q@X@t & !6 ' X@&P@dBX@B0$Q@Q@$Q@$!5$Q@ $PA@!X@$Y@,B0X@ Y@(!9@(PA@d$T@$B0@&@@PA@dC C0 #6 &  #(  #$ ӫɠdC BɠB :PA@ӫɠ##ʠ B0Y@#@&@ʰ$C`@C0$@@Aюp(p(ЇAC0X 8P:X@Aюp(p(ЇAnC0X 8P:X@Aюp(p(ЇA4C0$X,PX 8P:X@Aюp(p(ЇX@tX !5$@m #юp(p4ЇPA@mB0FX@4X P&PA@ ZX P&&PA@ ZX P&&PA@ Zюp4p(ЇX@4PA@ (P@4&PA@ (P@8&PA@ (P@<$PA юp(p(ЇX@XPA@PC0DXX ` #8@mC&P$Q XPA@!$#ю p,X!"4""@@e$C@ $@P" X7e4XT@?p,Ї PPP7A@ ч p,%s %x @Sp %x Psw %x %x Display console?B%%%%%%%%%%%%%%%1111111111111@11N1out of swap55555unlink -- igetxswapout of swap spaceswap errorout of textout of swap spaceiinitno spacebad blockOut of inodesbad countno fsnxnxh* +`nxnxp*"P~nxnx8nxnxnxnZxnx(b^p$Ї$PX7$$0(XG( @A`@!BЁJQӅ&&RӈXXrP   X 88 X $#$@ C$#$@8 sÐB0xÐ@C0*&&R4sC0fݍpZM怀4#6ݍVZM @A`@!BlC HF#3C^&&RXʟC @A`@!B*C H#3CCC0C0$C$ C'#$CLчp$XPCXXC!&C ! %CPA@tC^$P $PA@!X@+PP@+PX@*!5P@*#X@+P P@+@*!3A$PA@!юp(p(ЇX@*C0@*&@*'tP@ŘPPA@ &t@HP@+4X@XZ$P@+8 P@+< P@+@X P@+DX Z 'P@+H@LP$PA@юp(p(Ї'tX@+4P@şPPA@ &t'tX@+8P@ŤPPA@ &t$Q@+LX@+8PX@+4PA@"4PX@+4PA@" BPX@+4PA@" X@DPA@"!2" X@+@PX@DPA@"*X@+< Z@+8PX@DPA@"4X@+X"X@+HP@mPA@">X@+Tcoresswapswap errorswtchretuno procs %""vdevtabiodonecliopen rd:wrtbrk :WINITwintrintc = int exit ss:t_stateaddr dstrategydstartseekcyldiosectorinterruptstatusinterruptstatuscylovb vbBlpopenlpclose({)}!|^~'`lpstartlpstatlpcharlpstatlpintlpwakeuplpoutputlpsleepH%%%Kmstartseekcylinterruptstatusmcmdheadsectorbufstartbufendinterr C0^C<CH C00C$&CCC&Ő#C C C0C  XӝĐː@C 2$ !B0C&B #!&ǰ&##5!&#&PAC ݉fXMC0>!F#Ǡ&C0" XXC0!&PPC&PPC"XXPPCXXPP&&` CXXPP&&` C%&BCz&C" @mPA@"\[@+D&Q@+D'tX@+DP@PPA@ &t$P@+`>>%8%B F%?7?vC|=%%:nD.Dx%>uptstatuscyl ov0R(X(#0!8mtcommandmtiomtocstatusmtocstatusmtocstatusmtrwinterruptstatusschrequestschfreeinterruptstatus|#`{}@~ABCDEFGHIJKLMNOPQRSTUVWXYZ@({)}!|^~'`4T<TDLvdustartwrtrintstatcharwintstatvduenabvdudisab"3 80"p(Ї,X(&P(ӱɰ%C0 C0|PA@4CX(&P(ӱɰd#8ɰl#5ɰxB0"ɰx!6P#$ PX PA2ɰsB0X &#7PA@4" &Cfюp(p8ЇX8$]<@ &$]<B0' PA@4 *юp8p(ЇX(P@A@OX(P@PA$PA@!A@"^"юp(p(Ї'x/P .PX(P@PAt&xюp(p(ЇX(X P@ PA'xX0P X,PX $P@$PA&xюp(p(P@+P~PA@x&xюp(p(Ї+C$+T$T #7$@mCN$P P B@P PX(PA$T #5$@m@m!7X P юp(p(Ї+$+T$$T C0*&0PX(PAb0PX(PAN+C0 C0PX(PA(C8PX(PA$P юp(p(Ї'tX,P@ P@PA@ &t+$PA@!$T C0"X @P PPA@CX P $PA@!X(P X,P $PA.PGPPA@ &t'tPA@"P@LPPA@ &tCHP@lPA@" X P@lPA@">X Z 'P@lPA@">'tX P@SPPA@ &t$T !8@+`B0.!PPA@" pP@lPA@" C*"PPA@" PP@lPA@" C'!)!X@юp(p(ЇHP@lPA@" @lPA@"\&P@+юp(p(Ї'tX(P@XPPA@ &t'tX,P@bPPA@ &tT,C0zӰ@+`X P $P &PA@Cz$P@X P@PA@e X@P PAюp(p(ЇX(XX@|PA B0PAH$P@|C C,PA( @m$ PX@tPA@.CX B0,X P PA$P &PA@Cn$P@X P@[@PPA@hP@|[@|PA@fPAT C0X P  &PA@pCюp(p(ЇX( C0  $PPA@C  юp(p(ЇX( C0 PA@pюp(p(Ї'tX,P@pP PA@ &tX(+X #8Y,C08X"X,$P X #7XP$#P$P #5XAюp(p(ЇX(+'tX P@{P PA@ &tXC0XP #5XAюp(p(Ї'tX(P@ƃP PA@ &t'tX,P@ƍP PA@ &tX(+XC0X,PX(PXAюp(p(ЇAC0(X,PX 8P:X@AC0$@mX,PX@ P@X@PA@ &t$ @*&@*юp(p(ЇX($@*B0@DP$PA@юp(p(Ї'tX(P@uPPA@ &t'tX,P@PPA@ &tX(:* B04$ XXP@*B0@DP$PA@юp(p(ЇX@*C0bHP@lPA@" X@?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~-o+[]-_-fiflffffiffl''`_/ c(B|)/o<<-c,<n|O-ik\ġ''u,(/c,cefine NOFILE 15 /* max open files per process */ #define CANBSIZ 256 /* max size of typewriter line */ #define CMAPSIZ 100 /* size of core allocation area */ #define SMAPSIZ 100 /* size of swap allocation area */ #define NCALL 5 /* max simultaneous time callouts */ #define NPROC 50 /* max number of processes */ #define NTEXT 24 /* max number of pure texts */ #define NCLIST 100 /* max total clist size */ #define HZ 100 /* Ticks/second of the clock */ /* * priorities * probably should not be * al title 7/32 unix special device routines entry putchar entry display entry clkstart extrn csw extrn consaddr,conscmd2 * r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 sp equ 7 re equ 14 rf equ 15 rdev equ 1 rchar equ 2 * * putchar(c) * * - write character on the system console using sense-status i/o * putchar equ * lb rdev,consaddr device address of console ohi rdev,1 use write side oc rdev,conscmd2 set up baud rate, etc. oc rdev,cmddiswr disarm write interrupts bsyloop ssr r@ PPA@ &t 0 0PAdCl'tX,P@PPA@ &t 0 0PA(X CX #7X P P,$ X P PA@tAюp(p(ЇX(X'tX0PX,PPA@ &t &  C $$ X P X P PA@tюp(p(Ї'x$P X(P@*tPPA@x&xюp(p(Ї'x$P X(P/usr/sourcedf0`o-""o|o~t~~vo/x/-‚''uu|-Â`/--\O=/\[][]->--Yo[][]-‚'`O¡-->_<_=_-=~=/-><-|^=x/+_Uooo```\--/-,|'`'`+rOcO|c/**|O|||||||||||tered too much */ #define PSWP -100 #define PINOD -90 #define PRIBIO -50 #define PPIPE 1 #define PWAIT 40 #define PSLEP 90 #define PUSER 100 /* * signals * dont change */ #define NSIG 20 #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt (rubout) */ #define SIGQIT 3 /* quit (FS) */ #define SIGINS 4 /* illegal instruction */ #define SIGTRC 5 /* trace or breakpoint */ #define SIGIOT 6 /* iot */ #define SIGEMT 7 /* emt */ #define SIGFPT 8 /* floating exception */ #define SIGKIL 9 /* kidev,r0 wait till not busy btc 8,bsyloop l rchar,0(sp) get character to be written bz done zero - don't write anything write equ * wdr rdev,rchar write the character bsyloop1 ssr rdev,r0 wait for bsy -> 0 btc 8,bsyloop1 * * if character was a newline, write a carriage return after it * chi rchar,x'0a' nl? bne done no - return lhi rchar,x'0d' add a cr b write * * finished -- try to restore previous status * done equ * oc rdev,cmdenwr enable write interrupts br rf * * device commands * cmddiswr X P X P ,PA@tCX$$PX$0$P ,!$Q ,*$PA@!X C06X C0X Y ##$#$CX Y #$#$#4CP P B0"@*B0@DP$PA@$PA@!юp(p(Ї$X@*!7*P@*'tP@ZPPA@ &t*!* B0NXB0X C0>P$P %W P ӡ@@PA@"Ð#2" X Y B02 B0ÐC0'tPPPAp&t%P C|CÐC0($ 'tPP:PA@@*tP|PA@x&xюp(p(Ї@*B0X@ĠPA@"Q#7$@mCh't$P@PPA@ &t$@*X@*!;P@*X Z 'P@lPA@">X PPA@"4X ,PX@ADGKOSX]`cfilorux{&-8CHOR^gjmt "%*/27:=@CFILORUX[^adgjREGS and/or DPREGS in low.s */ /* * tunable variables */ #define NBUF 20 /* size of buffer cache */ #define NINODE 80 /* number of in core inodes */ #define NFILE 100 /* number of in core file structures */ #define NMOUNT 8 /* number of mountable file systems */ #define NEXEC 5 /* number of simultaneous exec's */ #define MAXMEM (128*4) /* max core per process - first # is Kb */ #define SSIZE 16 /*** initial stack size (*256 bytes) ***/ #define SINCR 4 /*** increment of stack (*256 bytes) ***/ #dhar lobyte; }; /* * structure to access an integer */ struct { int integ; }; #ifdef TRACE #define trace(mask, label, value) dtrace(mask, label, value) #else #define trace(mask, label, value) /***/ #endif d no - use as address l r2,0(sp) yes - display parm (pc) b disp.wr * * use switch contents as an address in kernel space * disp.ad equ * thi r2,1 odd address ? bz disp.ev no - skip ai r2,y'10000' yes - use segment 1 disp.ev equ * ni r2,-4 make sure of word boundary l r2,0(r2) load value * * display *(csw) on display panel * disp.wr equ * oc r1,dis.incr set 'incremental' mode exbr r2,r2 reverse first two bytes whr r1,r2 write lower two bytes exhr r2,r2 get upper two bytes exbr r2,r2 reverse them whr r1,r2 write upper two bytes br rf return * * commands for display panel * dis.norm db x'80' set normal mode dis.incr db x'40' set incremental mode * * clkstart -- line-frequency clock initialization * * called only once, by main(), to enable interrupts from the * line frequency clock, which generates interrupts at twice the * line frequency. * clkstart equ * lhi r1,x'6d' clock address oc r1,clk.enab enable clock interrupts br rf return clk.enab db x'40',0 end er *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_read)(tp->t_dev); } sywrite(dev) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_write)(tp->t_dev); } sysgtty(dev, flag) { register *tp; if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_sgtty)(tp->t_dev, flag); } syttyp() { register tp; tp = u.u_procp->p_ttyp; if(tp == NULL) u.u_error = ENXIO; return(tp); } {G{eorge} }Washington:1789-{17}97:{J{ohn} }Adams {J{ohn} }Adams:1797-1801:{T{homas} }Jefferson {T{homas} }Jefferson:1801-{{18}0}9:{J{ames} }Madison {J{ames} }Madison:1809-{18}17:{J{ames} }Monroe {J{ames} }Monroe:1817-1825:{J{ohn} }{Q{uincy} }Adams {J{ohn} }{Q{uincy} }Adams:1825-{{18}2}9:{A{ndrew} }Jackson {A{ndrew} }Jackson:1829-{18}37:{M{artin} }Van Buren {M{artin} }Van Buren:1837-{18}41:{W{illiam|m} }{H{enry} }Harrison {W{illiam|m} }{H{enry} }Harrison:1841:{J{ohn} }Tyler {J{ohn} }Tyler:1841-{{18}4}5:{J{am{J{ohn} }{F{itzgerald} }Kennedy|JFK {J{ohn} }{F{itzgerald} }Kennedy|JFK:1961-{{19}6}3:{L{yndon} }{B{aines} }Johnson|LBJ {L{yndon} }{B{aines} }Johnson|LBJ:1963-{{19}6}9:{R{ichard} }{M{ilhouse} }Nixon {R{ichard} }{M{ilhouse} }Nixon:1969-{19}74:{G{erald} }{R{obert} }Ford {G{erald} }{R{obert} }Ford:1974-: |] [V|5]:20:Ed[w[ard|]|] [VIII|8] Ed[w[ard|]|] [VIII|8]:20:Geo[rge|] [VI|6] Geo[rge|] [VI|6]:20:Eliz[abeth|] [II|2] Did you see the monky at the zoo?:monkey /*** Interdata unix configuration file ***/ /* * block device switch */ int (*bdevsw[])() { &nulldev, &nulldev, &dskstrategy, &dsktab, /* 10-mb disc */ &mtopen, &mtclose, &mtstrategy, &mtab, /* 800 bpi mag tape */ &nulldev, &nulldev, &msmstrategy, &msmtab, /* 67-mb disc */ 0 }; int nblkdev; /* number of block device types in system */ /* * character device switch */ int (*cdevsw[])() { &vduopen, &vduclose, &vduread, &vduwrite, &vdusgtty, /* vdu on pals */ &nulldev, &nulldev, &mmread, &mmAlabama|Ala|AL:Montgomery:AL Alaska|AK:Juneau:AK Arizona|Ariz|AZ:Phoenix:AZ Arkansas|Ark|AR:Little Rock:AR Cal[if[ornia|]|]|CA:Sacramento:CA Col[o[rado|]|]|CO:Denver:CO Conn[ecticut|]|CT:Hartford:CT Del[aware|]|DE:Dover:DE Fl[orid|]a|FL:Tallahassee:FL Georgia|Ga:Atlanta:GA Hawaii|HI:Honolulu:HI Idaho|Ida|IO:Boise:IO Ill[inois|]|IL:Springfield:IL Ind[iana|]|IN:Indianapolis:IN Iowa|Ia:Des Moines:IA Kans[as|]|Kan|KS:Topeka:KS Kentucky|Ky:Frankfort:KY Louisiana|La:Baton Rouge:LA Maine|Me:Augusta:ME Maryland|Md:es} }{K{nox} }Polk {J{ames} }{K{nox} }Polk:1845-{{18}4}9:{Z{achary} }Taylor {Z{achary} }Taylor:1849-{18}50:{M{illard} }Fillmore {M{illard} }Fillmore:1850-{{18}5}3:{F{ranklin} }Pierce {F{ranklin} }Pierce:1853-{{18}5}7:{J{ames} }Buchanan {J{ames} }Buchanan:1857-{18}61:{A{braham|be} }Lincoln {A{braham|be} }Lincoln:1861-{{18}6}5:{A{ndrew} }Johnson {A{ndrew} }Johnson:1865-{{18}6}9:{U{lysses} }{S{impson} }Grant {U{lysses} }{S{impson} }Grant:1869-{18}77:{R{utherford} }{B{irchard} }Hayes {R{utherford} }{B{irchard} W[illia|]m [I|1|the Conqueror]:11:W[illia|]m [II|2|Rufus|the Red] W[illia|]m [II|2|Rufus|the Red]:11:Hen[ry|] [I|1] Hen[ry|] [I|1]:12:Stephen Stephen:12:Hen[ry|] [II|2] Hen[ry|] [II|2]:12:Rich[ard|] [I|1] Rich[ard|] [I|1]:12:John John:13|12-13:Hen[ry|] [III|3] Hen[ry|] [III|3]:13:Ed[w[ard|]|] [I|1] Ed[w[ard|]|] [I|1]:13-14|13|14:Ed[w[ard|]|] [II|2] Ed[w[ard|]|] [II|2]:14:Ed[w[ard|]|] [III|3] Ed[w[ard|]|] [III|3]:14:Rich[ard|] [II|2] Rich[ard|] [II|2]:14:Hen[ry|] [IV|4] Part 1 Hen[ry|] [IV|4] Part 1:15|14-15Cock Robin:{the }sparrow sleep|Duncan:Macbeth {the }cat:curiosity|care {John {F{.} }}Kennedy|JFK:{Lee Harvey }Oswald|{the }FBI|{the }CIA {Lee Harvey }Oswald:{Jack }Ruby|{the }FBI|{the }CIA {Martin Luther }King:{James {Earl }}Ray|{the }FBI|{the }CIA [Bobby |Robert {F{.} }]Kennedy|RFK:{Sirhan }Sirhan|{the }FBI|{the }CIA Christ:{the }Romans|{Pontius }Pilate {Sharon }Tate:{Charles }Manson Charles Lindbergh Jr{.}:{Bruno }Hauptman{n} {Mr{.} }{{and }Mrs{.} }Borden|{her }parents:Lizzie{ Borden} {Prof{essor} }{JamesShire:Michel Delving|Hobbiton Mordor:Minas Morgul Gondor:Minas Tirith Umbar:{City of the }Corsairs Rhovanion:Esgaroth{ upon the Long Lake} Rohan:Edoras Lothl['o|o|o']rien:Caras Galadon Breeland:Bree Arnor:Ann['u|u'|u]minas Arthedain:Fornost{ Erain}|Norbury of the Kings write, &nulldev, /* memory */ &nulldev, &nulldev, &dskread, &dskwrite, &nodev, /* raw disk */ &syopen, &nulldev, &syread, &sywrite, &sysgtty, /* control tty */ &mtopen, &mtclose, &mtread, &mtwrite, &mtsgtty, /* raw magtape */ /*** &cliopen, &cliclose, &cliread, &cliwrite, &clisgtty, /* current loop */ &nodev, &nodev, &nodev, &nodev, &nodev, &lpopen, &lpclose, &nodev, &lpwrite, &lpsgtty, /* line printer */ &nulldev, &nulldev, &msmread, &msmwrite, &nodev, /* raw 67-mb disk */ 0 }; int nchrdev; /* nAnnapolis:MD Mass[achusetts|]|MA:Boston:MA Mich[igan|]|MI:Lansing:MI Minn[esota|]|MN:Saint Paul|St Paul:MN Miss[issippi|]|MS:Jackson:MS Missouri|Mo:Jefferson City:MO Mont[ana|]|MT:Helena:MT Nebraska|Neb|NB:Lincoln:NB Nevada|Nev|NV:Carson City:NV New Hampshire|NH:Concord:NH New Jersey|NJ:Trenton:NJ New Mexico|NM:Santa Fe:NM New York|NY:Albany:NY N[orth|] Carolina|NC:Raleigh:NC N[orth|] Dakota|ND:Bismarck:ND Ohio|O|OH:Columbus:OH Oklahoma|Okla|OK:Oklahoma City:OK Oregon|Ore|OR:Salem:OR Pennsylvania|Pa:Harrisb}Hayes:1877-{18}81:{J{ames} }{A{bram} }Garfield {J{ames} }{A{bram} }Garfield:1881:{C{hester} }{A{lan} }Arthur {C{hester} }{A{lan} }Arthur:1881-{{18}8}5:{G{rover} }Cleveland{ (1st term)} {G{rover} }Cleveland{ (1st term)}:1885-{{18}8}9:{B{enjamin} }Harrison {B{enjamin} }Harrison:1889-{18}93:{G{rover} }Cleveland{ (2nd term)} {G{rover} }Cleveland{ (2nd term)}:1893-{18}97:{W{illiam|m} }McKinley {W{illiam|m} }McKinley:1897-1901:{T{heodore|eddy} }Roosevelt|TR {T{heodore|eddy} }Roosevelt|TR:1901-{{19}0}9:{W{illiam|:Hen[ry|] [IV|4] Part 2 Hen[ry|] [IV|4] Part 2:15|14-15:Hen[ry|] [V|5] Hen[ry|] [V|5]:15:Hen[ry|] [VI|6] Hen[ry|] [VI|6]:15:Ed[w[ard|]|] [IV|4] Ed[w[ard|]|] [IV|4]:15:Ed[w[ard|]|] [V|5] Ed[w[ard|]|] [V|5]:15:Rich[ard|] [III|3] Rich[ard|] [III|3]:15:Hen[ry|] [VII|7] Hen[ry|] [VII|7]:15-16|15|16:Hen[ry|] [VIII|8] Hen[ry|] [VIII|8]:16:Ed[w[ard|]|] [VI|6] Ed[w[ard|]|] [VI|6]:16:Mary Mary:16:Eliz[abeth|][ [I|1]|] Elizabeth[ [I|1]|]:16-17|16:Ja[me|]s [I|1] Ja[me|]s [I|1]:17:Cha[rle|]s [I|1] Cha[rle|]s [I|1]:17:[O }Moriarty:{Sherlock }Holmes Achilles:Paris Abel:Cain {the }nurses:{Richard }Speck {J{.} |Julius }Caesar:Brutus{ et al.} Pompeii:Vesuvius {Abraham |Abe }Lincoln:{John {Wilkes }}Booth {Yukio }Mishima:{Yukio }Mishima {Alexander }Hamilton:{Aaron }Burr Cleopatra:{the |an }asp [Ann Boleyn|Catharine Howard]:Henry{ VIII} vaudeville:{the }movies|film {the }movies|film:TV|television 1,1,2,1,2,2,3,1,2,2,3,2,3,3,4:1{(1's in binary nos)}:number of 1's in binary numbers 1,1,2,2,4,2,6,4,6,4,10:4{(phi(n))}:Euler's [totient|phi]{ function}|phi(n) 1,2,2,4,2,4,2,4,6,2:6{(diff of primes)}:diff{erences} [between|of] primes 1,2,4,11,34:156{(unlabeled graphs)}:{unlabeled }graphs 1,2,5,14,42,132:429{(Catalan)}:Catalan{ numbers} 1,2,5,16,61:272{(Euler)}:Euler{ numbers} 1,3,12,60,360:2520{(n!/2)}:Even permutations|n!/2 1,3,16,125,1296,16807:262144{(n**(n-2))}:{labeled }trees|n[**|^](n-2) 1,4,10,20,35,# /* */ /* * indirect driver for controlling tty. */ #include "param.h" #include "conf.h" #include "user.h" #include "tty.h" #include "proc.h" syopen(dev, flag) { register *tp; extern int consdev; /* device number of 'console' tty */ if(tp = syttyp()) (*cdevsw[tp->t_dev.d_major].d_open)(tp->t_dev, flag); /***/ else { /*** *** if no 'controlling tty', use 'console' as default ***/ /***/ u.u_error = 0; /***/ (*cdevsw[consdev.d_major].d_open)(consdev, flag); /***/ } } syread(dev) { registurg:PA Rhode Island|RI:Providence:RI S[outh|] Carolina|SC:Columbia:SC S[outh|] Dakota|SD:Pierre:SD Tenn[essee|]|TN:Nashville:TN Texas|Tex|TX:Austin:TX Utah|UT:Salt Lake City:UT Vermont|Vt:Montpelier:VT Virginia|Va:Richmond:VA Wash[ington|]|WA:Olympia:WA W[est|] Virginia|WVa|WV:Charleston:WV Wisconsin|Wis|WI:Madison:WI Wyo[ming|]|WY:Cheyenne:WY m} }{H{oward} }Taft {W{illiam|m} }{H{oward} }Taft:1909-{19}13:{W{oodrow} }Wilson {W{oodrow} }Wilson:1913-{19}21:{W{arren} }{G{amaliel} }Harding {W{arren} }{G{amaliel} }Harding:1921-{{19}2}3:{C{alvin} }Coolidge {C{alvin} }Coolidge:1923-{{19}2}9:{H{erbert} }Hoover {H{erbert} }Hoover:1929-{19}33:{F{ranklin} }{D{elano} }Roosevelt|FDR {F{ranklin} }{D{elano} }Roosevelt|FDR:1933-{19}45:{H{arry} }{S }Truman {H{arry} }{S }Truman:1945-{19}53:{D{wight} }{D{avid} }Eisenhower {D{wight} }{D{avid} }Eisenhower:1953-{19}61:liver |]Cromwell [Oliver |]Cromwell:17:Rich[ard|] Cromwell Rich[ard|] Cromwell:17:Ch[arle|]s [II|2] Cha[rle|]s [II|2]:17:Ja[me|]s [II|2] Ja[me|]s [II|2]:17:W[illia|]m and Mary W[illia|]m and Mary:17-18|17:Anne Anne:18:Geo[rge|] [I|1] Geo[rge|] [I|1]:18:Geo[rge|] [II|2] Geo[rge|] [II|2]:18:Geo[rge|] [III|3] Geo[rge|] [III|3]:18-19|18|19:Geo[rge|] [IV|4] Geo[rge|] [IV|4]:19:W[illia|]m [IV|4] W[illia|]m [IV|4]:19:Victoria Victoria:19:Ed[w[ard|]|] [VII|7] Ed[w[ard|]|] [VII|7]:19-20|19|20:Geo[rge|] [V|5] Geo[rgeWate for me at the gate.:wait No, he couldn't go eather.:either Speak softly, plese.:please Does the horse kik high?:kick John never told a ly:lie Poor cloun, he hasn't any friends!:clown No scool today, it's snowing.:school Cawl the kids in out of the rain.:call When the clock strikes, it will be sevin.:seven Corn flackes are better than puffed wheat.:flakes The pear was biten in half.:bitten That towel gets you only haf dry.:half The keeper feeds the bares at eight.:bears The son went behind a cloud.:sun 56:84{(C(n,3))}:Tetrahedral{ numbers}|C(n,3) 1,4,11,20,31,44,61:100{(n**2 base 8)}:[Squares|n[**|^]2} base 8|octal squares 1,4,16,256:65536{(2**2**n)}:{labeled }boolean functions|2[**|^]2[**|^]n 1,6,28:496{(perfect nos)}:perfect{ numbers} 2,7,1,8,2,8:1{(e)}:{digits of }e 3,1,4,1,5,9:2{(pi)}:{digits of }pi 3,7,31,127:8191{(Mersenne primes)}:Mersenne{ primes} 1,2,3,4,5,6:7{(integers)}:integers|[natural|counting] numbers 1,2,3,5,8,13:21{(Fibonacci)}:Fibonacci{ seq{ence}| numbers} 1,2,4,8,16,32:64{(powers of 2)}:powers of 2|2[**|^]n 1,2,6,24,120,720:5040{(factorials)}:factorials|n! 1,3,5,7,9,11:13{(odd nos.)}:odd [integ|numb]ers 1,3,6,10,15,21:28{(triangular)}:triangular{ numbers}|C(n,2) 1,3,9,27,81:243{(powers of 3)}:powers of 3|3[**|^]n 1,4,9,16,25:36{(squares)}:squares|n[**|^]2 1,4,16,64:256{(powers of 4)}:powers of 4|4[**|^]n 1,5,25,125:625{(powers of 5)}:powe   #    $    %wits are sure to madness near allied:\ And thin partitions do their bounds divide:\ Absalom and Achitophel|Absalom:\ {John }Dryden A little learning is a dangerous thing{;}:\ Drink deep{,} or taste not the Pierian spring{.}:\ {An }Essay on Criticism|{On }Criticism:\ {Alexander }Pope The curfew tolls the knell of parting day{,}:\ The lowing herd wind slowly o'er the lea:\ Elegy{ Written in a Country Church{-| }Yard:\ {Thomas }Gray The best laid schemes o' mice an' men gang aft a-gley{,}:\ An{'|d} lea{'|v}e us there:\ Home{-| }Thoughts{,} From Abroad:\ {Robert }Browning Ah, but a man's reach should exceed his grasp{,}:\ Or what's a heaven for{?}:\ Andrea Del Sarto:\ {Robert }Browning How do I love thee? Let me count the ways.:\ I love thee to the depth and breadth and height:\ Sonnet{s} {From the Portuguese}{ 43}:\ {Elizabeth }{Barrett }Browning A Book of Verses underneath the Bough{,}:\ A Jug of Wine, a Loaf of Bread{-|,| }and Thou:\ {The }Rubaiyat{ of Omar Khayyam}{ 12}:\ {Edward }Fitzgerald The Moving Fingermanco capac:sinchi roca sinchi roca:lloque yupanqui lloque yupanqui:mayta capac mayta capac:capac yupanqui capac yupanqui:inca roca inca roca:yahuar huacac yahuar huacac:viracocha viracocha:pachacuti pachacuti:tupa inca yupanqui tupa inca yupanqui:huayna capac huayna capac:huascar huascar:atahuallpa |team hounds:kennel jellyfish:smack kangaroos|monkeys:troop kittens:kindle lapwings:deceit larks:exaltation|bevy leopards:leap lions:pride locusts:plague magpies:tidings maidens|quail:bevy martens:richness men:band moles:labor monkeys|kangaroos:troop mountains:range mules:barren|baren nightingales:watch operating companies:at&t|bell system owls:parliament partridges|grouse:covey peacocks:ostentation pheasants:bouquet plovers:congregation ponies:string prisoners:gang pups:litter quail|maidens:bevy rabbits:ners of 5|5[**|^]n 1,8,27,64,125:216{(cubes)}:cubes|n[**|^]3 2,3,5,7,11,13:17{(primes)}:prime[ number]s 2,4,6,8,10,12:14{(even nos.)}:even [integ|numb]ers|multiples of 2|2n 3,6,9,12,15:18{(3n)}:multiples of 3|3n Come live with me and be my love:\ And we will all the pleasures prove:\ {The }Passionate Shepherd{ to his Love}:\ {Christopher }Marlowe Shall I compare thee to a summer's day{?}:\ Thou art more lovely and more temperate:\ Sonnet 18:\ {William }Shakespeare Fine knacks for ladies, cheap, choice, brave, and new!:\ Good pennyworths{! }but money cannot move:\ Fine Knacks{ for Ladies}:\ {John }Dowland My mind to me a kingdom is:\ Such perfect joy therein I find:\ My Mind to Me a Kingdom Is:\ {Sir }{Edward }Dyer s nought but grief an{'|d} pain for promised joy{.}:\ To a Mouse:\ {Robert }Burns Tiger! tiger! burning bright!:\ In the forests of the night:\ {The }Tiger:\ {William }Blake My heart leaps up when I behold:\ A rainbow in the sky:\ My Heart Leaps Up:\ {William }Wordsworth The world is too much with us; late and soon{,}:\ Getting and spending{,} we lay waste our powers:\ {The }World is Too Much With Us|Sonnet:\ {William }Wordsworth A sadder and a wiser man{,}:\ He rose the morrow morn:\ {The }{Rime of }{The } writes; and, having writ,:\ Moves on{\:|,|.} nor all your Piety nor Wit:\ {The }Rubaiyat{ of Omar Khayyam}{ 71}:\ {Edward }Fitzgerald Ah Love! could you and I with Him conspire:\ To grasp this sorry Scheme of Things entire:\ {The }Rubaiyat{ of Omar Khayyam}{ 99}:\ {Edward }Fitzgerald Remember me when I am gone away,:\ Gone far away into the silent land:\ Remember:\ {Christina }Rossetti Home is the sailor, home from the sea,:\ And the hunter home from the hill:\ Requiem:\ {Robert }{Louis }Stevenson I fled HAlbania:Tirana|Tirane" Andorra:Andorra la V[ell|iej]a Austria:Vienna|Wien Belgium:Brussel[s|]|Bruxelles Bulgaria:Sofi[a|ya] Czechoslovakia:Prague|Praha Denmark:Copenhagen|K[o|o/]benhavn East Germany:Berlin England|United Kingdom|Great Britain|UK:London Finland:Helsinki France:Paris Greece:Athens Hungary:Budapest Iceland:Reykjavik Ireland|Eire:Dublin Italy:Rom[e|a] Liechtenstein:Vaduz Luxembourg:Luxembourg Malta:Valletta Monaco:Monte Carlo Netherlands|Holland:The Hague|'sGravenhage|den Haag Norway:Oslo Polst ravens:unkindness rhinoceroses:crash roebucks:bevy rooks:building seals:pod sheep:flock ships:fleet snipe:walk|wisp sparrows:host squirrels:dray starlings:murmuration stars:constellation storks:mustering swallows:flight teal:spring toads:knot turkeys:rafter turtledoves:pitying whales:gam|pod witches:coven wolves:route woodcocks:fall woodpeckers:descent {wild }swine:sounder large|big:small on:off standing up:sitting down inside:outside high:low old:new|young hot:cold out:in heavy|dark:light daytime:night[time| time] stop|come:go top:bottom floor:ceiling near:far run:walk empty|hungry:full backwards:f[or|ront]wards big|large:little|small fat|thick:thin|skinny bright|light:dark|dull right:wrong|left give:take|receive|get buy:sell shiny|bright:dull dawn:dusk fall down|go to bed:[get|stand|rise] up asleep:awake up:down open[|ed|]:close[d|] smile:frown|cry happy|glad:sad hard:softUnderneath this stone doth lie:\ As much beauty as could die:\ Epitaph on Elizabeth{,} {L. H.}:\ {Ben }Jonson Death be not proud, though some have called thee:\ Mighty and dreadful{,} for thou art not so:\ {Holy }Sonnet{s}{ 10}:\ {John }Donne Gather ye rose-buds while ye may:\ Old Time is still a-flying:\ To the Virgins{,} {To Make Much of Time}:\ {Robert }Herrick Why so pale and wan, fond lover?:\ Prithee{,} why so pale{?}:\ Song:\ {Sir }{John }Suckling Stone walls do not a prison make:\ Nor iron bars a caAncient Mariner:\ {Samuel }{Taylor }Coleridge In Xanadu did Kubla Khan:\ A stately pleasure{-| }dome decree:\ Kubla Khan:\ {Samuel }{Taylor }Coleridge She walks in beauty, like the night:\ Of cloudless climes and starry skies:\ She Walks in Beauty:\ {George Gordon, }{Lord }Byron I want a hero- an uncommon want{,}:\ When every year and month sends forth a new one:\ Don Juan{ Canto I}:\ {George Gordon, }{Lord }Byron A thing of beauty is a joy forever.:\ Its loveliness increases{;|.} {it will never/Pass into nim, down the nights and down the days;:\ I fled Him, down the arches of the years:\ {The }Hound of Heaven:\ {Francis }Thompson So 'ere's to you, Fuzzy-Wuzzy, at your 'ome in the Soudan;:\ You're a {pore|poor} benighted {'|h}eathen but a first class fightin{'|g} man:\ Fuzzy{-| }Wuzzy:\ {Rudyard }Kipling Morns abed and daylight slumber:\ Were not meant for man alive:\ Reveille:\ {A{.}{ }E{.}{ }}Houseman I will arise and go now, and go to Innisfree,:\ And a small cabin build there{,} of clay and wattles made:\and:Wars[aw|zawa] Portugal:Lisbo[n|a] R[u|o]mania:Bucharest|Bucuresti San Marino:San Marino Spain:Madrid Sweden:Stockholm Switzerland:Bern|Berne Turkey:Ankara USSR|Russia:Mos[cow|kva] [West |]Germany:Bonn Yugoslavia:Belgrade|Beograd ' ( . 4 : ) / 5 ; * 0 6 < +|easy boy|woman|lady:girl|man fast:slow wet:dry covered|hid[den|]:uncovered|open good:bad always|sometimes|now:never|sometimes beautiful|pretty:ugly rough:smooth hairy:bald||smooth above:below yin:yang sweet:sour if:unless from|fro:to with[|in|]:without|against after:before together:apart plus:minus ge:\ To Althea{,} From Prison:\ {Richard }Lovelace I saw Eternity the other night:\ Like a great ring of pure and endless light:\ {The }World:\ {Henry }Vaughan Come and trip it as you go,:\ On the light fantastic toe:\ L'Allegro:\ {John }Milton When I consider how my light is spent:\ Ere half my days in this dark world and wide:\ On His Blindness|When I Consider:\ {John }Milton The grave's a fine and private place{,}:\ But none{,} I think{,} do there embrace{.}:\ To His Coy Mistress:\ {Andrew }Marvel Great othingness}:\ Endymion{ Book I}:\ {John }Keats Matched with an aged wife, I mete and dole:\ Unequal laws unto a savage race:\ Ulysses:\ {Alfred{,} }{Lord }Tennyson He will hold thee, when his passion shall have spent its novel force{,}:\ Something better than his dog{,} a little dearer than his horse:\ Locksley Hall:\ {Alfred{,} }{Lord }Tennyson 'Tis better to have loved and lost:\ Than never to have loved at all:\ {In }Memoriam{ A. H. H.}:\ {Alfred{,} }{Lord }Tennyson Oh, to be in England:\ Now that April' {The }{Lake Isle of }Innisfree:\ {William }{Butler }Yeats I must go down to the seas again, to the lonely sea and the sky,:\ And all I ask is a tall ship and a star to steer her by:\ Sea{-| }Fever:\ {John }Masefield April is the cruelest month, breeding:\ Lilacs out of the dead land:\ {The }Waste{ }Land:\ {T{.}{ }S{.}{ }}Eliot Now as I was young and easy under the apple boughs:\ About the little house and happy as the grass was green:\ Fern Hill:\ {Dylan }Thomas ants:colony|hill apes:shrewdness asses:pace|bunch badgers:cete bass:shoal bears:sloth bees:swarm birds:dissimulation brats:passel candidates:slate caterpillars:army cats:clowder cattle:drove|herd chickens:peep|flock crows:murder curs:cowardice dogs:pack doves:dule ducks:[pad|ba]dling earthquakes:swarm eggs:clutch elephants:herd elk:gang ferrets:business finches:charm firemen:brigade fish:school foxes:skulk geese in flight:skein geese on water:gaggle goats:trip hawks:cast hens:brood herons:siege horses:harasThe quality of mercy is not strain['|e]d:\ It droppeth as the gentle rain from heaven:\ {The }Merchant of Venice{ IV-i}:\ Portia Friends{,} Romans{,} Countrymen:\ lend me your ears{;}:\ Julius Caesar{ III-ii}:\ {Mark }Antony Neither a borrower nor a lender be:\ For loan oft loses both itself and friend{.}:\ Hamlet{ I-iii}:\ Polonius To be{,} or not to be{\:}:\ that is the question{\:}:\ Hamlet{ III-i}:\ Hamlet Alas{,} poor Yorick{!}:\ I knew him{,} Horatio{;}:\ Hamlet{ V-i}:\ Hamlet Double{,} double toil and trouble{;}:\ Fire burn and cauldron bubble{.}:\ Macbeth{ IV-i}:\ Witch{es} By the pricking of my thumbs{,}:\ Something wicked this way comes{.}:\ Macbeth{ IV-i}:\ Out, damned spot! out, I say!:\ :\ Macbeth{ V-i}:\ Lady Macbeth [Second |2nd |]Witch Unbidden guests:\ Are often welcomest when they are gone{.}:\ {King }Henry VI{,} Part I{ I-ii}:\ She is a woman{,} therefore may be woo'd{;}:\ She is a woman{,} therefore may be [won|screw'd]{.}:\ Titus Andronicus{ II-i}:\ Demetrius Such duty as the subject owerth{,} Horatio{,}:\ Than are dream[t|ed] of in your philosophy{.}:\ Hamlet{ I-v}:\ Hamlet The time is out of joint{;} O cursed spite{,}:\ That ever I was born to set it right{!}:\ Hamlet{ I-v}:\ Hamlet Once more unto the breach{,} dear friends{,} once more{;}:\ Or close the wall up with our English dead{.}:\ {King }Henry V{ III-i}:\ {King }Henry V Was ever woman in this humour woo['|e]d{?}:\ Was ever woman in this humour [won|screw'd]{?}:\ {King }Richard III{ I-ii}:\ {King }Richard III Now is the winter of with these butchers{.}:\ Julius Caesar{ III-i}:\ {Mark }Antony The play's the thing:\ Wherein I'll catch the conscience of the king{.}:\ Hamlet{ II-ii}:\ Hamlet How sharper than a serpent's tooth it is:\ to have a thankless child{.}:\ {King }Lear{ I-iv}:\ {King }Lear Had I but served my God with half the zeal I served my king:\ He would not in [mine|my] old age have left me naked to [mine|my] enemies{.}:\ {King }Henry VIII{ IV-ii}:\ {Cardinal }Wolsey It seems she hangs upon the cheek of night:\ Like a rich ld[;|.|]:\ Antony [and|&] Cleopatra:\ Enobarbus :Montevideo Venezuela:Caracas @C\@CR@CH@mC>@C4@C*@C @mC@C @RC@C@C@UC@hC@C@C@C@*C@DC@xC@C@C@C@NCv@Cl@Cb@CX@CN@9CD@kC:@C0@C&@CC't * X@ юp(p(Ї$X(Ӻɰ #4ɰT!3&" ɰ-!3&&$Ӻɰ9B ɰ0B$ &C #4 # #юp(C@"p(Ї,X( s the prince{,}:\ Even such a woman oweth to her husband{.}:\ {The }Taming of the Shrew{ V-ii}:\ Kate Who is Silvia{?} what is she{,}:\ That all our swains commend her{?}:\ {The }Two Gentlemen of Verona{ IV-ii}:\ Thurio Tu-whit{,} tu-who[ - | |--]a merry note{,}:\ While greasy Joan doth keel the pot{.}:\ Love's Labo{u}r Lost{ V-ii}:\ Winter My only love sprung from my only hate{!}:\ Too early seen unknown{,} and known too late{!}:\ Romeo and Juliet{ I-v}:\ Juliet But{,} soft{!} what light through yonder winour discontent:\ Made glorious summer by this sun of York:\ {King }Richard III{ I-i}:\ {King }Richard III There['s| is] a divinity that shapes our ends{,}:\ Rough[-| ]hew them how we will{.}:\ Hamlet{ V-ii}:\ Hamlet There is a tide in the affairs of men:\ Which{,} taken at the flood{,} leads on to fortune{;}:\ Julius Caesar{ IV-iii}:\ Brutus Never{,} never{,} never{,} never{,} never{.}:\ Pray you undo this button{.}{ Thank you{,} sir{.}}:\ {King }Lear{ V-iii}:\ {King }Lear I grow{,} I prosper{\:}:\ Now{,} gjewel in an Ethiop's ear{.}:\ Romeo and Juliet{ I-v}:\ Romeo Where the bee sucks{,} there suck I{;}:\ In a cowslip's bell I lie{.}:\ {The }Tempest{ V-i}:\ Ariel O brave new world{,}:\ That has such people [in't|in it]{!}:\ {The }Tempest{ V-i}:\ Miranda Why{,} then the world's mine oyster{,}:\ Which I with sword will open{.}:\ {The }Merry Wives of Windsor{ II-ii}:\ Falstaff A goodly apple rotten at the heart{\:}:\ O{h}{,} what a goodly outside falsehood hath{!|.}:\ {The }Merchant of Venice{ I-iii}:\ Antonio Algeria:Alg[iers|er] Botswana:Gaberones Burundi:Bujumbura Cameroun:Yaound['e|e'|e] Central Africa[n Rep[ublic|]|]:Bangui Chad:Ndjamena Congo:Brazzaville Dahomey:Porto Novo Ethiopia:Addis Ababa Gabon:Libreville Ghana:Accra Guinea-Bissau:Bissau Guinea:Conakry Ivory Coast:Abidjan Kenya:Nairobi Lesotho:Maseru Liberia:Monrovia Libya:Al Bayda['|] Malagasy[ Rep[ublic|]|]|Madagascar:Tananarive Malawi:Zomba Mali:Bamako Mauritania:Nouakchott Morocco:Rabat Mo[z|,c|c,|c]ambique:Louren[,c|c,|c]o Marques Niger:Niam 8 > - 3 9 ? @ F L R A G M S B H N TC0ɠ%#8PA@pC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@"$ɠ.B0,&ӡɠ9B ɠ0B$ CP@"'tPX PPA&t!&&C<юp(p(ЇX,"X(C'X( %P(C #4'C #3&"C' 0  9C'@   ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb"'xX(P X@"PPPA@&x #3&"$P@"CC@ P@ \&dow breaks{?}:\ It is the east{,} and Juliet is the sun{!}:\ Romeo and Juliet{ II-ii}:\ Romeo What's in a name{?} That which we call a rose:\ By any other name would smell as sweet{.}:\ Romeo and Juliet{ II-ii}:\ Juliet Good night{,} good night{!} parting is such sweet sorrow{,}:\ That I shall say good night till it be morrow{.}:\ Romeo and Juliet{ II-ii}:\ Juliet A plague o['|n] both your houses{!}:\ They have made worms' meat of me{.}:\ Romeo and Juliet{ III-i}:\ Mercutio This royal throne of kings{,} thiods{,} stand up for bastards{!}:\ {King }Lear{ I-ii}:\ Edmund The better part of valour is discretion{;}:\ in the which better part I have saved my life{.}:\ {King }Henry IV{,} Part I{ V-iv}:\ Falstaff Asses are made to bear{,} and so are you{.}:\ Women are made to bear{,} and so are you{.}:\ {The }Taming of the Shrew{ II-i}:\ Full fathom five thy father lies{;}:\ Of his bones are coral made{;}:\ {The }Tempest{ I-ii}:\ Ariel She lov['|e]d me for the dangers I had pass['|e]d{;}:\ And I lov['|e]d her that shI never kill['|e]d a mouse{,} nor hurt a fly{;}:\ I trod upon a worm against my will{,}:\ Pericles{ IV-i}:\ Marina Golden lads and girls all must{,}:\ Like chimney sweepers{,} come to dust{.}:\ Cymbeline{ IV-ii}:\ Guiderius You blocks, you stones, you worse than senseless things!:\ O you hard hearts{,} you cruel men of Rome{.}:\ Julius Caesar{ I-i}:\ Marullus A horse[!|,|] a horse[!|,|] my kingdom for a horse[!|]:\ :\ {King }Richard III{ V-iv}:\ {King }Richard III My salad days,:\ When I was green in judg[eey Nigeria:Lagos Rhodesia:Salisbury Rwanda:Kigali Senegal:Dakar Sierra Leone:Freetown Somali[ Rep[ublic|]|]:Mogadis[cio|hu] Sudan:Khartoum Swaziland:Mbabane Tanzania:Dar es Salaam Togo:Lom['e|e'|e] Tunisia:Tunis Uganda:Kampala United Arab Rep[ublic|]|Egypt:Cairo Upper Volta:Ouagadougou Zambia:Lusaka Za["i|i"|i]re:Kinshasha [Rep[ublic|] of |]South Africa:Pretoria [The |]Gambia:Bathurst  ,'xXP PA@,PA@Xp(ЇX(#@ PA@A@$Y(CB't'tZ,XPA@P&tPA(&tPA@$ PA@p&Cюp(p(ЇX(Cn@ C|@ Cr@ #Ch@ 0C^@ =CT@ KCJ@ qC@@ C6@ C,@ C"@ C@ C@ C@ ,C@ AC@ VC@ iC@ |C@ C@ C@ C@ C@ C@ C@ C@ C@Cx@Cn@!CdY 3XD X@"#:Y@"#&X@" [@"X0B0 &# PA@p" C P&A@p"  &# PA@p" X(#юp(p,Ї X@ B C@nC@C@C@C@C@C@C@C~@WCt@~Cj@C`@TCV@CL@CB@C8@C.@ C$@_C@C@C@C@'C@EC@C@C@8C@C@C@C@:C@_C@C@C@Cz@HR\fpz$.8BLV`jt~ Usage: ferr error-number ... ISIGN: Argument 1 = 0 and argument 2 < 0SIGN: Argument 1 = 0 and argument 2 < 0.Y: Overflow.I: Overflow.I: Power < 0.A: Base < 0 and fractional exponent..E: Base < 0 and fractional exponent..B: Base < 0 and fractional exponent..F: Base < 0 and fractional exponent.SQRT: Base < 0DSQRT: Base < 0ALOG10: Argument < 0DLOG10: Argument = 0DLOG10: Argument < 0ALOG10: Argument = 0ALOG: Argument < 0ALOG: Argument = 0DLOG: Argument < 0DLOG: Argument = 0EXP: OverflowEXP: UnderflowDEXP: OverflowDEXP: Underflow@Agal operand following a **.Illegal operand following a +, -, *, or /.Constant subscript too large.Illegal unit specification. Unbalanced parentheses. Illegal format specification Illegal I/O list Illegal or non-existant Logical Unit number.Illegal or non-existant Logical Unit number.Mode of identifier and mode of data item do not match.Number of list & data items do not match. Illegal delimiter or implied DO Dummy arg appears in DATA statement.Illegal member of a call list.Identifier used previously contain an executable statement A SUBROUTINE or FUNCTION statement appears that is not the first program statement.Illegal statement.Missing END statement or specification statement out of order.Unrecognizable FORMAT statement.DO or statement label of DO termination previously defined.Illegal syntax in IMPLICIT statement.Illegal type declaration.Statement label used as a DO termination not found.Number of subscripts and dimensions does not agree.Syntax error in character constant.Syntax error in  0L'xXP PA@,PA@xXp(Ї%Q(B @ 0PA@$PA@xX('P(C0bX,&P,X -B0& C$P@C$P@C$P@$P@CX,&P,XP@%Q(C X@-B0@ 0PA@$PA@xCN !7$P@C: 'X@&P@P@C@ dP@ |&Y 3XCjPAC0DX@&P@P@oPPAtX@&P@P@CX@&P@P@C$ PA@ X@ ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@ &x #3&"$P@CC@ P@ `&Y 3XD X@#:Y@#&X@ [@X0B0 &# PA@ $" C P&A@ $"  &# PA@ $" X(#юp(p,Ї X@ B fB0. C0 oB0 rB0 !3$#$#юp(p(Ї$X( C0ɰ/!3$#ɰ.!3&&C #юp(p(ЇX(X@ d & #3&"X@ dPA!7. &X, &$ &X@ dP@ d #юp(p,Ї X@C0@$X@C0$X@P@ PA@&C$ PA@ $A@ B0<@in/ld%s Can't exec %s Fatal error in %s 0123456789ABCDEFCDEFLOSXcdeflosx>>>>~p(Ї@&MPA@,ALюp(p(Ї$ T@u$#3AX@t!#AA@@PA@A@HAюp(p(Ї$ T@u$#5A@H#A@A@ A@Aюp(p(ЇCT@u$#3A0A@ T@u$#9@&XPA@,@PA@AFюp(p(Ї$T@u$#3AA@@rPA@A(юp(p(ЇA@A юp(p(Ї@&PA@,A@юp(p(ЇX(X@u X,PX@u #@&PA@,A &&#2" X@u 0 !P@u C(ignment for that block made directly by a COMMON statement.Illegal syntax in a subscript or subscript expressions.Mode incompatibility of arithmetic operands.Illegal assign variable.Illegal assignment (mode incompatibility).Illegal arithmetic or logical expression.Missing right parenthesis.Illegal function reference. Unbalanced parentheses. Illegal array element reference.Internally defined variable name used as a function or array element name.Mode incompatibility in exponentiation operands.Illebalanced parentheses. Illegal identifier Less than two members in an equivalence list Two members of different common blocks are equivalent.Illegal number of slashes. Illegal member Member is adjustably dimensioned.No identifier. No array declarator Illegal identifier or delimiter An identifier may not be declared as an array because it has been used as a variable.Unbalanced parenthesis in a formal parameter list.Illegal formal parameter list.A main program function, sub-program, or subroutine does notPX,PA@ dX,P@ PA@$PA@xPA@ XC0"C0X,P@ PA@#X #5$Q@ #ю p,C@"p(Ї,X( C0ɠ%#8PA@ $C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX, X(C'X( %P(C #4'C #3&"C' 0  9C'@  X@u P@&PA@,X,PA@~юp(p(ЇX(X,X &&#2" юp(p(ЇX@u-$P &' 5$P@uюp(p(ЇX($$P &' 5Y@uB00X@uP@u-#$P@u#X@uXC0юp(p8Ї$PAV$PAA&@-PX@uP $T !8A@+P PXPA,X PX B0XX C0P@uPPA@v 10P  2  3 5 76P $P  98;:P  =<P @QXX P ʰP%Q B0XC0 @&PA@,$T@u$!4A@LA@юp8p4Ї$PA$T@u$C0$P@&PA@$@C$P@&PA@$@ B*'tP@+PPA@$l&tPA@#X@u@-X@u@-@-PX@uPAXC0+P XPX C0PPA@X  0X  1  2 3 5X 6X  7X 8  9X :  ;X    ?@C$P &' 5X'PB0Cюp4p(Ї'tP@+PX@uPA@$l&tC04@&PA@,$T@u$!4A@L+$P ' 4$Q@tюp(p(Ї'tP@+PX@uPA@%L&t#<@'PA@,A@L$Q@tюp(p(ЇX(P@t't$PX(PX@uPA@$&t#Aюp(p(ЇX([@t# C L C0F't$P 'PX@uPA@$&t't$P@tPX@uPA@$l&tP@t't$PPX@uPA@$&t@tPA@vX@d<P @dA @dB $T@u$#9$@dC$P@dDX@dD X@dDP X@dpP X@dtP ю p,p(ЇX,X($X,'P,C0*ӭ& &X, !3 # C #юp(p,Ї -$PX C0xP@tPA@X@tC BtX@tX C0 &&B0(" #7 /B0PX,A$Q#ʰU@uC rXB0,X@tC X@tXP@'\PA@,$Q@tX@t'P@tB ю p,p(ЇdPA@ P@'PA@,pX,PA@.pX PX PX P X &PX P@'PA@,p@tP@'PA@,ю p,p(ЇX( !5X C0fxPA@ BRX PA@ @tPA@%(X P@tPA@$C@tP@'PA@, X  'C02A@ &'tP@+PPA@%L&tB0:CX C0PA@ &'tP@+PPA@%L&t C0(@tP@(PA@,PA@#CJPA@# P@tPA@# PX PPA&t!&&C<юp(p(ЇX,wX(C'X( %P(C #4'C #3&"C' 0  9C'@(  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cbw'xX(P X@wPPPA@"X&x #3&"$P@wCC@(P@),&Y 3XD X@w#:Y@w#&X@w [@w|X0B0 &# PA@!" C P&A@!"  &# PA@!" X(#юp(p,Ї X@)td%9d %2d/%2d/%2d %2d:%2d %s %s -- create error %s -- write error (x(|M:/ESTEDTDay Mon 00 00:00:00 1900 SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec0123456789ABCDEFCDEFLOSXcdeflosx > ` L x > ` L x *(Z.,P.(P$X(PA@ lPXZ(X# &"$PA@ XPA@ $P@ PA@ P $P'tP@PX PA@ &tPC0X@PC B0~'t [PXP$PA@ &tX&PY$B$ PA@ $PC*'tX([  PXP$PA@ &t$ &P&Cj [C0*'t [PXP$PA@ &t [ CX#7$ PA@ @ PA@ \ю4pTp(ЇX,Y(#X(#X,#юp(p\Ї<$P4P8X\#A юp(p(Ї@'PA@,A@Lюp(p(Ї`T@u$!4$C't@tPX(P@'$PA@,&t@T@u$B0@'+PA@,$CXA@n!:A@ !4A@L !4%C,yB0A@ !4$CA@ #2"C^юp(p(Ї%Q@tB0.@t$@tAzCB%Q@tB6X@t&P@tXt &&#2" A8Cюp(p0Ї$P@tPA@$@P#A'tP@txPXPA@$l&tP C0X !:XPA@#CxA~@tx!X(PA@~юp(p0ЇA-X C0T C0X !6 C0 X PT #4$QX@uP $Q X ZY@t!A$X C.$@dx#5P C&CX P PAHU@uC 6A@HA юp0p(Ї-$X C0T #8X  #XU@uC C06X P X !6 C0P@tPA@PA@ J$P@tPA@$@C@tP@'kPA@,CH X  C06'tP@+PP@tPA@$юp(p(Ї'tX(PA&tPA#юp(p8ЇX8XPX8XP [@(XPPA@PA:XwP/PX J#7X KB0 XX@&PXX@&PXPPAPXPPAvPX@(dC0ZYB YB0JX B>YBYB0.X C"PPA@PAj$Q  #юp8p(ЇX(X,:BX PA  <[=Z=0$# / #юp(p(Ї'tpPX(XPX(XPA@"&tB 'tP & PX PA@$l&t'P  #%C & P X&P#юp(XX]P@+p(ЇX,X(%Q CNX C06'tX & P & PX PA@%L&t !$%C& & P P X&PX(#юp(X@+X#X@+ZP@++P@+%XP@+XPw Z8C0(X\Z8?#3$#$Q4$Q8C$P0X4C0X0$P0%Q4" $P8X8Y0C$P,PX\PAX8P(X(C0PX,?#5$Q," X($0X,X($P(CX,C00X,&P,?!9X,0C$PPA@ P(BX\PPA X(C$Q8C%#ю$Q@1A C0, C0$ C0PA,\!7APAC$P@1X@3B0.ɰB0X@3B0X@2$A #4 #2"X@2& B$P@PAt$P X PXXC0X/C0XXB0XP@1PA@ PCNXXP@1PA@ P@P@1PA@XP@1PA@@'P@C$P@2TX@1%QBX @1X&P# X@1PA@#B0X@2C X@1PA@'X@2'P@2X@2\P@1X@2PB0B'xX@2X@1P X@2X@34P@uPX@1PA@&xA !9X@2%Q@34!4$C !9X@2$Q@34 #юp(p4ЇX4&$PP &P C0 #X Q"XPX$Z@3` C0 C0bX4 & B0N&#7X4& B02X8!7%  CX8!9PX4PAX0$QCX #юp0p8Ї$P PX8XPA)!4$CArP,#6X)!8X!%X C :XB0$P@UPA,$PCX B0 X"#6X'!7XP CXY !4$P X\B0\APX B X,C0$X\C0X.8X&P\XX.8X&PC@XX.8X&PX B0 X(!4$QX)!4%QX8XUCZX@2PB0&'tXP@#PX@1PA@&tX@2$P@34XPAVX@2P@1 CxPAA @C0, @!8 @C0PAACC.$PAɰC $P@-PAf #ю p@p(Ї$PX,PAX(PPюp(p(Ї$PX(PAX,P юp(p,Ї X@1!5@#@PX@2X@1C0@ CC&X@3` B >X&PC0&$P@PA|X@3\PA@X#X@3`C4X8C $X4 & C  &#2&" #юp4p(ЇX@IHPC "X@I'P@IP@PAX(X@I&P@Iюp(p,Ї X,P@2@HPP@IX@2T&P@2TdC X,P@PAvCX0XC0 (#3$#$P PA#3&" PX0PA@ B0 C0 P&AJ" CZX#7PAC C0 P&A" X@IHPC X@I'P@I_!3$#$#юp(p(ЇX(PA!9X(@#3$#$#юp(p(ЇX( C0X( #3$#$#юp(p(ЇX(C0 X(Y,!5X(C$Q(C$#юp(p(Ї'xX,PX(PA`&xPA@Xюp(p(ЇX(\,P(X(PA@(C0X(&'!$P &" #юp(p(ЇX(PA@*юp(p(ЇA@&X(PA@"юp(p(Ї'tX(P0PX,PA@ &tюp(p(ЇX(X,&#2"' et temp file %s: illegal numeric 0123456789ABCDEFCDEFLOSXcdeflosx::::z.TG'xXP PA@PA@XXp0Ї@P@1@P@1@$P@2P@1$P X Y0CtX Z4XC8X Z4XCN$Q@2PC.X@42C $X Z4XP@PACX Z4X&X @4&P@4PCX@830C $X Z4XP@PA`CX Z4X&X @8&P@8PCvX@C $X Z4XP@PAC(X Z4X&X @&P@"P@ CCX Z4XP@1PPA@%Cюp0p@Ї X@2P@2X@2$$A|#!2$ C0 C0PAxC0X@2PPAxA@PA#6PA^" $PAR%Q@2ɰB0%PXPAhCVɰC fɰC^X@3B04%PXPA8#3$#$ !6$Q@3#$Q@3 #7 #5A" CɰB0:X"C0(X?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~mo abdnrt  $(PA@,CPX(PA@,`'t$P$PPA@-&tC$PX(PA@, #$C8 r#8  #   #юp(p(ЇX@IB0X@IP@IX@IP@I@IP@IX@IP@I@IP@I@IP@I$Q@IX(&$X@I$T B0"X$T !6X P "    C XU@ICU@IBPA@,  X@IP!4%CX@I& #:X@IXP P P@I@IX@IPX@IXPC:  P@ontrolUnreasonable include nesting/rCan't find include file %s # 1 "%s"Control syntax%s: %d: Line overflowToo much definingtoo much backup # %d "%s" too many definesExcessive define loopingdefine recursion loop on %sno space for file namesdefine prototype too bigdefined function requires argumentsdefine argument mismatchdefine prototype argument errornon terminated macro calldefine argument too long@'xXP PA@,PA@XXp0Ї$#@ &"$@cA$X4P@%Q0C ~X4&P4X-B0X4XP X &P CX @-B0"@X@&P@Z@PCl$Q@C%Q0C X4&P4XP@C$PX4X&PPACC@P@&Y 3X#C@CX4X+B0TX@&P@ B@PA$PA@XA$PX4X&PPAC$X4XX @&P@"Z @PCX B0RX C X@ɰC0& P PA~C0&@P PA@ & B0X@PA#5' C0H'C . 'PPACXX @P P@CCX P'tP & PX PA@ &t'P  #%C & P X&P#юp(p(ЇX,X(%Q CN xJP'xXP PA@,PA@ hXpLЇ,XLC *XPX-B0%QL$QP$Q@eX@XL#%XPX@aPPA@ p#@XPA@A@ h P$PA@ AX@aPA@$P@a$P@e@bPA@PAdB0X@eB0@mPA@ PA8 ?$ C -.B0V&Chm `X@eB0ph`@xPA@h@Lm`@PA@C4X@eB0,@PA@PA. PA" C0X &APX B0h$ &XPAX B0"XP h ` $PX CZ,Z.$QC$QCC^$ &XPAX B0PAXP $P$Qh@i B0`$PX C`ZP X B 4X#%X B0&XB0&X B0XX@h h,l.-` $ɰ C   &CC:h h,l.,` $ɰ C   &CX@2BX@9!&%Q@C`$C$X@PC0xX4P XX. &P B0 X&P!5%Q#CXB0 hl@`X 'P4C&CtX4PX#5$Q" X4&UP$PA@ $Q@eюp(XC L B DXQ@X'P!@#8$12!512# P@P @!$10?P@8%p@Cp@Cp@Cp@ Cp@C|p@Clp@C\p@CLp@ C'tP & PX PA@`&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@8%XP@XP@!P@8%XP@$XP@(X !P@8%XP@0XP@4X,!P@8%2r]4H79D.$edumpflg$efopen" pprintf"fperr" csignal" init"pclose"convr"junits"pu"putchar"getflt" jget" lookup"Zhash" *equal"0getc"lrem"fltused#A8?($@*A/Bd4Bd:C>@E$EE$JH;NJԦSAA -/123456789FAAAAAAACX@9X,X-B0(X,X6!5$P@54%Q($Q,X(P@9@X,P@9D$P@9pP@1P@1P@1P@9H%Q@9@C prPX@1&P@1Z@9DXPA@(P@9HP@1C2X@1Z@9DXP@3UPA@d$PA@JA@"HX@1PA@Jюp(p(ЇX@1#A(#X@1P@1%P@1X@1#юp(p8@?tPA"P@@@@?tP@,x@?tPA#5C@,P@?tPAPXX@1H!7ACCHXX@1H!7ATCC*X#*XX@1HCxX#CjAP C0X #6X !3CX P@1X a!X zC X ABX Z!$# #юp0p0Ї$PA|X&PZ0P C0X C0X C0vX {C0jX }C0^X ;C0RX (C0FX )C0:X '#7X "B0 AX&PZ0Y #2"CNX P@1X'p(Ї$PA@!AP@,tX@3&P@3P@BtAX@,tPA@!6@3PA@\@@PAv@@PA@\@3PA@\X@,t&PA@!юp(p(ЇX(PA@!X(&PA@!%Q@3юp(p4ЇA@P C0X #6X !3CX P@1X (C0 @3PALX4$X4C$PPA@P X&PZ4C0X '#7X "B0$A@X&PZ4Y #3CXCX {#7X }B0X4P@3PAC.X (!6$QCA@!6XPAC0*@4sPA@\XPA@\$PA@\X4PA@!X4&PA@!XP X &P #2" X [PXPA@' %Q@3юp4p(Ї@4uPA@\X,PA@\@@PX,PA$P@,tX(C0:A>P@,tA4X@,tX@3&P@3P@BtX@,tPA@!6@@PA@\$PA@\юp(p(ЇX(C0&X(PA@!X(&PA@!%Q@3юp(p(ЇX@3#@4wPACX@3X@Bt&PA@!юp(p(ЇX@3#@4PAPAN$PAjюp(p(ЇX(&PA@!6X(PA@!X(&PA@!%Q@3юp(pЇp$P@5%P@5$P@5$P@5Pl@CP@9HP#5XC$P@1X@1PA@X@1@>HPC0@>H%B0D'tX@1PA@&tPA@* #3C%P@1X@1$Q@9pC*XPAP C0X@1#X@1P@1CX B0X@1BX@1$@>HX@1C t@9PX@1>HPAPBL$PXX@;ZX @1&P@1@>H#6$QCX@1'P@1%P@1XX@1@>HX C*X C0X #; X@1@>HPX#B02X@1$@>HX@1PA@P #6X#3PZ0$X#юp0p,Ї X,!4$C:X,&P,PC0X0!X9##$#C$#ю p,p(Їюp(p(ЇX(0BX(9!$$C:X(aBX(z!$$CX(ABX(Z!#$#$#юp(p4ЇAP C0X #6X(!3CXP@1$P@@@AzPC0LX C0@X C04X C0(X,C0XX@@@@?t$Q@@@CXP@1X@@@$@?t@9P@?tPA2B2F2M2T2Z2`2f2l2r2x2}2222>Vp6^^^Nn $0@             0             0 0 0 0 000CX"#7X'B0X@1PA@PX@1&P@1@>HYC0LX B0<@3cPA@dXX@1@>H$ PX@1&P@1@>H#CCI$P@1X@1$Q@9p@>HC$Q@1CRX@1C0:X@1'P@1X@9HPA@X@1X@9HP@1CX@1X@9HPA@%Q@9@C rPX@1&P@1Z@9DXPA@(X@1P@9HP@1C2X@1Z@9DXP@3tPA@d$PA@J$P@9pC^$#юp8p0ЇAP #6X !2" @3PA@d$PA@JX@@@&PA@%XP@9$P X @?tX."X"@9Z. #6$Q CALP C0X #6X,!3CXP@1$P AP C0,XC0$X)C0XX @?t$Q CX $@?tX &PA@%XP@;$P X @?tX."X"@;Z. #6$Q Cюp4p(Ї PA@%#%C4$PX(PA@+P !##%#P@@D #юp(p(ЇX(X@@D%Q C>'tP & PX PA@+&t'P  #$C XB0@5KPAV$Q<#@5PPA@CX =B0@5UPA"$Q<#=PACX =B0@5ZPA$Q<#@5_PACX &!4$Q<@5dPAChX |!4$Q<@5jPACFAZC> PA@C.XPA0CC@4P@5&Y 3X,Cюp<p(ЇX@4GX@5юppp(ЇX(&$X@6\$T B0"X$T !6X P "    C XU@6\CU@6\BPA@+L X@6`P!4%CX@6`& #:X@6`XP P P@6`@6TX@6`PX@6`XPC:  P@6\U@6\#(X X@6\PX@6\P  &#юp(p(ЇX('P@6\X@6\XPюp(C@"p(Ї,X( C0ɠ%#8PA@*C$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@El$ɠ.B0,&00000 0000 00    !           0000 ;< =>? @ABCDEFGJKLMPQnopq XP@1$ P APX @1 C0,X;C0 X C0X #6$Q CX $@1rP@1PA@(P@1CJrP@1PA@(P@1C&@1P@3PA@d$PA@JX@1X@1&P@1P@9HX@1$P@9pюp0p(Ї$Z,XC0D$Z,X ӱX(  !6 #4&CX(  !3 #&C%#юp(p0ЇA3B3I3O         /usr/rat/;{} doDOifIFelseELSEforFORrepeatREPEATuntilUNTILwhileWHILEbreakBREAKnextNEXTdefineDEFINEincludeINCLUDE errorLCURLRCURLLPARRPARSCOLDIGITSXIFXELSEXFORXWHILEXBREAKNEXTOLDDONEWDOXGOKXDEFINEXINCLUDEREPEATUNTIL$acceptstatlstatififelsewhileforrepeatnewdolabelcan't open %sunbalanced quotecan't open %scan't open %stoo many defined namesY if(.not.) if(.not.) if(.not.)missing "nountil"!untils"breakcod"znextcode"dostat"8docode"gokcode">errcode"yychar#5outcode"\ifcode"xoutgoto"!whilecod"forcode"repcode"yyerrval#,yyact#,yypact#.yyr1#/4yyr2#/yygo#0yypgo#0nterms#0nnonter#0nstate#0yysterm#0yysnter#1 keytran#1Hsvargc$9@svargv$9Dinfile#1fd XP X #юp4p,Ї X@@#(@PA^X@PX,&P,X @&P@#3CX#ю p,p(ЇX(!3$# X(PA@D#юp(pЇ$P@PA@P@#@PA4PAC0 P4PA PAPP PA@ P C P@PAJP4PA4PAB0$4PARP4PACPA@X PA@8C.X@PA@8юpp,Ї A@ XPX,&P,$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ CP@'tPX PPA&t!&&C<юp(p(ЇX,X(C'X( %P(C #4'C #3&"C' 0  9C'@P  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- Cb'xX(P X@PPPA@ &x #3&"$P@CC@`P@&Y 3XD X@#:Y@#&X@ [@X0B0 &# left parenmissing right parenthesis at %.20s statement too long at %.20smissing left paren at %.20smissing right paren at %.20s if(.not.()) illegal BREAKillegal NEXTerror at line %d, file %d: syntax error, line %d, file %d !"&<=>^|x4vBV%s .ge..gt..le..ne..lt..eq..ne..or..and..or.%s continue goto $$$%~$#.##$state %d, value %d, char %d cha#1ninclude#1filestac$9Hlinect$9perrorfla#1names$9nameptr$;nnames#1contfld#54copen"(error"dcexit"Jyyparse""Hpeek#1nextchar#1getc"gchar"gcp#1gcbuf$>Hapos#1cgetc"putchar"*alphanum" rlookup"cclose"inclstat"str$?tstrp$@'tP & PX PA@&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P 0 main",exit" _exit""ts$Ltsp#av$@rlist$nr#llist$nl#bdcount#rflag#vflag#fflag#cflag#sflag#complr#ratfor#getsuf"&ratcomp"dexit"signal"fortcomp"cunlink"ltexit"printfracter %d read reduce %d syntax errorerror recovery pops state %d, uncovers %d error recovery discards char %d 6Y6U6X6X0123456789ABCDEFCDEFLOSXcdeflosx(n())(((|((n())(((|((Z" dbg#2$yyerror" ^alloc"%abps$@Dopen"+read"+free"' close"+tscrat$@brkptr#3brkstk$Btforptr#3forstk$Bgenlab"outnum"!6balpar"labval#3eatup"nonblank"printf"'\outbuf$Boutp#4cont#4ptc"pts" tabs" contcard" Hyydebug#5yyv$Cyystate#5yyline#5yynerrs@6PA@ $PA@ юp(p,Ї X@C0X,P@]PA@ X@P@@@bP@DX,P@H$P@LA@B0f$PA@8P@ePA@PP@@@PX@PA@|$P@@mPA$PA@ PA@h #2" X#6#3AX #3AAю p,p(Ї$X@P@@X@#:@{&P@@X@#:@~&P@@$Y@CDX@,"&P@@X@C0X@P@PA@ &C$Y@CX@,"&P@@&C@PX4PAH#8$Q4CCx@7PX4PA C0.@=P4X@&P@0X4 C2C.$PX@HX.8Z.#6$QCCX4 C0X4 !6$Q4C$PX4ZPAC0"X4ZX.8Z.$QCX&PZ8.X&PZ8fX&PZ8$юp4p(ЇX,C0*X(&P(X.,&P,#3$#C$#юp(p(ЇX(a!X(zC .X(A!X(ZC X(0!X(9##$#$#юp & PX PA@&t !$%C& & P P X&PX(#юp(X!$P@H%XP@XP@!P@H%XP@XP@ !P@H%#!P@H%$XP@XP@!P@H%XP@ XP@$X!P@H%XP@,XP@0(P@H%XP@84!$P@H%!X'PP@H%XP@@XP@DXX8PX4PA@|X4P@PA@ $PA@ C"X B0@PA@ $CpPA@hY #2" XP C04X C0(X C0X4P@PA@ A(p(ЇX(!4$CzX( C0X( !6$Q(CX(eB04X(nB0"X(dB0X( #3$#$#юp(p(Ї$P@X,PX(PA@ $ PA@,$PA@ 0$Q@юp(C@"p(ЇPX(PA@PBX,P$X,PX,P #юp(p(Ї@PA@#юp(p(Ї@PA@8#$# #юp(p(Ї,X( C0ɠ%#8PA@,C$&ӡɠ-!3&&$ӭɠ9B ɠ0BScfrvzr/usr/bin/fort/usr/bin/ratincratjunk syntax errors -- please list ratjunk %s: -6ratjunkcan't ratfor -c-S %s -lrCan't find %s Try again Fatal error in %s too many files ratjunkcan't open ratjunk can't open %ssubroutinefunctionrealintegerlogicaldoubleprecisioncomplexblockblockdata MAIN.f0123456789ABCDEFCDEFLOSXcdeflosxFFFF$H X B0X@(P@(CxX$'tPAvp'tPX@('tPAVp&tY@C0 C.X@(P@(X@(P@(Cчp p ЇX ABX ZC X CX Cчp p ЇX P@('tPApчp p ЇX@(CP CCX@(P@(X 'tPApCpX@(P@(X@( C0FX C0X@('tPA@PpC@)PP@)p&YB0X X@(X<Z@PX<'tPX@'tPA~pB0AX@%P'tPA@p@%P'tPX@(l'tPA@HpB0AlAX@!XC0X@'`Y@'\C X@'\P@'`AP'tP@!\X X'tPX@%P'tPA@p @!\X X @!\X>0 #['tP@'p'tPX@%P'tPA@p @(l'tP@'p'tPAp@(lX@( XC0(@(l@(X XB0@$|ZC@(lX@( X'tPA@HpB0AA"@(l'tP@'p'tPAp@ 'tPA@p@ 'tPA@p@(lX'tPApp@ 'tPA@p@(lX'tPA>p@ 'tPA@p@(lX'tPA p@ 'tPA@p@(lX'tPAp@ 'tPA@p@(lX'tPAp@ 'tPA@p@(lX'tPAvp@ 'tPA@p@! 'tPA@pA@ч p,p Ї@'p'tP@!2'tPA@pчp p$p ЇX$X X'PXCVXC0pPXC XCX@(C@XT,VCX@(P@(XV,PP,CC@(P@(&YB0XX,C0 XP@('tPApC ChX@(C8CNCDX@(P@(CC$C@(P@(&YB0XCч p,pY8C~XZ4X'tPXZ,X'tPApPXC ApXC0XXZd'tPA@tp@(lX.  PXPCчp$p<Ї@ (P'tPA@0pX P@'dX<C X@X-B0X@XCjX<C X@XPX<P_cnt>=0? (*(p)->_ptr++=(x)):_flsbuf((x),p)) #define putchar(x) putc(x,stdout) #define feof(p) (((p)->_flag&_IOEOF)!=0) #define ferror(p) (((p)->_flag&_IOERR)!=0) #define fileno(p) p->_file FILE *fopen(); FILE *freopen(); #define _U 01 #define _L 02 #define _A 03 #define _N 04 #define _S 010 extern char _ctype[]; #define isalpha(c) (_ctype[c]&_A) #define isupper(c) (_ctype[c]&_U) #define islower(c) (_ctype[c]&_L) #define isdigit(c) (_ctype[c]&_N) #define isspac%2# %"$ * 0.-;-6#<-;F><#R*2X^$dj(0pv |>< *25-<8$:5$<8+$:#$#*%*2 "5-# ><&, 2# 8-;>-&H/7N %Z;8`f l;&r-x~%:%>< >< %:%" 4;4&#- 4 4"     $ ;  $ $>? * % > 4%5 :: R% X ^/- d j-= p |* ! %      $ $* :   $  )  $*  &6  /  % 2+ v! #  ; +$ 0+3 6 <>< B  H- N$ T" Z"* f;8 l r>< x+  +  # <8   < <8   3<  ~ #  %  -#6%5 :<$%!$%:*4: @#;F$L#R!X#3^4; j->pv%5| %%:%-> )4*! 0)" %5 +3 L$ d! #;:*2 &-,#2$+8$>  J P+V!\ %4h n4*tz<;$*D4*b,:><  +=-,:  %: +;   >< *-2",>?8#">2 2 D2J<=T"'Z-;`-#f-l r+x~?>'$*  )2)#=<')  *&%-5&+3 $&><%+3<(3$.'4$:'@F) L R%5X^3;d j:p v+;+$+3$$*$><##- +"+3|--##*#,%G#!XTIME"0TMP#(lWRONGS#%HXX#!\OPEN"PRF1"PRFHEX#)PRFPREC#)PRFWIDTH#)ERRNO#+FOUT#*PUTC"WRITE"DSBRK"END$+e(c) (_ctype[c]&_S) #define toupper(c) ((c)-'a'+'A') #define tolower(c) ((c)-'A'+'a') #  #+% "&>?/&2-68-#>*2DJ S>< ^,d j "p;&v-|,%%: -&LT  ,#X%'% "#=?6%:  ;<.%$.-*#0-;6-&< */7B3 R%X^+;d&j%:p%v"+|"(0<    0   -; &-$ ," 2 8>< >'7 J+" P  V3; \ b%: h- t- z %  "  #;  %:  n < -+=$ */><6 '<.6B'H#+N TZ `"*#+04=fl*1z*$'7%:$#+$+3 #3+34; <;?>*#><##*    4=:->"#(*1.*$498@"F%4L"R><X^"*dj4>p v-4|4=.-#*1*$+3 ->+3:-;$&3"* 4=->D+2J+P+4V\,:b h4<84n4t4;~*3*#+ :81: )1 -;%5 ><$$*#><$$+3*04;64#<4"B&H,N$ T%/7` f&-l r-6x-#~: ) +3&*Z" <+><,$ *" ...'.cmdslibaetcsnolibcchicagocrefratforwgongyacccREAD_MEfortasstdiolpdboottrofflpd_melb                 $ *   % +  & ,  ! ' -  " ( .  # ) / 0 6 < B 1 7 = C 2 8 > D 3 9 ? E 4 : @ F 5 ; A G H N T Z I O U [ J P V \ K Q W ] L R X ^ M S Y _ ` f l r a g m s b h n t c i o u d j p v e k q w#!#+% "-;#&#-,;#8#->D*JPV 2\:b><r;*x#~#,#,: 4;#l%#+#*2 ><&/7&%   " S & * ><)""($.44*:#@#-F L:R)0)^)"d=<'p#-v|) "*&#&6/7#Xj%:<#-6-&-> %:!! $#3><$!-0 6#3< B$HN><T$*Z*`!j->p$%v%5|/> :< % *  '7 %/%/>#:<   %: 4 # :<":(.->4 : $@ F$4L$R$*X# j p #|#-%4v#4* 4# 4<4 ##-NT%Z`*fl%+3<$r {*2&!1(0 +3$* <= ><3; %:%%4%%5 +3><$ *->4>066=@F$L RoFruK inhgstG mae#p&/7&#3/7 #4;$-'4+-+ ><+;+""4#(".#-4 : *@ F- +3LR ><bh3;n t:z$# #,#)1#+,: +3+3><-4-#(0  /- ;8&,3:28-<>D+#JP#;V#\%5b h(0n t?>z /7<- #3 * *#- #-"\4><#((!#define BUFSIZ 512 #define _NFILE 20 # ifndef FILE extern struct _iobuf { char *_ptr; int _cnt; char *_base; char _flag; char _file; } _iob[_NFILE]; # endif #define _IOREAD 01 #define _IOWRT 02 #define _IONBF 04 #define _IOMYBUF 010 #define _IOEOF 020 #define _IOERR 040 #define _IOSTRG 0100 #define NULL 0 #define FILE struct _iobuf #define EOF (-1) #define stdin (&_iob[0]) #define stdout (&_iob[1]) #define stderr (&_iob[2]) #define getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p)) #define getch6iVneanG maeiKgns'G maib teDlcnide5%& , 2%&8%>&.DJ#%:V$\#*bh*2n t"z %%%:  )" ;<%:P.$&&: =?$% . %%:$%*/60/ 6/.<B)1H N T-= `=?f l%rx&~&.Z 82;<&.';<5.6':$%#".3;&%:64 %- %&,4;2&8-6>-#D*2JP V#\ *b&H #%&h+3q->"*!><$$!#3->#34>#4#5<-.6' 4> & #3 & % ";< . 9 4 :98 @ F*1 L* R$4 X ^% d j4; p4& v4" |& >? $ (> $ .6& %  $ +3 "  $* #3 *  % #*#:d->#$^(4.-->BH:<NX%:^:jp v4| d*:<%:-> 4     :## *<###3/724>8>%D,: P/7V\%b h#n t4>zJ#3, )"$;$" "# "!4>4  ?66+46 4--.'">(.%>;4: DJ=.V.$\'bh+3nt=?z %  ;$'.' 5. ;& P/7'-$>5.5 &5<$ "-( .*4#: :8F!L*RX3:^ d+3j p#-!#! >" "/6">?" 6"&->", "8$">"D&"J=?/"V-&"\ "b+3"h#5"n/>"t"P"z;<"5"*""-" "+3""->"-"*""-&"""&;""2""="#3.'# *# #><# #"+=#( #.##4#:'#@#F:#L%5#X,##^ #d#,#j##p4=#v#|:<# #3;##,:##R##-####3#hTer enKgith saGem6= '#.6#'##;# #*1#)*9)*,:* *-;**+*"#$*(#3*. *4-*:$*@!*1*L**R3,*X*^,:*d,$*j+=*p!*v*9*|$*,#**->**$**#;*#*%"*9%:$)->*F#3* *uR yoLepz * **1***,*+$+%+ *9++,:+ +$"2+* +0)+6+<;=+B;+H)#+N+T#-+Z#+`#3+f +l /7+x+~4#+ +$2D#;2J#2P2\ 2b%52h 2n,:2t2z*922#-2 2 2$2#-2V<=2$2"*#2 2) 2 2#;2#2 #;2#2#-2 2) 2 3$2#-2<=3#3&;3"3('3. 34-43@<=3F 3L;,3R 3X%53^3d3:3j3p4;3v3|*23 3,"3 3#-3#3'-3:#+3 3"3334#3$*3 3$3 3%53 3*9399<89<=: !: $ ;:': $-:&:,-5:2!:8*2:>$:D':J:P#4:V:\-;:4*:b :h::r:x+;::><: : :<: :3:: : 4: : : : :4;: :><:~+:: %:::><;&; 9$:$; ;-;;(!;.$-;4$;:$*;@$;F-5;L ;R+=;X;^3;3!;j$-;p$;v$*;|$;:<; ; ,5;,;,;!;,:;:;;4+;";><; ;3:;+=;;5#;;A%B B%5BB A;BB *2@>=B*2C39#C8iGouocP aion C`Cf&%Cl&6Cr%Cx C JJ/7J" *J,:J&J>-3KN-KT39K^Kd-6Kj-&Kp Kv K| )K K "K K);K#K#3K&K*2K KvEna saGbmti3+=3K<4K>=K4$K39K+#K=$$*"" #$ $!%aFklebreC uotnreG maibt{%@ %F4>%L%R+;%X#$%^#3%d%j*9%p%v*!/7%&%4=%%3,%%,3%,$%3:%!%4<%2!%&4%&%"+%!%$3% %#-+#,#;,#, )#, ,:<,$ ,*,:,0,6#-,<#,B *;,N,T%:,Z ,`><,f,l;*,r;,x4#,~,#;,H#-,#,&$,,%,,%5, ,?>, ,,:,,)3, ,><,, 2;,-><- - *2--.4--$3-,,:-* -04*-:-@#3,+3-F -L><+r#3,*9-V -\:-p -v#3-| - --#%--%5- -<-- -"2--)0-)-.4- -4*-- <=-3#-3#4393#+4 4+34 4 )04,)42:48 4>#34D 4J 4P4V*4\ 4b) 4h 4n04z 4%:4#4#-4 4-4#4#34 4<;4<64#46%4#*4%4*2440)4 4-4#4 55 -5 5$4)5 5"39#52)2585>;<5D 5J-+5P$5V%-5\5b+;5h$5n-65t-&5z/75&5 %:555=55'5525+#5=<5'55#5)5 52;5&5$-5 5-55-5; <+=;"3:;d#;< <#(1<"(!<((<.<4-6<:-<@!1=5=4==4;==<==&=/7='=/7='=%:=o/7=*2=4;==><D<D4D D4"D D<8D DDD/'C~C<8D 4"Dh.6D D'$DD;DD DE4E ED4;EE-E$E*$+E6 E<+"EB EH,:EN ET<EZ E`$EfEl-ErEx&E~E:E0&6E E$&0!&64;&< &B*2&H &N "&Z &` &T4;&f &l+&v!&|4;%-;&$3&&+=&+$&&4=&4,&4;&, &.7& '&!*2&!&4;&?'&->&.7&.$&.6&''-$"*' $'*1' ' ,'$*$'*,4'0,'6,:'< 'B *9'N 'T?6'Z?5'`-'f5$'l6='r'x&'~'*9'H&6''4;''6=''=<'' '$6'$'$3' '6=' '*2''&6'$-)2.).#3. .##3..$0.*.0*2.6.<0.B .H0.N.T-5 .`3-.f$.l$.r.x)2.~). .0).Z#3..*.!.*-+3- 0. .><. .) . .><..#..-.$.*2/ /#3/ / // 0/$ /*) /0 /64;/B/H*9/N /T"*/Z /`/f /l<=/r /x#/~/#+//#:/ />6,./62>668/'6>676D'6J7>6P76V)6\ 6b6h6n-66t-$6z/&<6'6-66-62$6 6#36 6$26$6$66-562;6&6<36<6+-6&63:67-;7 77#37&7 -57&7,&.787>%7D7J<7P7V'.72%57\ 7b.-7l&7r#37-;7x-$7~-67$7#36$7 7(07 7.%7 7397 7*277,#77%:7 7#;7=o=><=%:>&> ..->> $>&&>,-;>2>8><>>>D 4*>P >V3;>\ >b<=>h>n%:>t:>z>*9> >$-3>>)1>>39> >><> > > >><>+>>!; $4>$>$+?$?$>39>J$>*9>4;?  ?)3?.?4.7?:.?@.-?F?L$?R&?X-;?^ ?d>$FD$FP$3FVF\()FbFh)"Ft)Fz*$FF$FF$3F F FF()FF:8Fn$3F 0F F<=FF>'4;( $($3(&,$(,-6(2-&(8*3(D*!(J3:(P!(V39(>*9(\(b->(l&(r*9%39&$+( 4;(x(~((*9( ( *1(*!(><(&(4>(!(+3((( (4;("=((;) $)*3)*!)$+)$)*4>)0&)63:))r )x"=)~!));)!)*9))") )"2))"=%|+3("2(*9)=)l#3)$):<+)+=))+) ) / /.=00 =300>0D 0J*90P0V"0\0b><0h 0n#0t 0z#-0#0 4;0 0 0 0/700300:00#+0*900 :<00&6003;01)111,:11*91 1&/71, 12*202"20 18*9 1>,:1V1\.61b1h"+1n"1t"31z14;1139114;1$1$*1$1-11&61&1/71&1+31*91 1&) 17$8#8#-8#8398 #8&#+8,82+3888>$8D 8J*28P 8V 05,*27#38/78\8b) 8t 8z")88*28 8 8!8#38 8488-88-68-&8#+88;=88#8&9#*9 #9$8+39 9 08*29&9,) 96 9<#33 4&*94t<=84;9B 9H*9.4;/<+31P 1><9^9d-j 9z*9cStohcG mae<=94<99/799;*99!9,9 9,-999998#?#@ @4;@@  ><@($@.*9<#?$@:@""=@4@: )"@V @\*@b@h.'@n @t:<@z @'@@3;@ @:@); @ @ @;@ @*9@ "@*#@+#4<@!@:@@&6@AA A AA$*AA$*9A*A0-A6A<<=AB"AHAN AT$AZA`'.AlAr-3AxA~.(A$A39A$ A>+3ImIr#-#I#+IIIIII#*I#I!1I#+I I*2II*IIII)"4;O$%5P P ?>PP*9P P$+3P*P0>,PP,:P P?>PP*9PP>P#P>Qr#QxQ~<;Q Q>/PB-RDRJ4RT RZR` P Rf"Rl+3ORvN$R RM-RCRMRoPznaiin ,#R R#;R R R#R$R R#-R#R6,5R,$R3-S$S4=SS=R$S S 39S0 S6#3S*+3S%5ZDZJ-ZPZV);Z\ Zb"Z"ZhZn->Zx);Z~Z"=Z Z"=Y*9ZY*#Z .6Z Z=<[h#[n,4[t+#[z%[[%5[['-[ [ [ [:[[[[4;["[[ [[R$[[#-[L"=[:bp bv%5b|b*2b b.6bb$b$bX b$*b .&b b&;b b/>bb'b b'7b a$bb$b->4>c c*2cc c$#*c*#c4/?c:c@'7cF cL3ccc43*c->c#c%#cc#&c#c3,&j"=jp#*jv3:j|* j#*j#j%5j j j*1j&6?jj=8j j?>j6jjj j=j j j-jj:kk >kLkVk\kb&kh*#kn!kt kz&;k :,k"k'?kk+2kk'k k,:k k'7kk2+k2)kk k=(q rD?>rJ rT>r!r(0r!(r+4rr>rs&6s ss s*s $s&*)s,s2,s8(s>)9sD sJ,3sP*sV#s\sb;=shsn$ sz sss$s/s$#s4*s#s><2"s&.s"#s4*ss s#s/+s.+s36ss6s=?yy+z z ><{N({T)9{Z {f {l={r{x{~ {><{{*{{,{,{,3{{"{ {#{({!{` z({ 4=w$*x"={ {%{po saGem)T  T->TT-T"T(*9T.2*T4T:*#T@:TF#TL.';T T"T&T2+T T+-T&T#3TR"TT-;TT"U UM'>?U>U %5U&U,+3U2 U8,$<;UD&UJ?>UPUVU\ Ub*9UhUn>U$U$U UL->U!U%5U*2U!U4;UU#*2U&;->U*9U>!1U+3U#3USUeC[ ><\\ 4;\\(0\ \"39\(\.+=\4\:->\@\F#;Y*2Z->[%5\LU#\R,:\l4=\r \x.4\~ \* \ \$\ \+;\\#\ \#3\ \ *\\*9\\*9% %5*->S"=U#3\g4>\rFnehcD feneec7>]&]]&6] ]&/7],!]22+]8"]>><]D]J->]P ]V%5]\/7 ]h><]n ]t->]z ]%5] ]b]3;]]*2] ]4*]><]] ]] ]]&6 ]<8]]><]/?c+=c c d'7d cdd&;d$d$*1d*<=d6+#d<+dB>d!d&;d*!d0 d3dd$d.6d*$d d9:d d"2d e:e,*e9:ee*ee:ll*l#k!l"!1l(#h*!j!l2(0l8/lL4&lR lX l^ ld%5ljlp=?lv=l|/>ll:m #m m#;m m m$% m*m0 m6%3m< mB!1mH>< mT mZm`=mfmN ml#mr m|->m m3:m!m(0m.mm.4m !m*2mm4*m m>m m+=m lF &st&4t tt(t+3t t,t2t8#t>$tDtJ(tPtV()t\tb3th tn#tttz>+4uD uJ)#uPuV)9t>u$u> |D |J 5|P+$|V.|\$|b,;|h|n;*|t|z?>| |)1| |+"| |"+|"|"3||=8||5=|&|.5| |3)| |4,||,/| |><} } 5'}}%}}"'}(}./-}4}:+=}@ }F 0}L }R-;}X }^ 4=}j}p'7}v }|}}&6} }:<} }-;} })#} *}1}+;qh3;|&)#}d(0}=>} }}%}%-tnreG mae!$V V*V V*9V"V(6&,5V4,*V:2+V@*VF,.VL&#VR*1VX*!V^*2Vd#&Vj#,Vp&$Vv,%V|#V+=V V/>VV%3V$V$*V$V*VV-,VV'7VV%5VV-VV"VW &W  W&6WW)"W$W*->W-5W0 W6.,V"=W@WF:^^ ;^^+^#^$^*>< ^6->^<^B;^H^N+^T\^0"^Z*^c+2+^r3;^x<8 ^+;^ ^~+^><^^->^ ^#^ ^.6^ ^^ ^l ^%5^^^%+"^%4^^__  _3_ %_&%3_,_8+_>_D_J_ _2 _P3;_V _d_j"2"_p_v*_|!_(0_; _#4_ ___ *_(_)9_(1_98_#_%_ _%5__><_ *3ef$f f =f f3;f f$->f*e f0f6#;fF fL;8fRfX%f^fd4;fj fp>f f$f f@ f$*f c!d$f:f'7f:f f$6f$f6=g gg g:gg.6g$:< g04;g6 g<.%gBgH+gN gT=gZ g`%:gf gl->grgx$g~*2 g$gg->g g*g g$*gg%g g'&g g+gg*1gg%:g l m m m$m#4 n<=n1n">n@nF4*nL nRnXn^=nd#nj#npnv$n|3;1n$*n1!n(0n$n$+n! n+=n n n$n$n n:nn->nf$g!n n n*9n o\#3o iSicilnaD feneec;o*,o0o6*ov$v*>$*wJwP5#wVw\#3wb#wh?>wnwt>?~h ~n% ~z'~!~!(~!~ ~ ~-~*~ ~~= ~9:~/7~ ~6/~6~6-~62~/.~6> -&- .5"2"(54."#443:#8@"=F5#L-+R#X3:^8*d+j*p:1v|&.1:;&# !>? .-    W+=X&X#:;X%&X4+X4X$4=X*& X0+,X6X<;X X,3XX<;X X,XX:Xv*3X"2XX*XY$Y Y *9Y Y+$5.Y$5Y Y*9Y Y1:Y1*Y);Y YY Y>_31!`-6`-`3;` ! `&->`, `2%`8`> `D`J `P- `\3+`b$`h<8`n`t+;`z+`><` `%``->` ` `` `+ `` `'` `'.``.<` `<;` `>a a a"%a(->a. a4a: a@ aF `V`aaL%5aR%5^c#adaj*ap]^! ` az+=a a a6= a.6a a->a 6=a/> a.6a%$aa%5a aa ag-gh hh#-hh"h( h.8h4 h::h@ hF!&hLhR!hXh^*1hd hj<=hph hv>hh&;h*#h!(h&6#h->h.6'h'/h'h#*hh#h/&hh+=h i%ii-i i ->i&i,%5i2 *i83:i>*iD98iJ3:iV98i\ib*4ih*#in+it iz%5ii4>iiP iii&ii'i i'7ii%5ii4>i#iii&iop"p=>p=p=8p p p&p,3p2p8=p> pD.5pJ.pP#pV p\"pbph.'pnpt'pzp:qq>98qDqJqP qV)#q\1qb-=qn>x@ xF*xLxR#xX =9xd xj xp xv'x| x =x*(x=9x?>x#*x =x;*:2x<5x2:x5=x:(x=>x=x 9x x#x)9x*(xy$*yyyy" y(y.=y4 y:y@ yFyL (yR=9yX=y^#yd*(x y  yjyp'xy~3y x^ y>!%$ * 4#,-$% >?,-.>"$(.4-4 :%@!"F# R$-X ^ ?L <  $$! !#!*/ ! #; /-"(#.4;   9:1*"=*!".( .4 :>@4*LR>;X ^>dj+=pv|F$# />? 6= $  / -& $,* 06 < BH,:N T 0Z"`%f l%5r x><~ )# ;8""+" "*(:*1*!*2- % $*$!* 006><< B-#H N4;T Z+=`&6 l)"r x><~"=,:-;-&/7& -#+= f   :8 .4&6  4#$3)& ,+$2"8:<> D,:JP$&V \$b%h&;n&t'/z*;%% '/4;,:,:  ,: *2&,: "4;3)2!&=<,! $"2/?8"B*2H!N$T` $lr;x &;f ~ 8)0)#*2Z#;&/ & %- $3;#), 2"8"4>"D> ><6= &6(0.4:!$4#  o/7&t3*983*9LFR#-X#b#3h%t&z&6:,"53-4$-4#$ (0*# 5< (0+"39(.4>4/7@(0FL*2RX.6^d39j5<v*2|-339/7.6p4>#4  =?#+%(04> *2 :%5" 0+;6+<+=BH$N T#3ZiNzmvoci heDefsne=>?z:?66*;= $, /% +=* #  !&",/-2 8%>+= DN X&6^ d:< =- .6 =? #5#4= :<-$)#*0&6 <&6BH:< !*2!1;*1-#!&8 52"(.4:2@$FL&;RX.^!d8jp v| ( 0 *,?>, ,:.4 4#% %5 4*!% '7 #;$#*.>06#,<#B%-H N&T Z>?`f-5l r&6x ~><,:0" %<=$ /-/')0)-+'/- =>7.% %  % %" (,.4)1:@:FL%RX*^d%4j p/7v|4#><6=78 # ##%  8?5>?/ %=%%4 %,/$,:* '0+6$<%5B H+;N T Z`!f lr$x"~  8 4.' "2 )1!(.4&(0 $*&4;4%/%%&4*%*)#4)# :@4=F3;V,:\P b&hr&6x##:!"2-!*-=*-  !1$-;;8 ,5,,: "() 4:: .@FP#V#$\"b$<*1*!,: %4$" (4>. !4#3: D "h*9JeCtnreC uotnreD fenees"2tz ;!1;? ; #;8 -44<443 4&3;"(.4- %:2-; "6=;*"*" -.4= - #-v.' (%6<'B pH-;N,=/%^=3d%4j")p89v3-|9: !#-#;)).4*./))2)!  )# /- %  &!!(!$&6* 06<=* H/V \#bh/-n t(0B$z=+= :< -;'(19813; ' -6 - +;.'-= $.*'0*6 <B!H'7NT>>< #$&,%6<%5B 46N T).Z'`64f/l.>rx4<~/(19"9:(/>?   %*/<;%*3":1!&./7 ><  6=&.,28=6>DJ-P6=V\,bh;3n tz ! =6&6>-$ = !8;  (*"=6 &-'"(&." 4'/:@-4FL;=R X3;^ d;8jp4;v|,:.4 &. (0 /7 >< 65 3;*,'/,$;8 #  %:""($.;4,:#@);F$L$ -;$<  :X j6$"<=><;<$);3: $ &"=,#<$B&;HN"T"6$ Z"2`jp   $ v*| 4= &*, /?//= '/ 9:-5= #3 *:<$%:*0$#6<#;B#H#3N; Z%`f-lr"=x ~%:*3  T**9$ n o->lAkeihens'D fenees,#>< =#-!""(.#4*"'@3&-&D/7J&T->Z `#3f5,. v.5|&&/./7 .43; 4>&+= ,:+; <=>< -4-&4=& -> #3p(*9.->>3;DJ,:PV/7\b*9hn"2tz#38\$uYoglsvaD fenees><% # +=->%5+ # $ +=" (:<.3;:'@ F:* #-<=-464(05=*$  02 :9&,-221898> D,+J1P-#V \><+;z4=$* %.+$* 4=+4 # DJPV!\!(b!h#-nt(0z 9:-#:< %: % %5 & 4; &6 H (0)" $,4+"(-4. 4,:@?>FL;8RX*2^d+;jp>**++;*434)1/73+ ;=><+3 6/ 3  ; &*,!2 08 >/=D J6=:P , V4#` j$6 z6=;$$*$&&6.'"= '/&:< 3+ ,:'/ "(&.3+>,:D-+ P'/V J \6=b 8l+#r% %5 ,: &  |#; #&698 !1"+ :4; >< # &!$*86=2$>D+=,&6N ~  T:"= 4=%5.6p/7^*!, /7 &6*9:#,#:<* , -# = =;3="( .3,4 :@!F*LR 0X^-dj#p&4| &4! =##-!",#& v ><4=(0  ,5,%$,)*0);6<*BH"N%'T5,Z'`-6f-&l4=r :! &x->~ *9,:%%5"2 #3$aCorK-na neDefsne.6*9 #3% ><$ *+=0 6->< B %5H X^dj p v | "9: ;?;* ,"4"-:< ,:# *9 /74;$->*0"=6R <#3B \ o  cW  L/7 #"==~->   &0 9 "(:3&-5&><98(3,2; : &, 2><8>:8D J"P V#*\98l); x:8~ 0+ +"& &    =><= 3 $ %4#4?>9="( 3@ F<8LX^?>dj3p Rv, !9#4 , /73*#4 *8 8$,:$4"  &!,$428->>$4JP#V \   +b)h n"t zD"") "/7 >< 4=&;8,:$4"6= " ;= $><* 04=6 <H$N#Z `)"f l 0r!;8~ 4"-6-&# -6-&/7 # " $-$-5") ".6%/$  %/6<,3BH/N-Z`,4f l'7rx%,~„,3ŠT *  ¦><¬²);¸¾4= !1,4-3;–/* ;0 -$" $"4;$"*#0 6 >< += -;&-&,/72&8/7D J"4P"V);:8>4=\b->p |ɜ v% ʊʐ )ʖʜ);ʢ%ʨ*1ʮ*$ʴ><ʺ$%, %"4=,4 ##-#'7&2),24*8>)"DJ"=PV%\b$hn$,tz-ˀˆ-;˒-&˘"=˞$*˪˰"=˶&˼3%$#&ˤ ,4ˌ$4 ".6 "$( .4 :'7/7@F !*b$hn:\*4x~*҈Ҏ6=Ҕ Қ'7V4>ҠҦ6=P-5ҰҶ-5p4>Ц.6,->&6=<= ;4=$43- $4-> 2*9 )3:4 : ;@F98L R$4X^*9dj4>v=|ӂӈ:ӎӔ*9Ӟ Ӥ$4ӪӰ.p-5ӶӼ*!*9 8 "(9!.  )1&29,2 8 ;>9D#JP-> "V\%f l"2rx"2״->%:~ ڄ *1ڜ*!ڢ#ڨ!ڮ#-ڴ#ں2*+3 )1*2*!(0<- ><4= 2;&!, ><8>6=DJ"P V> , 989=,:3,|?><8#4 8;:8@,:=L,"R$X^d"j"+p")v:|!< <;)0#0#F:8&  ")"*:= *4); &": ""+":8 "-5. r&4#*: %,NT#Z #f l+"rx;=~ `.%%,#  %,&)"%,  -= +"  -&/7$+"* 0-< B2+H-&#TN Z:<`j# v| ;8 +"p" -6-&;8 #,1 -6- )&4=#4<-/=#  &-6, -&2)"8B.4NT#;Z#`#,flrx'~ '7 4*4%-&-6-4=#;8( ,:8   3:  * &#, 2)"82+D"J+"P V98\ b(:h:8 t(:z&nĀ4;Ć Đ><Ė Ĝ*1Ģ>*Ĩ"=Įĸ4=<);f3:!1"ľ"><>< >< +=  3:4=+=);" (#-@#F*3L*R:8X"#d jp v=|ł +=ŎŔ,4Ś Š'ŦŬ,4ň3ŲŸ:8 ^3:" $4 % *:8"",4|->,%8 ;>2 98J P#*V#\#;b#h,4nt*1z*$̀"̆ ̌'̒$̘ "");->2%:D:̞ ;̤-5̪&6̰ ̶ 0>< 4>,4 *1>< 4>&,")18">$,DJ#P V<-\b>̀*͆*#4>͚#͠#,ͦͬ!(Ͳ#͸,:;*9(0 #!2!,:$4" <= ><$6=*0 );"$4 6=  .6 2("!(!1::@*9F L")R"X"39jp'd%v$| $4Ռ"Ւ4>՞դ*9ժհ"=ն ռ$4"$"->39(9. 04)1^:Ն2;՘-5 , :+3&"><( .+3z-4=4:98 N3-T#Z#*`#f2;l r*3x*~!1܄܊3:ܐ ܖ(0ܜܢ><ܨ ܮ6=ܴܺ.6" #3,42.6\$4H+3 *9#3->   S  $4#3""2(. <=BH-4N-T>ݢ ݨ#3ݮݴ!$-$ &&64>". .4 +$$ *+"0%< +"H BN<;?>T-=^%d#%| )$ %4 );  "$%&6 j <=<#*#;:##*  +"%5$ # *+"%5<;03; ; > :;:8T)"##H f>< 4>,:->#*#.++; '+()"="&6& $&,/72 8 ,%D J P V*\ b-6h-&n%,tz><4=3->1**#-6# -&:8# )#  :<4=;8H)"3- -6 ,:"  &,:, 2)( >-6D-#J:<->"="$->"=" 5<*198"1($. 4$-: @-5F$L *R X"Ƙ:8); ;^d#v". ǂLj><ǎ ǔ->ǚ 4<Ǧ Ǭ:8Dz Ǹ->Ǿ-6-; Ǡ6=9;#+=;=;- *9!-$*#0 6><<B*9͐$4->HN  ;b"h(0tz:8΀Ά1:ΌΒ)1ΘΞ"(ΤΪ(9ΰ"ζ><μ(:*1*$3-,4$*93- 33<3$<;"(1:.$4)1:@"39FL>b*9n l6=zπ;ό$ϒ Ϙ Ϟ Ϥ 0Ϫϰ#϶ϼ%-,:*9$4" #  "2 $2 ;8&,%:28  DJ2;> ;PV><` f6=l r.6x~-3ք-&֊/7֐֖(0֜&֢+#)3ִֺ)3֮(0 >< 39 6=&)#;<##;# #-##,$,4*039֨.6(06<>tz%׀׆%5׌ג->J$4ט#מ#ר ׮><׺6= -3 39 -3 -; "=$4  &1:, 2++">D:1J P#3V \4>b!h-;n%t$z ހ%5ކ ތ"=ޒ!ޘ6>ޤ6/ު39ް޶'-޼>,4 "$4ޞ(0!( .1:< B#,:N T4>Z$`$*f$l$r x~ ߄=ߊߐ$,ߖߜ#;ߢ#,#ߨ#3߲ ߸*9߾ --> 3;%:" -5 '7><" #*2#8)0>)D'J P)"V\ 3;h n+"tz><))" +">< 3;  ,"## +" :8 (   ;8 #* #$ ;* 4+": @,:F P'7b:> "=(:=%5 *1*x$4);#4=;8-6 -4 -&!"-&#",: &, =D-J$P;8V \"b h,:n t$!1 +"4=6/7z#$8#-#*%:1*$%"$,:$;=(0$ >< #" (!89481:9$@1F$"L$R3-X^*d j#p v'|  >< =# 4=.: "x&   T,4B$4.6&-#% *4-5"&(4>.)!:!@!F-LR-;X ^ dj*4pv4>|><ȈȎ4=ȔȚ->Ƞ Ȧ. Ȭ4Ȃ Ȳ %ȸ* ;:);:8# ;)$4>$*"0$6#< B ;NT*1Z*$`"f$l4=rx->~Ʉ#Ɋ ɐ"->);H:8ɖ$* ɮ"3ɴɺ;;)"44= 3- *9.6φ-52;eBonineBkn oaGbmtieBkn oaGbmti &6@ F5=L R,:X^4>dj'v|'7ЂЈ&6ЎД%4КР!ио -5 )198982; %54>-> 6= & :8284<>&D%:J P *1\*b%hn:8t&z":8цьђј 4ѤѪ-Ѱ Ѷ$Ѽ%:р:ў/72;V4<<"& -#-6-&%5 #- $"2*2*&0"2><:@6=JP><\ b4=hn*9t z"2ـن  7ْ&٘&/ٞ&٤7.٪ٰ,4ٶټ/7.'' "2T%:ظ.6V,4ٌ:%%5(0 +3.4$ *4*0#6$4<#3 B !"+X!^"dj"2pv39|3!3:!6=+;+$+3 #-$-> 4> $4 #3& *9"  "2&6=$ *$4R#3ڒ"2-><*2ݺ)18!1H,4*9L(0R.6&60 ~ y  z { | } HPXp'qrX XXpn'qrX X #3CP(X,J2P$CX CXC ' - )9IXpX'qr(PA@Xrd""Lrh""Trdh""\fptrap#sysent#dtrap1"%nosys"%nullsys"%rexit"+Bfork".read"1write"1open"2close"4wait"-creat"3link"6unlink"?exec"%chdir"@gtime"=mknod"7,chmod"ADchown"Asbreak"/stat"9seek"4getpid"?Nsmount":sumount"`getuid">stime">fstat"8smdate"B stty"Fgtty"nice"?sslep"7sync"?vkill"C|getswit"=dup":npipe"times"D.profil"PA@DX P&&PA@Dюp4p(ЇX@4PA@P@4&PA@P@8&PA@P@<$PA юp(p(ЇX@XPA@GC0DXX ` #8@mC$X(PX PX@Aюp(p(ЇX($PA@X C0( 0@ 0P PA@CPAt$PA@юp(p(Ї&4B X@DP P@D"$X #5&ʰ"P@ʨюp(p(ЇX( & PA@~!"  PA@~!" PA@ 0$P@UPA@Q B0D@mB0PX@8 PA@P C04't$P$PPA(&tC't$P$PPA &tюp(p,Ї X,X0X4C0Jð#:PPA@IðC0*PPA@IX `@!6@m@mB0zX4#6PA@OxPA@wA@KZC0T  PX@XP PPA@I@mC0"X$P@ ' PA@Mю p,p(ЇX@XPA@G C0X@X$P@PA@Hюp(p0ЇX@XPA@G C0 ...-.(stdio.h? 0 PA@ $PA@PA@~!"$ ,PA@юp(p,Ї X,$PA@ ,B0$ 0!4$C$ PPA@C$PA@VPA@~Bɰ!8 ,' ,C T $B0n @\C0, . !8V#"'C / C0ɰC0C4 @C0( @ #6$T $C0 @\#4ӻ@'ҽ&T#CPPV&UCP P&A@F"$#ю p,p(ЇX,X(X$ !5#2$ B08#5B0*!5$P#$PPA@HPACX #8@mCX@8C 0X@4 P X@4P!7XPC X@4P $P #7X #%P CPX QX PPA@CHXQXXPPA@CB BX@tX P XP юp0p(Ї$P@UPA@Q C0 !@mCX `@!7A@JC0 X@8P@$P@UPA@Q #;@mPA@M@mB0PX@XYC0X@PA@M@mC PA@Qr &   PA@L@@B` A`4#A`($PA`A`A` =A`A`H&Ȱt@)C^!PACC0A!Z!# PPA@F !8 #5B0*PA@ PPA@F!6 ,& ,C0 0B0PPAPA~юp(p,Ї X0X,!7 T $C0 B0($T $C0P PA - b_flags&B_ERROR) if ((u.u_error = bp->b_error)==0) u.u_error = EIO; } x interval (.04 sec) stclk.b dc x'e000' disarm pic interrupts and start sytim dac y'0' accumulated system time utime dac y'0' user time itime dac y'0' idle time endc end  #'PAPPA@ NX@X(P &PA@ NP &PA@ NX@PX@P(CN CP@4AH#3C' !)!X@X@XP@4A@+`юp(p(Ї$@m@P@$P@dPA@a0 B0*@m#4$CPA@Z !4$CPPA@RB0`T B0@n@pB0PA@X$P@$P@@P@xP@|$@lPA@fX@tX''x$P $PP$PA@]&x$P@x P@|$@lPA@fPA@V@ml..i.dsk.4mem.4mt.4pals.4l..h.archive.5core.5a.out.5fs.5ttys.5utmp.5l..g.boot.8crash.8attach.8detach.8mkboot.8mkdir doc mkdir doc/cdoc mkdir doc/cman mkdir doc/ctut mkdir doc/man mkdir doc/man/man1 mkdir doc/man/man2 mkdir doc/man/man4 mkdir doc/man/man5 mkdir doc/man/man8 mkdir source mkdir source/as mkdir source/boot mkdir source/c mkdir source/chicago mkdir source/cmds mkdir source/cref mkdir source/cref/index mkdir source/cref/src mkdir source/cref/tab mkdir source/etc mkdir source/fort mkdir source/liba mkdir source/libc mkdir source/lpd mkdir source/lpd_melb mkdir source/m6 mkdir source/ratfor mkdir source/ratfor/lib mkdir source/ratfor/ratinc mkdir source/sno mkdir source/stdio mkdir source/stdio/pdp11 mkdir source/stdio/src mkdir source/troff mkdir source/troff/cmds mkdir source/troff/doc mkdir source/troff/eqn mkdir source/troff/fonts mkdir source/troff/macros mkdir source/troff/neqn mkdir source/troff/programs mkdir source/troff/tbl mkdir source/troff/terms mkdir source/troff/tests mkdir source/wgong mkdir source/yacc tp mx find doc -type d -a -exec chmod 775 {} ";" find source -type d -a -exec chmod 775 {} ";" .ll 80 .de ph .s1 .ti 0 .ul .. .th DDT I .sh NAME ddt - dynamic C debugger .sh SYNOPSIS ddt [a.out [core [-]]] .sh DESCRIPTION .ul ddt is a debugger for use primarily with C programs. It is useful for both post-mortem and interactive debugging. An important feature of ddt is that even in the interactive case no advance planning is necessary to use it; in particular it is not necessary to compile or load the program in any special way nor to include any special routines in the object file. The first argument is the object program (containing a symbol table); if not given, "a.out" is used. If only one argument is given, it is assumed to be an object program. The second argument is a core-image file; if not given, "core" is used. The core file need not be present. The optional third argument specifies that the file being debugged is not a core image. This feature is used most frequently in examining the memory file /dev/mem. In order to set breakpoints and execute, the namelist (a.out) file must be present and can not be a shared text program. Commands to ddt have the following form: .ce 1 [
[,repetition]][] If no address is given, the last displayed address is used (this value is accessible by typing the special symbol "."). An address expression may optionally be followed by a comma and a number, in which case the command applies to the appropriate number of successive addresses. .ph Address Expression An address expression is an arithmetic combination of operands and operators. Operands may be: .nf .ta 5 20 e.g. main symbol name -32 decimal number 0177 octal number 0x3e8 hexadecimal number 'a ASCII character "xy two ASCII characters .fi The following operators are recognized: .ta 5 20 .nf + addition blank addition - subtraction * multiplication \\ division % mod (remainder) | OR & AND @ indirection (postfix operator) [] array subscription (postfix operator) .fi Evaluation proceeds left-to-right. The construction name[expression] assumes that name is a pointer to an integer and is equivalent to the contents of the named cell plus four times the expression. .ne 24 .ph Commands The command strings are .in +11 .ta 11 .ti -11 / display the contents of the addressed memory locations according to the display mode (default i). .ti -11 = evaluate and display the address expression according to the display mode (default o). .ti -11 ! store the address expression (1 word) into the last specified memory location, which must be on a fullword boundary. .ti -11 ! if no address expression preceeds the "!", the remainder of the line after the "!" is sent to UNIX to be interpreted as a command. .ti -11 $ print a stack trace of the terminated program. The calls are listed in reverse order; the actual arguments to each routine are given in octal. .ti -11 ? display fault type. .ti -11 display the next memory location according to the current display mode. .ti -11 ^ display the previous memory location according to the current display mode. .ti -11 > Replace dot with the effective address of last instruction which was displayed (follow the path). .ti -11 ;f exit from ddt. .ti -11 ;= search equal. .ti -11 ;# search not equal. .ti -11 ;b set an execution breakpoint. .ti -11 ;c clear an execution breakpoint. If no address is given, all breakpoints are cleared. .ti -11 ;d display the location of all execution breakpoints. .ti -11 ;g begin execution of the symbolic file at location 0. This command may be optionally followed by a list of character string arguments to the program. .ti -11 ;p continue execution after a breakpoint. .ig .ti -11 ;s execute one instruction and break. .ti -11 n;s execute n instructions and break. .ti -11 ;. set a temporary breakpoint at the specified address and continue execution. This temporary breakpoint is deleted when the next breakpoint is encountered. .. .ti -11 ;r display all registers in octal and as symbols. .ti -11 ;e display the floating point registers. .in -11 .ne 18 .ph Display Mode The mode characters are: .ta 5 15 .nf o octal x hexadecimal d decimal l unsigned decimal f floating point e double precision floating point i symbolic instruction & address b byte in octal ' byte in ASCII " two bytes in ASCII s string in ASCII .fi There are two display modes: one for display contents (/) and one for evaluate (=). When ddt is invoked, the default mode for display contents is i (instruction) and the default mode for evaluate is octal (o). Whenever an explicit display mode is given, the default mode is set to the given mode and used thereafter until another mode is given. .ph Special Symbols Ddt recognizes a number of special symbols. The values of these special symbols may be displayed, modified, and used in expressions. .ta 12 40 .nf Name Meaning Default value . last address displayed :r0 user register 0 :r1 user register 1 :r2 user register 2 ... :re user register 14 :rf user register 15 :sp user stack pointer :pc user program counter :ps user processor status :m search mask 0xffffffff :8 lower search limit 0 :9 upper search limit 0x8000 :l lowest address to display as a symbol 0x100 :q last value typed to user :a 0 only C symbols 1 1 C and assembler symbols :r maximum symbol offset 0x1000 to display symbolically :f current function for last function called accessing local variables :sl lowest address on stack 0xe0000 .fi .ph Symbols .ig All C symbols begin with an _. As long as the special symbol :a contains a value of zero (default), ddt prepends an _ to all symbols, thus eliminating the requirement for the user to type _. If :a is set to a nonzero value, indicating that the program contains symbols which did not pass through the C compiler (such as assembler symbols), the _ before each C symbol will be displayed by ddt and must be typed by the user when specifying a symbol name. .. Variables local to a function (automatic, static, and arguments) are accessible by writing the function name followed by a colon ":" followed by the local variable name (ie. main:argc). The notion of the current function exists and is addressable as the special symbol ":f". The value of :f is set to the last function to be invoked whenever a breakpoint is encountered. Variables local to the current function are accessible by simply writing the variable name. The current function can be changed by modifying :f (ie xyz!:f sets the current function to xyz which must be active). .ti 0 Examples (each command is terminated by a ): .in +15 .ta 15 24 .ti -15 t1/ display the contents of t1 in the default display mode .ti -15 t1= display the address of t1 in the default evaluate display mode .ti -15 t1+40/d display the contents of t1+40 (decimal) in decimal .ti -15 p@/o displays in octal the contents of the word pointed to by p .ti -15 :sp=o display the contents of the users sp (r7) in octal .ti -15 0377!:r2 set the value of the users r2 to 0377 octal .ti -15 string/s display the contents of string as ASCII characters .ti -15 i1/o this is equivalent to fun1:i1/o if the current function (:f) is fun1 and i1 is a local variable in fun1 .ti -15 xyz+012 023147 ddt displays the cell value .ti -15 xyz+012 023147 0272! user changes xyz+012 to octal 272 .ad .ti -15 Searches: .ti -15 0100!:8 set lower search limit to 100 octal .ti -15 1000!:9 set upper search limit to 1000 decimal .ti -15 0177400!:m set search mask to third byte in word .ti -15 023000;= search between 100 octal and 1000 decimal and prints the address and contents of each word if the value of that word when logically ANDed with octal 177400 is equal to octal 23000. A search not equal also searches between the limits in :8 and :9, ANDs each word with the mask in :m and displays each word for which the resulting value does not equal the given value. .in -15 .ph Execution and Breakpoints The general format of the set breakpoint command is: .ce
;b[] which causes a breakpoint to be installed at location
. When a conditional breakpoint is encountered during the course of execution, the conditional expression is evaluated. If the value of the conditional expression is true (non-zero), the execution break occurs. If the value is false the execution break does not occur, and execution continues in the normal fashion. A null conditional expression is always evaluated as true. The format of the conditional expression is: .nf [ ...] .fi A conditional expression is thus composed of any number of relational operators separated by the boolean operator && (for AND) or || (for OR). Evaluation is strictly left to right (no parentheses). A relational expression is an address expression or two address expressions separated by one of the relational operators: ==,!=,<,<=,>,>=. If an address expression contains a symbol name then the value of the address expression is taken to be the contents of the memory cell addressed by the expression. If an address expression contains no symbol name then the expression is taken literally (ie. the value of i1+4 is the contents of the memory cell whose address is i1+4 while the value of 100+4 is 104). The expression 104@ has the value of the contents of memory cell 104. CAUTION: blanks are meaningful to ddt and are equivalent to the addition (+) operator. The command ;d displays each active breakpoint along with any conditional expression associated with each. Some valid conditional expressions are: .nf xx i1>=0100 fun1:arg1!=1&&ii<12 j1||j2 0177203@==0177777 .fi Upon encountering a breakpoint, ddt displays the instruction which will be executed when execution continues and ddt then goes into the command mode. .in +15 .ti -15 fun1;b sets a breakpoint at the entry point of function fun1 .ti -15 ;g abc filea starts execution of the symbolic(a.out) file at location 0 passing to it the arguments abc and filea. .ig .ti -15 ;s execute the next instruction and break .ti -15 5;s execute the next 5 instructions and break .ti -15 fun1;. set a temporary breakpoint at fun1 and continue execution .. .ti -15 xxx;c clear the breakpoint at location xxx .ti -15 ;c clear all breakpoints .in -15 .sh DIAGNOSTICS Self-explanatory (?) diagnostics are given for illegal or unrecognized commands. .sh "SEE ALSO" cc(I), C Reference Manual .sh BUGS The $ (stack trace) command always prints at least 2 arguments for every function, even those with fewer than 2 actual arguments. Local function symbols (auto, static, and register) are not accessible in the current Interdata implementation -- only external symbols. Ddt can not be used interactively with FORTRAN (or ratfor) programs, since the illegal supervisor calls normally handled by the `OS/MT SVC Emulator' are intercepted by ddt. When proceeding from a breakpoint ddt removes the breakpoint temporarily, and replaces it only when a different breakpoint is encountered. This means any loop being debugged interactively should contain at least two breakpoints. Occasionally ddt may leave breakpoints set in the a.out file after it exits, making it impossible to execute the program. It is advisable to make a copy of valuable programs before debugging them interactively. .dt .th AS I .sh NAME as - UNIX Interdata assembler .sh SYNOPSIS as [ -u ] [ -m ] [ -sN ] [ -o object-file ] file [ ... ] .sh DESCRIPTION Assembles the Interdata CAL source code in the named file(s), leaving the object-code output on .it a.out. If multiple filenames are given, only the last may have an END statement; they are concatenated together and assembled as one program. .lp +8 4 -u Uppercase characters (other than those within quoted strings) are to be translated to lowercase. .ti -4 -m Multiple redefinitions by EQU statements are to be considered legal (mainly for the benefit of the stupid Interdata Fortran V compiler). .ti -4 -o Leave the object-code output on the file named by the next argument, instead of "a.out". .ti -4 -sN Specifies the extent of 'SQUEZ' optimization performed. .nf -s0 NOSQZ - use longest form of all instructions -s1 NORX3 - squeeze RX3 instructions to RX2 or RX1 (where possible) -s2 SQUEZ - shorten all possible instructions: RX branches to SF branches RX3 instructions to RX2 or RX1 RI1 instructions to SF or RI2 .fi The default is -s2 (full SQUEZ optimization). .i0 .dt The input format is compatible with 32-bit CAL assembly language, with the following main exceptions: .lp +6 2 - if `-u' is not specified, opcodes must be lowercase, and uppercase and lowercase symbols are distinct (FRED is different from fred) .ti -2 - fields may be separated by tabs and/or blanks .ti -2 - a BSS pseudo-op is available for defining storage in the uninitialized data segment, as well as the text (PURE) and initialized data (IMPUR) segments. There is no ABS segment. .ti -2 - external references and common-block members may be used in assembly expressions .ti -2 - data definitions of type D'', E'' and T'', and externals of type Z() are not implemented .ti -2 - pseudo-ops BATCH, CAL, COPY and TARGT, and symbols ABSTOP, PURETOP and IMPTOP are not implemented .ti -2 - no listings .i0 .dt .ne 28 .sh DIAGNOSTICS .ta 4 .in +4 .nf A: previously-defined absolute symbol required B: short branch out of range C: illegal or missing opcode D: illegal data within COMN, STRUC or BSS E: unexpected input after the END statement G: garbage character I: illegally nested IF, COMN, or STRUC L: missing label M: multiply defined symbol N: syntax error in number O: org to illegal address P: symbol value changed between assembly passes Q: missing quote R: relocatability error S: missing symbol U: undefined symbol V: illegal value (e.g. register field > 15) X: syntax error Z: division by 0 .i0 .dt .fi .sh AUTHOR Richard Miller .br University of Wollongong .th ARCV I .sh NAME arcv - convert old archive files to new format .sh SYNOPSIS arcv file ... .sh DESCRIPTION Converts each file (assumed to be old archive format) to the new format. Each file is rewritten. .sh FILES /tmp/arc# .sh "SEE ALSO" ar(I) .sh DIAGNOSTICS "Bad archive format" - file was not in old archive format. .th BS I .sh NAME bs - backspace-delete filter .sh SYNOPSIS bs .sh DESCRIPTION .it bs copies from standard input to standard output; when an ASCII backspace character is encountered, it and the previous character are deleted (unless the previous character was '\\n'). It is useful after forgetting to change the erase character with .it stty before an edit session. .sh BUGS Maximum line length is 256 characters. .th LD I 8/16/73 .sh NAME ld \*- link editor .sh SYNOPSIS .bd ld [ .bd \*-sulxrodn ] [ output ] name ... .sh DESCRIPTION .it Ld combines several object programs into one; resolves external references; and searches libraries. In the simplest case the names of several object programs are given, and .it ld combines them, producing an object module which can be either executed or become the input for a further .it ld run. (In the latter case, the .bd \*-r option must be given to preserve the relocation bits.) The output of .it ld is left on .bd a.out. This file is made executable only if no errors occurred during the load. .s3 The argument routines are concatenated in the order specified. The entry point of the output is the beginning of the first routine. .s3 If any argument is a library, it is searched exactly once at the point it is encountered in the argument list. Only those routines defining an unresolved external reference are loaded. If a routine from a library references another routine in the library, the referenced routine must appear after the referencing routine in the library. Thus the order of programs within libraries is important. .s3 .it Ld understands several flag arguments which are written preceded by a `\*-'. Except for \fB\*-l\fR, they should appear before the file names. .s3 .lp +4 4 \fB\*-s\fR `squash' the output, that is, remove the symbol table and relocation bits to save space (but impair the usefulness of the debugger). This information can also be removed by .it strip. .s3 .lp +4 4 \fB\*-u\fR take the following argument as a symbol and enter it as undefined in the symbol table. This is useful for loading wholly from a library, since initially the symbol table is empty and an unresolved reference is needed to force the loading of the first routine. .s3 .lp +4 4 \fB\*-l\fR This option is an abbreviation for a library name. \fB\*-l\fR alone stands for `/lib/liba.a', which is the standard system library for assembly language programs. \fB\*-l\fIx\fR stands for `/lib/lib\fIx\fR.a' where \fIx\fR is any sequence of characters. A library is searched when its name is encountered, so the placement of a \fB\*-l\fR is significant. .s3 .lp +4 4 \fB\*-x\fR do not preserve local (non-extern) symbols in the output symbol table; only enter external symbols. This option saves some space in the output file. .s3 .lp +4 4 \fB\*-X\fR Save local symbols except for those whose names begin with `L'. This option is used by .it cc to discard internally generated labels while retaining symbols local to routines. .s3 .lp +4 4 \fB\*-r\fR generate relocation bits in the output file so that it can be the subject of another .it ld run. This flag also prevents final definitions from being given to common symbols, and suppresses the `undefined symbol' diagnostics. .s3 .lp +4 4 \fB\*-o\fR the executable output is placed on the file .it output instead of .it a.out. .s3 .lp +4 4 \fB\*-d\fR force definition of common storage even if the .bd \*-r flag is present. .s3 .lp +4 4 \fB\*-n\fR Arrange that when the output file is executed, the text portion will be read-only and shared among all users executing the file. This involves moving the data areas up the the first possible 64k word boundary following the end of the text. .i0 .dt .sh FILES /lib/lib?.a libraries .br a.out output file .sh "SEE ALSO" as (I), ar (I) .sh BUGS ЇC"X Y(!9X,PPA$Cюp(p(ЇX,CHX(  #5X,  dC  #d  !6PA@юp(p(ЇX@t C02 C0A0 !4$CX@h!3 #$#юp(p(ЇX@tX C0RCBX Y B0.PA@d$ A@` C0A!:C$CA@+`юp(p(ЇX@t$ X@hC0$@m C0C0#7$P@hX@X$X@X@C0$@#3$#$#юp(p(Ї%#юp(p(ЇX@C6X@P@CD$PX@PA@ NBX@PX@PA@ NC $PX@PA@ NBX@PX@PA@ NCX@!hB*$CX@8Z@ #6&CC`X@$ B0&X@P@X@XP@X@P C@X@X@t$C.A@+`%P@C' ) X@$#юp(p(ЇX@tX,BrA@B0$PA@!X(P $ X, $PA@!@C0$@@PAnAfA@B0DC4$PA@!X(P $ X, $PA@!A"PA@!# @XPA@!юp(p(ЇX(Ȱ2X  !5PA$' ;юp(p(ЇX($P $ ##Y@#@&@@C0" B0$@@PAZюp(p(ЇX(ӽɰ#% # d ##Y@#(@&@юp(p,Ї C$@&@P@PA$PA@!%C0 B0 .th CC I .sh NAME cc \*- C compiler .sh SYNOPSIS cc [-c] [-p] [-o out] [-Ddef] [-Udef] [-Ifile] [-S] [-P] [-m] file ... .sh DESCRIPTION .it cc is the UNIX C compiler. It accepts three types of arguments: .s3 Arguments whose names end with `.c' or `.s' are taken to be C or assembly-language source programs; they are compiled, and each object program is left on the file whose name is that of the source with `.o' substituted for `.c'. The `.o' file is normally deleted, however, if a single C program is compiled and loaded all at one go. .s3 The following flags are interpreted by .it cc. See .it "ld (I)" for load-time flags. .s3 .lp +6 5 \fB\*-c\fR Suppress the loading phase of the compilation, and force an object file to be produced even if only one program is compiled. .s3 .lp +6 5 \fB\*-p\fR Arrange for the compiler to produce code which counts the number of times each routine is called; also, if loading takes place, replace the standard startup routine by one which automatically calls the .it monitor subroutine (III) at the start and arranges to write out a .it mon.out file at normal termination of execution of the object program. An execution profile can then be generated by use of .it prof (I). .s3 .lp +6 5 \fB\*-m\fR Allow multiple definitions of \fIextern\fR variables in different files; for compatibility with earlier versions of the PDP-11 C compiler. .s3 .lp +6 5 \fB\*-o\fR The executable output is placed in .it out instead of .it a.out. .s3 .lp +6 5 \fB\*-D\fR Makes .it def defined to the preprocessor. .s3 .lp +6 5 \fB\*-U\fR Makes .it def undefined to the preprocessor. .s3 .lp +6 5 \fB\*-I\fR Search the directory .it dir for #include files. .s3 .lp +6 5 \fB\*-S\fR Compile the named C programs, and leave the assembler-language output on corresponding files suffixed `.s'. .s3 .lp +6 5 \fB\*-P\fR Run only the macro preprocessor on the named C programs, and leave the output on corresponding files suffixed `.i'. .i0 .dt .s3 Other arguments are taken to be either loader flag arguments, or C-compatible object programs, typically produced by an earlier .it cc run, or perhaps libraries of C-compatible routines. These programs, together with the results of any compilations specified, are loaded (in the order given) to produce an executable program with name .bd a.out. .sh FILES file.c input file .br file.s assembler source file .br file.o object file .br a.out loaded output .br /tmp/ctm? temporary .br /lib/cpp preprocessor .br /lib/c[01] compiler .br /lib/crt0.o runtime startoff .br /lib/mcrt0.o runtime startoff for profiling .br /lib/libc.a C library; see section III. .br /lib/liba.a Assembler library used by some routines in libc.a; see Section II. .sh "SEE ALSO" ``Programming in C\(em a tutorial,'' C Reference Manual, monitor (III), prof (I), ddt (I), ld (I). .sh DIAGNOSTICS The diagnostics produced by C itself are intended to be self-explanatory. Occasional messages may be produced by the assembler or loader. Of these, the most mystifying are from the assembler, in particular `M,' which means a multiply-defined external symbol (function or data). .sh BUGS Double precision is unimplemented .it (double is synonymous with .it float). Alignment of data objects is poorly implemented; in particular aggregates .it "(struct, union)" are always aligned on fullword boundaries and rounded to fullword length. There is no .it "unsigned short" type. Structures containing unions or bit fields cannot be initialized correctly. .th RKDUMP I .sh NAME rkdump - convert PDP-11 filesystem image to dump format .sh SYNOPSIS rkdump [fsb] [outfile] file .sh DESCRIPTION .it rkdump reads the named file, which is assumed to be an image of a PDP-11 UNIX filesystem volume, and produces an incremental dump tape on /dev/mt0. The dump tape can then be extracted to an Interdata UNIX filesystem by restor(VIII). It is useful mainly for examining the Bell Labs distribution tape. Dump format and flags are the same as for the .it dump command. .lp +4 4 f Write the dump file to .it outfile instead of tape. .s3 .lp +4 4 s Specify tape size in feet .s3 .lp +4 4 b Specify tape size in blocks .i0 .sh "SEE ALSO" dump(VIII), restor(VIII) .th TC I .sh NAME tc - tape commands .sh SYNOPSIS tc [-N] command [count] .sh DESCRIPTION Position the tape on drive /dev/mtN (default mt0). Commands are: .dt .nf ff Forward Space File bf Back Space File wf Write File Mark fr Forward Space Record br Back Space Record rw Rewind .fi If .it count is specified, the command is repeated .it count times. .th TM I .sh NAME tm - map of records and filemarks on magtape .sh SYNOPSIS tm [-N] [-tN] [-rN] [-e] .sh DESCRIPTION Read the tape on drive /dev/mtN (default mt0) and print a summary of record lengths and tapemarks. Output lines have the form .br .dt L:N .br (N records of length L), or .br tm:N .br (N tapemarks). .lp +6 4 -tN stop after N consecutive tapemarks (default: 2) .s3 .lp +6 4 -rN stop after N records .s3 .lp +6 4 -e continue even if I/O errors occur .i0 .sh AUTHOR R Miller .br University of Wollongong .th AR I .sh NAME ar - archive and library maintainter .sh SYNOPSIS ar [-]key [ posname ] afile [ name ] ... .sh DESCRIPTION .it ar maintains groups of files combined into a single archive file. Its main use is to create and update library files as used by .it ld. It can be used, though, for any similar purpose. .it key is one character from the set `drtmx', optionally concatenated with `vuaib'. .it afile is the archive file. The .it names are constituent files in the archive file. The meanings of the key characters are: .lp +8 6 d delete the named files from the archive .ti -6 r replace the named files in the archive. If the optional character .it u is used with .it r, then only those files with modified dates later than the archive files are replaced. If the optional positioning character .it a (also .it i) is used, then the .it posname argument must be present and specifies a file in the archive after (before for .it i) which new files are inserted. If no names are given, all files present in the archive which are also presnt in the current directory are replaced. If the archive file does not exist, .it r creates it. If the named files are not already in the archive, they are appended. .ti -6 t print a table of contents of the archive file. If no names are given, all files in the archive are tabled. If names are given, only those files are tabled. .ti -6 p prints the named files in the archive to standard output .ti -6 m moves the named files to the end of the archive. If the options .it i or .it b are used, then the .it posname argument must be present and specifies where the files are to be moved. .ti -6 x extracts the named files. If no names are given, all files in the archive are extracted. In neither case does .it x alter the archive file. .ti -6 v verbose option: .it ar gives a file-by-file description of the making of a new archive file from the old archive and the constituent files. When used with .it t, it gives a long listing of all information about the files. .sh FILES /tmp/v# temporary .sh "SEE ALSO" ld(I), archive(V), arcv(I) .th AL I 8/12/77 .sh NAME al - create empty files .sh SYNOPSIS al [-mode] file ... [-mode] file ... .sh DESCRIPTION Creates the specified files, or truncates them to zero length if they already exist. .lp +8 8 mode Octal value of access mode (as in chmod(I)) to be given to following files. .i0 .sh AUTHOR .nf Ross Nealon University of Wollongong .fi lchq *selchq; { register struct selchq *s; register struct selchtab *st; register free; trace(040<<16, "schrequest", selchq); st = &selchtab[n]; /* Make sure request not already on queue */ for (s = st->sc_actf; s; s = s->sq_forw) if (s == selchq) return; (s = selchq)->sq_forw = 0; if (st->sc_actf) { st->sc_actl->sq_forw = s; free = 0; } else { st->sc_actf = s; free = 1; } st->sc_actl = s; if (free) (*s->sq_sstart)(); } /* * Free selch #n for next device */ selchfree(n) { or 12*NCLIST characters */ struct cblock cfree[NCLIST]; /* List head for unused character blocks. */ struct cblock *cfreelist; /* * The routine implementing the gtty system call. * Just call lower level routine and pass back values. */ gtty() { int v[3]; register *up, *vp; vp = v; sgtty(vp); if (u.u_error) return; up = u.u_arg[0]; suword(up, *vp++); suword(++up, *vp++); suword(++up, *vp++); } /* * The routine implementing the stty system call. * Read in values and call lower level. */ st>= 0); wakeup(&tp->t_rawq); tp->t_state =& ~(ASLEEP | SUSPEND); /***/ wakeup(&tp->t_outq); sps = spl(5); while (getc(&tp->t_rawq) >= 0); tp->t_delct = 0; spl(sps); } /* * transfer raw input list to canonical list, * doing erase-kill processing and handling escapes. * It waits until a full line has been typed in cooked mode, * or until any character has been typed in raw mode. */ canon(atp) struct tty *atp; { register char *bp; char *bp1; register struct tty *tp; register int c; tp = atp;.th BEEP I 8/12/77 .sh NAME beep - ring typewriter bell .sh SYNOPSIS beep .sh DESCRIPTION Writes the character '\\007' (BEL) on file descriptor 2. Useful to signal completion of command files. .sh AUTHOR Anonymous .th CV I 8/12/77 .sh NAME cv - number base conversion .sh SYNOPSIS cv -XY value ... .sh DESCRIPTION Arguments are one or more numbers in base X, to be printed in base Y. Each value must fit in a 32-bit word. Possible bases are: 'in +10 .lp +4 4 b Binary .lp +4 4 c Ascii characters .lp +4 4 o Octal .lp +4 4 l Unsigned decimal integer .lp +4 4 d Signed decimal integer .lp +4 4 h Hexadecimal .i0 .in -10 .sh AUTHOR R Miller .br University of Wollongong .th CVO I 8/12/77 .sh NAME cvo - convert Interdata object files to a.out format .sh SYNOPSIS cvo infile outfile .sh DESCRIPTION Converts the output from the Interdata CAL assembler into a UNIX a.out file. .sh AUTHOR R Miller .br University of Wollongong .sh "SEE ALSO" a.out(V), cvtask(I) .sh BUGS Absolute code is not supported. .br Halfword externals are not supported. .br If input file contains common block initializations (BDATA) it must not have any pure or impure segments. register struct selchq *s; register struct selchtab *st; st = &selchtab[n]; trace(040<<16, "schfree", st->sc_actf); if ((s = st->sc_actf) == 0) return; st->sc_actf = s = s->sq_forw; if (s) (*s->sq_sstart)(); } /* * Selector channel interrupt -- handled by currently active device */ selchintr(dev, stat) { register struct selchq *s; register struct selchtab *st; trace(040<<16, "interrupt", dev); trace(040<<16, "status", stat); st = &selchtab[devmap(dev)]; if (s = st->sc_actf) (*s->sq_ty() { register int *up; up = u.u_arg[0]; u.u_arg[0] = fuword(up); u.u_arg[1] = fuword(++up); u.u_arg[2] = fuword(++up); sgtty(0); } /* * Stuff common to stty and gtty. * Check legality and switch out to individual * device routine. * v is 0 for stty; the parameters are taken from u.u_arg[]. * c is non-zero for gtty and is the place in which the device * routines place their information. */ sgtty(v) int *v; { register struct file *fp; register struct inode *ip; if ((fp = getf(u.u_ar0[R0 spl(5); while (tp->t_delct==0) { if ((tp->t_state&CARR_ON)==0) return(0); sleep(&tp->t_rawq, TTIPRI); } spl(0); loop: bp = &canonb[2]; while ((c=getc(&tp->t_rawq)) >= 0) { if (c==0377) { tp->t_delct--; break; } if ((tp->t_flags&RAW)==0) { if (bp[-1]!='\\') { if (c==tp->t_erase) { if (bp > &canonb[2]) bp--; continue; } if (c==tp->t_kill) goto loop; if (c==CEOT) continue; } else if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE)))юp(p(Ї'tX,P@P@PA@&t%$PA@!$T C0"X @P PPA@CX P $PA@!X(P X,P $PA.PA@t@@T #6PA@d$P юp(p(ЇX(%C0$%x&X $U C X P PA@tCX $Y B0*$T C0 X P ,PA@uZPA@tC^$T !6X $&P $P $PA@!X@%#7X@%P #P@%P@%@%!3A$PA@!юp(p(ЇX@%C0$%x%C0.$T C0$X P X P@%PA@tCX P %!7$@%CZX $Y B02$@%$T B0X P $T #5$@%CX $U #&$@%#$@%@XP$PA@#Cюp(p(Ї't@%P@P@PA@&tX@%C0@T@%CX $B0r$%x PPA@"@PPA@"PA@" ð#7X P ð #7X P $@%# X $PPA@"'tX $P@PPA@&t'tPA@" P@PPA@&tX P@%PA@t$PA@2CPPA@"'tP@PPA@&t'tPA@" P@PPA@&tCf0PPA@"'t0P@PPA@&t'tPA@" P@PPA@&tCHP@PA@"X P@PA@"2X Z 'P@PA@"2'tX P@PPA@&t$T !8@%B0.!PPA@"pP@PA@"C*"PPA@"PP@PA@"C'!)!X@dюp(p(# /* */ /* * general TTY subroutines */ #include "param.h" #include "systm.h" #include "user.h" #include "tty.h" #include "proc.h" #include "inode.h" #include "file.h" #include "reg.h" #include "conf.h" /* * Input mapping table-- if an entry is non-zero, when the * corresponding character is typed preceded by "\" the escape * sequence is replaced by the table value. Mostly used for * upper-case only terminals. */ char maptab[] { 000,000,000,000,004,000,000,000, 000,000,000,000,000,000,000,000, ])) == NULL) return; ip = fp->f_inode; if ((ip->i_mode&IFMT) != IFCHR) { u.u_error = ENOTTY; return; } (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v); } /* * Wait for output to drain, then flush input waiting. */ wflushtty(atp) struct tty *atp; { register struct tty *tp; tp = atp; spl(5); while (tp->t_outq.c_cc) { tp->t_state =| ASLEEP; sleep(&tp->t_outq, TTOPRI); } flushtty(tp); spl(0); } /* * Initialize clist by freeing all character blocks, then count * number of c            ЇHP@PA@"@PA@"P&P@%юp(p(Ї'tX(P@PPA@&t'tX,P@PPA@&tT,C0zӰ@%$@%X@%C0bɰ!5ACT$PA@2$%xX P $T,C04X P X P@%X P PA@tACɰ!5%Q #$Q T,C0jɰB0b'tX(PX,PPA@ &t@%&@%C"$@%@XP$PA@ClX P ɰC0`T,C0HɰB0@$@%X P@%`T,#4X # X PPA@ B0XU@#XCю p,p(ЇX(X P , BX P PA@tCX@U$B (X #7X P PA@tC^$P $PA@!X@%tP@%tX@% !5P@% #X@%$P P@%$@%!3A$PA@!юp(p(ЇX@% C0@%&@%'tP@PPA@&t@P@%XX@Z$P@%\ P@%` P@%dX P@%hX Z 'P@%l@P$# /* * Selector channel scheduling routines */ #include "param.h" #include "buf.h" #include "selch.h" #define NSELCH 2 /* number of channels */ char selchaddr[NSELCH] = { 0xf0, 0xf1 }; #define devmap(addr) (addr&03) /* map channel address=>channel no. */ /* * Queue of devices using selch * - top of queue is currently active device; others are waiting */ struct { struct selchq *sc_actf; struct selchq *sc_actl; } selchtab[NSELCH]; /* * Request use of selch #n */ selchreq(n, selchq) struct se 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,'|',000,'#',000,000,000,'`', '{','}',000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, '@',000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000,000, 000,000,000,000,000,000,'~',000, 000,'A','B','C','D','E','F','G', 'H','I','J','K','L','M','N','O', 'P','Q','R','S','T','U','V','W', 'X','Y','Z',000,000,000,000,000, }; /* The character lists-- space fharacter devices. (Once-only routine) */ cinit() { register int ccp; register struct cblock *cp; register struct cdevsw *cdp; ccp = cfree; for (cp=(ccp+017)&~017; cp <= &cfree[NCLIST-1]; cp++) { /***/ cp->c_next = cfreelist; cfreelist = cp; } ccp = 0; for(cdp = cdevsw; cdp->d_open; cdp++) ccp++; nchrdev = ccp; } /* * flush all TTY queues */ flushtty(atp) struct tty *atp; { register struct tty *tp; register int sps; tp = atp; while (getc(&tp->t_canq) >= 0); while (getc(&tp->t_outq) { if (bp[-2] != '\\') c = maptab[c]; bp--; } } *bp++ = c; if (bp>=canonb+CANBSIZ) break; } bp1 = bp; bp = &canonb[2]; c = &tp->t_canq; while (bpt_flags; if ((c =& 0177) == '\r' && t_flags&CRMOD) c = '\n'; /***/ if ((t_flags&(RAW|BREAK))==0 && (c==CQUIT || c==CINTR)) { signal(tp, c==CINTR? SIGINT:SIGQIT); flushtty(tp); return; } if (tp->t_rawq.c_cc>=TTYHOG) { flushtty(tp); return; } if (t_flags&LCASE && c>='A' && c<='Z') c =+ 'a'-'A'; putc(c, &tp->t_rawq); if (t_flags&RAW || c=='\n' || c==004) { wakeup(&tp->t_rawq); if (putc(0377, &tp->t_rawq)==0) tp->t_delct++; } if (t_flags&ECHO && break; /* backspace */ case 2: if (*colp) (*colp)--; break; /* newline */ case 3: ctype = (rtp->t_flags >> 8) & 03; if(ctype == 1) { /* tty 37 */ if (*colp) c = max((*colp>>4) + 3, 6); } else if(ctype == 2) { /* vt05 */ c = 6; } *colp = 0; break; /* tab */ case 4: ctype = (rtp->t_flags >> 10) & 03; if(ctype == 1) { /* tty 37 */ c = 9 - (*colp & 07); if(c < 5) c = 0; } *colp =| 07; (*colp)++; break; /* vertical motion */ case 5: if(rtp->t_fl>t_canq.c_cc || canon(tp)) while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0); } /* * Called from the device's write routine after it has * calculated the tty-structure given as argument. */ ttwrite(atp) struct tty *atp; { register struct tty *tp; register int c; tp = atp; if ((tp->t_state&CARR_ON)==0) return; while ((c=cpass())>=0) { spl(5); while (tp->t_state&SUSPEND) /***/ sleep(&tp->t_outq, TTOPRI); /***/ while (tp->t_outq.c_cc > TTHIWAT) { ttstart(tp); tp->t_state =| Apied back on return. * dev is the kind of trap that occurred. */ trap(dev, stat, r0, r1, r2, r3, r4, r5, r6, asp, rf, ps, pc, nps) /***/ { register i, a; register struct sysent *callp; trace(02, "trap", dev); trace(02, "psw", pc); #ifdef FPREGS savfp(); #endif if ((ps&UMODE) == UMODE) dev =| USER; u.u_ar0 = &r0; switch(dev) { /* * Trap not expected. * Usually a kernel mode address error. */ default: printf("Useg = %x\n", *ka6); printf("PSW = %x %x\n", ps, pc); printf("SP = %x\n current process to be picked * up later. */ case 8: /* floating exception */ psignal(u.u_procp, SIGFPT); return; case 8+USER: i = SIGFPT; break; /* * If the user SP is below the stack segment, * grow the stack automatically. * This relies on the ability of the hardware * to restart a half executed instruction. * At the moment this is unimplemented (and possibly * unimplementable) on the Interdata. */ case 9+USER: /* segmentation exception */ /*** a = asp; if(backup(u.u_ce to clean up. * * If this occurs, the return takes place without * clearing u_intflg; if it's still set, trap * marks an error which means that a system * call (like read on a typewriter) got interrupted * by a signal. */ trap1(f) int (*f)(); { u.u_intflg = 1; savu(u.u_qsav); (*f)(); u.u_intflg = 0; } /* * nonexistent system call-- set fatal error code. */ nosys() { u.u_error = 100; } /* * Ignored system call */ nullsys() { } !(tp->t_state&SUSPEND)) { ttyoutput(c, tp); ttstart(tp); } } /* * put character on TTY output queue, adding delays, * expanding tabs, and handling the CR/NL bit. * It is called both from the top half for output, and from * interrupt level for echoing. * The arguments are the character and the tty structure. */ ttyoutput(ac, tp) struct tty *tp; { register int c; register struct tty *rtp; register char *colp; int ctype; rtp = tp; c = ac&0177; /* * Ignore EOT in normal mode to avoid hangags & VTDELAY) /* tty 37 */ c = 0177; break; /* carriage return */ case 6: ctype = (rtp->t_flags >> 12) & 03; if(ctype == 1) { /* tn 300 */ c = 5; } else if(ctype == 2) { /* ti 700 */ c = 10; } *colp = 0; } if(c) putc(c|0200, &rtp->t_outq); } /* * Restart typewriter output following a delay * timeout. * The name of the routine is passed to the timeout * subroutine and it is called during a clock interrupt. */ ttrstrt(atp) { register struct tty *tp; tp = atp; tp->t_staSLEEP; sleep(&tp->t_outq, TTOPRI); } spl(0); ttyoutput(c, tp); } ttstart(tp); } /* * Common code for gtty and stty functions on typewriters. * If v is non-zero then gtty is being done and information is * passed back therein; * if it is zero stty is being done and the input information is in the * u_arg array. */ ttystty(atp, av) int *atp, *av; { register *tp, *v; tp = atp; if(v = av) { *v++ = tp->t_speeds; v->lobyte = tp->t_erase; v->hibyte = tp->t_kill; v[1] = tp->t_flags; ", asp); printf("trap type %d\n", dev); panic("trap"); case 0+USER: /* address error */ i = SIGBUS; break; case 1+USER: /* illegal instruction */ #ifdef FPTRAP /**** if illegal instruction assume it to be a floating point one and call fptrap. passing fptrap a pointer to the user's saved r0 ( see reg.h ) and a pointer to his fp regs in the ppda ****/ if ( i=fptrap(&r0,u.u_fsav)) break; /*** error returned by fptrap ***/ goto out; #else i = SIGINS; break; #endif case 2+USER:ar0) == 0) if(grow(a)) goto out; ***/ i = SIGSEG; break; case 10+USER: /* illegal svc number */ i = SIGSYS; break; } psignal(u.u_procp, i); out: if(issig()) psig(); setpri(u.u_procp); } /* * Call the system-entry routine f (out of the * sysent table). This is a subroutine for trap, and * not in-line, because if a signal occurs * during processing, an (abnormal) return is simulated from * the last caller to savu(qsav); if this took place * inside of trap, it wouldn't have a chan# /* */ #include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #include "text.h" #include "inode.h" /* * Swap out process p. * The ff flag causes its core to be freed-- * it may be off when called to create an image for a * child process in newproc. * Os is the old size of the data area of the process, * and is supplied during core expansion swaps. * * panic: out of swap space * panic: swap error -- IO error */ xswap(p, ff, os) int *p; { register *rp, a; rp = p; trace(01,ing up * certain terminals. */ if (c==004 && (rtp->t_flags&RAW)==0) return; /* * Turn tabs to spaces as required */ if (c=='\t' && rtp->t_flags&XTABS) { do ttyoutput(' ', rtp); while (rtp->t_col&07); return; } /* * for upper-case-only terminals, * generate escapes. */ if (rtp->t_flags&LCASE) { colp = "({)}!|^~'`"; while(*colp++) if(c == *colp++) { ttyoutput('\\', rtp); c = colp[-2]; break; } if ('a'<=c && c<='z') c =+ 'A' - 'a'; } /* * turn te =& ~TIMEOUT; ttstart(tp); } /* * Start output on the typewriter. It is used from the top half * after some characters have been put on the output queue, * from the interrupt routine to transmit the next * character, and after a timeout has finished. * If the SSTART bit is off for the tty the work should be done here * (currently unimplemented); * otherwise the address word of the tty structure is * taken to be the name of the device-dependent startup routine. */ ttstart(atp) struct tty *atp; { return(1); } wflushtty(tp); v = u.u_arg; tp->t_speeds = *v++; tp->t_erase = v->lobyte; tp->t_kill = v->hibyte; tp->t_flags = v[1]; return(0); } /* bpt or trace */ i = SIGTRC; break; case 3+USER: /* iot */ i = SIGIOT; break; case 5+USER: /* emt */ i = SIGEMT; break; case 6+USER: /* sys call */ u.u_error = 0; ps =& ~EBIT; callp = &sysent[stat&077]; /*** stat is svc no. ***/ if (callp == sysent) { /* indirect */ a = fuiword(pc); pc =+ 4; /***/ i = fuword(a); if ((i >> 24) != SYS) i = 077; /* illegal */ callp = &sysent[i&077]; for(i=0; icount; i++) u.u_arg[i] = fuword(a =+ 4); /***/ } else       "xswap", rp->p_pid); if(os == 0) os = rp->p_size; a = malloc(swapmap, (rp->p_size+1)/2); /***/ if(a == NULL) panic("out of swap space"); xccdec(rp->p_textp); rp->p_flag =| SLOCK; if(swap(a, rp->p_addr, os, 0)) panic("swap error"); if(ff) mfree(coremap, os, rp->p_addr); rp->p_addr = a; rp->p_flag =& ~(SLOAD|SLOCK); rp->p_time = 0; if(runout) { runout = 0; wakeup(&runout); } } /* * relinquish use of the shared text segment * of a process. */ xfree() { register *xp, *ip; if((xp=to if desired. */ if (c=='\n' && rtp->t_flags&CRMOD) ttyoutput('\r', rtp); putc(c, &rtp->t_outq); /* * Calculate delays. * The numbers here represent clock ticks * and are not necessarily optimal for all terminals. * The delays are indicated by characters above 0200, * thus (unfortunately) restricting the transmission * path to 7 bits. */ colp = &rtp->t_col; ctype = partab[c]; c = 0; switch (ctype&077) { /* ordinary */ case 0: (*colp)++; /* non-printing */ case 1: register int *addr, c; register struct tty *tp; struct { int (*func)(); }; tp = atp; addr = tp->t_addr; if (tp->t_state&SSTART) { (*addr.func)(tp); return; } } /* * Called from device's read routine after it has * calculated the tty-structure given as argument. * The pc is backed up for the duration of this call. * In case of a caught interrupt, an RTI will re-execute. */ ttread(atp) struct tty *atp; { register struct tty *tp; tp = atp; if ((tp->t_state&CARR_ON)==0) return; if (tp- the user's registers relative to * the saved r0. See reg.h */ int regloc[18] { R0, R1, R2, R3, R4, R5, R6, R7, /***/ R8, R9, R10, R11, R12, R13, R14, R15, /***/ RPS, RPC }; /* * Called from low.s when a processor trap occurs. * The arguments are the words saved on the system stack * by the software during the trap processing. * Their order is dictated by the details * of C's calling sequence. They are peculiar in that * this call is not 'by value' and changed user registers * get co { for(i=0; icount; i++) { u.u_arg[i] = fuiword(pc); pc =+ 4; /***/ } } trace(04, "svc", callp-sysent); u.u_dirp = u.u_arg[0]; trap1(callp->call); if(u.u_intflg) u.u_error = EINTR; if(u.u_error < 100) { if(u.u_error) { ps =| EBIT; r0 = u.u_error; } goto out; } i = SIGSYS; break; /* * Since the floating exception is an * imprecise trap, a user generated * trap may actually come from kernel * mode. In this case, a signal is sent * to the# #include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #include "reg.h" #include "seg.h" #define EBIT 010 /*** user err bit in psw: C-bit ***/ #define UMODE 01<<8 /*** user-mode bit in tsw (prot bit) ***/ #define SYS 0341 /*** svc (trap) instruction ***/ #define USER 020 /* user-mode flag added to dev */ /* * structure of the system entry table (sysent.c) */ extern struct sysent { int count; /* argument count */ int (*call)(); /* name of handler */ } sysent[64]; /* * Offsets ofu.u_procp->p_textp) != NULL) { u.u_procp->p_textp = NULL; xccdec(xp); if(--xp->x_count == 0) { ip = xp->x_iptr; if((ip->i_mode&ISVTX) == 0) { xp->x_iptr = NULL; mfree(swapmap, (xp->x_size+1)/2, xp->x_daddr); /***/ ip->i_flag =& ~ITEXT; iput(ip); } } } } /* * Attach to a shared text segment. * If there is no shared text, just return. * If there is, hook up to it: * if it is not currently being used, it has to be read * in from the inode (ip) and established in the swap space. * If it is being used, but is not currently in core, * a swap has to be done to get it back. * The full coroutine glory has to be invoked-- * see slp.c-- because if the calling process * is misplaced in core the text image might not fit. * Quite possibly the code after "out:" could check to * see if the text does fit and simply swap it in. * * panic: out of swap space */ xalloc(ip) int *ip; { register struct text *xp; register *rp, ts; int dummy[4]; /*** savu callers must have same stac# /* */ /* * This table is the switch used to transfer * to the appropriate routine for processing a system call. * Each row contains the number of arguments expected * and a pointer to the routine. */ int sysent[] { 0, &nullsys, /* 0 = indir */ 0, &rexit, /* 1 = exit */ 0, &fork, /* 2 = fork */ 2, &read, /* 3 = read */ 2, &write, /* 4 = write */ 2, &open, /* 5 = open */ 0, &close, /* 6 = close */ 0, &wait, /* 7 = wait */ 2, &creat, /* 8 = creat */ 2, &link, /* = x */ 0, &nosys, /* 61 = x */ 0, &nosys, /* 62 = x */ 0, &nosys /* 63 = x */ }; = 0; writei(pp); ip->i_nlink--; ip->i_flag =| IUPD; out: iput(pp); iput(ip); } chdir() { register *ip; extern uchar; ip = namei(&uchar, 0); if(ip == NULL) return; if((ip->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; bad: iput(ip); return; } if(access(ip, IEXEC)) goto bad; iput(u.u_cdir); u.u_cdir = ip; prele(ip); } chmod() { register *ip; if ((ip = owner()) == NULL) return; ip->i_mode =& ~07777; if (u.u_uid) u.u_arg[1] =& ~ISVTX; ip->i_mode =| u.u_arg[1]&07777; ip->q->p_ttyp || p <= &proc[1])) continue; if(u.u_uid != 0 && u.u_uid != p->p_uid) continue; f++; psignal(p, u.u_arg[0]); } if(f == 0) u.u_error = ESRCH; } times() { register *p; for(p = &u.u_utime; p < &u.u_utime+6;) { suword(u.u_arg[0], *p++); u.u_arg[0] =+ 4; /***/ } } profil() { u.u_prof[0] =u.u_arg[0] & ~3; /* base of sample buf */ u.u_prof[1] = u.u_arg[1] & ~3; /* size of same */ u.u_prof[2] = u.u_arg[2]; /* pc offset*/ u.u_prof[3] = (u.u_arg[3]>>1); /* pc scale *//***/ } o out; } else if(smp == NULL) smp = mp; } if(smp == NULL) goto out; (*bdevsw[d.d_major].d_open)(d, !u.u_arg[2]); if(u.u_error) goto out; mp = bread(d, 1); if(u.u_error) { brelse(mp); goto out1; } smp->m_inodp = ip; smp->m_dev = d; smp->m_bufp = getblk(NODEV); bcopy(mp->b_addr, smp->m_bufp->b_addr, 128); /***/ smp = smp->m_bufp->b_addr; smp->s_ilock = 0; smp->s_flock = 0; smp->s_ronly = u.u_arg[2] & 1; brelse(mp); ip->i_flag =| IMOUNT; prele(ip); return; out: u.u_error = Ek frame ***/ if(u.u_arg[1] == 0) return; rp = NULL; for(xp = &text[0]; xp < &text[NTEXT]; xp++) if(xp->x_iptr == NULL) { if(rp == NULL) rp = xp; } else if(xp->x_iptr == ip) { xp->x_count++; u.u_procp->p_textp = xp; goto out; } if((xp=rp) == NULL) panic("out of text"); xp->x_count = 1; xp->x_ccount = 0; xp->x_iptr = ip; ts = ((u.u_arg[1]+255)>>8) & 07777; /***/ xp->x_size = ts; if((xp->x_daddr = malloc(swapmap, (ts+1)/2)) == NULL) /***/ panic("out of swap space" 9 = link */ 1, &unlink, /* 10 = unlink */ 2, &exec, /* 11 = exec */ 1, &chdir, /* 12 = chdir */ 0, >ime, /* 13 = time */ 3, &mknod, /* 14 = mknod */ 2, &chmod, /* 15 = chmod */ 2, &chown, /* 16 = chown */ 1, &sbreak, /* 17 = break */ 2, &stat, /* 18 = stat */ 2, &seek, /* 19 = seek */ 0, &getpid, /* 20 = getpid */ 3, &smount, /* 21 = mount */ 1, &sumount, /* 22 = umount */ 0, &setuid, /* 23 = setuid */ 0, &getuid, /* 24 = getuid */ 0, &stime, /* 25 = stime # /* */ /* * Everything in this file is a routine implementing a system call. */ #include "param.h" #include "user.h" #include "reg.h" #include "inode.h" #include "systm.h" #include "proc.h" getswit() { extern int csw; u.u_ar0[R0] = csw; /* console switches read by display() */ } gtime() { u.u_ar0[R0] = time[0]; u.u_ar0[R1] = time[1]; } stime() { if(suser()) { time[0] = u.u_ar0[R0]; time[1] = u.u_ar0[R1]; wakeup(tout); } } setuid() { register uid; uid = u.u_ar0[R0].lobyte; if(u.ui_flag =| IUPD; iput(ip); } chown() { register *ip; if (!suser() || (ip = owner()) == NULL) return; ip->i_uid = u.u_arg[1].lobyte; ip->i_gid = u.u_arg[1].hibyte; ip->i_flag =| IUPD; iput(ip); } /* * Change modified date of file: * time to r0-r1; sys smdate; file * This call had been withdrawn because it messes up * incremental dumps (pseudo-old files aren't dumped). */ smdate() { register struct inode *ip; register int *tp; int tbuf[2]; if (suser() == 0 || (ip = owner()) == NULL) /***# /* */ #include "param.h" #include "systm.h" #include "reg.h" #include "buf.h" #include "filsys.h" #include "user.h" #include "inode.h" #include "file.h" #include "conf.h" /* * the fstat system call. */ fstat() { register *fp; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; stat1(fp->f_inode, u.u_arg[0]); } /* * the stat system call. */ stat() { register ip; extern uchar; ip = namei(&uchar, 0); if(ip == NULL) return; stat1(ip, u.u_arg[1]); iput(ip); } /* * The basic routine for fstBUSY; out1: iput(ip); } /* * the umount system call. */ sumount() { int d; register struct inode *ip; register struct mount *mp; update(); d = getmdev(); if(u.u_error) return; for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) if(mp->m_bufp!=NULL && d==mp->m_dev) goto found; u.u_error = EINVAL; return; found: for(ip = &inode[0]; ip < &inode[NINODE]; ip++) if(ip->i_number!=0 && d==ip->i_dev) { u.u_error = EBUSY; return; } (*bdevsw[d.d_major].d_close)(d, 0); ip = mp->m_inodp; i); expand(USIZE+ts); estabur(0, ts, 0, 0); u.u_count = u.u_arg[1]; u.u_offset[1] = 32; /***/ u.u_base = 0; readi(ip); rp = u.u_procp; rp->p_flag =| SLOCK; swap(xp->x_daddr, rp->p_addr+USIZE, ts, 0); rp->p_flag =& ~SLOCK; rp->p_textp = xp; rp = ip; rp->i_flag =| ITEXT; rp->i_count++; expand(USIZE); out: if(xp->x_ccount == 0) { savu(u.u_rsav); savu(u.u_ssav); xswap(u.u_procp, 1, 0); u.u_procp->p_flag =| SSWAP; swtch(); /* no return */ } xp->x_ccount++; } /* * Decrement the in*/ 3, &ptrace, /* 26 = ptrace */ 0, &nosys, /* 27 = x */ 1, &fstat, /* 28 = fstat */ 0, &nosys, /* 29 = x */ 1, &smdate, /* 30 = smdate; *** was inoperative */ 1, &stty, /* 31 = stty */ 1, >ty, /* 32 = gtty */ 0, &nosys, /* 33 = x */ 0, &nice, /* 34 = nice */ 0, &sslep, /* 35 = sleep */ 0, &sync, /* 36 = sync */ 1, &kill, /* 37 = kill */ 0, &getswit, /* 38 = switch */ 0, &nosys, /* 39 = x */ 0, &nosys, /* 40 = x */ 0, &dup, /* 41 = dup */ 0, &pipe, /* 42 _ruid == uid/*** .lobyte ***/ || suser()) { u.u_uid = uid; u.u_procp->p_uid = uid; u.u_ruid = uid; } } getuid() { u.u_ar0[R0].lobyte = u.u_ruid; u.u_ar0[R0].hibyte = u.u_uid; } setgid() { register gid; gid = u.u_ar0[R0].lobyte; if(u.u_rgid == gid/*** .lobyte ***/ || suser()) { u.u_gid = gid; u.u_rgid = gid; } } getgid() { u.u_ar0[R0].lobyte = u.u_rgid; u.u_ar0[R0].hibyte = u.u_gid; } getpid() { u.u_ar0[R0] = u.u_procp->p_pid; } sync() { update(); } nice() { register n; n = / return; ip->i_flag =| IUPD; tp = &tbuf[2]; *--tp = u.u_ar0[R1]; *--tp = u.u_ar0[R0]; iupdat(ip, tp); ip->i_flag =& ~IUPD; iput(ip); } ssig() { register a, aps, *asp; /***/ a = u.u_arg[0]; /* * Signal 0 means return from signal routine: * pop PS, PC, and SP off stack. */ /***/ if (a == 0) { /***/ asp = u.u_ar0[RSP]; /***/ if ((aps = fuword(asp++)) & (1<<31)) /* no user stack */ /***/ u.u_nostack = 1; /***/ u.u_ar0[RPS] = (aps & 010017) | (u.u_ar0[RPS] & ~010017); /***/ u.u_arat and stat: * get the inode and pass appropriate parts back. */ stat1(ip, ub) int *ip; { register i, *bp, *cp; iupdat(ip, time); bp = bread(ip->i_dev, ldiv(ip->i_number+15, 8)); /***/ cp = bp->b_addr + 64*lrem(ip->i_number+15, 8) + 44; /***/ ip = &(ip->i_dev); for(i=0; i<13; i++) { /***/ suword(ub, *ip++); ub =+ 4; /***/ } for(i=0; i<4; i++) { suword(ub, *cp++); ub =+ 4; /***/ } brelse(bp); } /* * the dup system call. */ dup() { register i, *fp; fp = getf(u.u_ar0[R0]); if(fp->i_flag =& ~IMOUNT; iput(ip); ip = mp->m_bufp; mp->m_bufp = NULL; brelse(ip); } /* * Common code for mount and umount. * Check that the user's argument is a reasonable * thing on which to mount, and return the device number if so. */ getmdev() { register d, *ip; extern uchar; ip = namei(&uchar, 0); if(ip == NULL) return; if((ip->i_mode&IFMT) != IFBLK) u.u_error = ENOTBLK; d = ip->i_addr[0]; if(ip->i_addr[0].d_major >= nblkdev) u.u_error = ENXIO; iput(ip); return(d); } -core usage count of a shared text segment. * When it drops to zero, free the core space. */ xccdec(xp) int *xp; { register *rp; if((rp=xp)!=NULL && rp->x_ccount!=0) if(--rp->x_ccount == 0) mfree(coremap, rp->x_size, rp->x_caddr); } = pipe */ 1, ×, /* 43 = times */ 4, &profil, /* 44 = prof */ 0, &nosys, /* 45 = tiu */ 0, &setgid, /* 46 = setgid */ 0, &getgid, /* 47 = getgid */ 2, &ssig, /* 48 = sig */ 0, &nosys, /* 49 = x */ 0, &nosys, /* 50 = x */ 0, &nosys, /* 51 = x */ 0, &nosys, /* 52 = x */ 0, &nosys, /* 53 = x */ 0, &nosys, /* 54 = x */ 0, &nosys, /* 55 = x */ 0, &nosys, /* 56 = x */ 0, &nosys, /* 57 = x */ 0, &nosys, /* 58 = x */ 0, &nosys, /* 59 = x */ 0, &nosys, /* 60 u.u_ar0[R0]; if(n > 20) n = 20; if(n < 0 && !suser()) n = 0; u.u_procp->p_nice = n; } /* * Unlink system call. * panic: unlink -- "cannot happen" */ unlink() { register *ip, *pp; extern uchar; pp = namei(&uchar, 2); if(pp == NULL) return; prele(pp); ip = iget(pp->i_dev, u.u_dent.u_ino); if(ip == NULL) panic("unlink -- iget"); if((ip->i_mode&IFMT)==IFDIR && !suser()) goto out; u.u_offset[1] =- DIRSIZ+2; u.u_base = &u.u_dent.u_name[-2]; /***/ u.u_count = DIRSIZ+2; u.u_dent.u_ino 0[RPC] = fuword(asp++); /***/ u.u_ar0[RSP] = fuword(asp); /***/ return; /***/ } if(a<0 || a>=NSIG || a ==SIGKIL) { u.u_error = EINVAL; return; } u.u_ar0[R0] = u.u_signal[a]; u.u_signal[a] = u.u_arg[1]; if(u.u_procp->p_sig == a) u.u_procp->p_sig = 0; } kill() { register struct proc *p, *q; register a; int f; f = 0; a = u.u_ar0[R0]; q = u.u_procp; for(p = &proc[0]; p < &proc[NPROC]; p++) { if(p == q) continue; if(a != 0 && p->p_pid != a) continue; if(a == 0 && (p->p_ttyp != p == NULL) return; if ((i = ufalloc()) < 0) return; u.u_ofile[i] = fp; fp->f_count++; } /* * the mount system call. */ smount() { int d; register *ip; register struct mount *mp, *smp; extern uchar; d = getmdev(); if(u.u_error) return; u.u_dirp = u.u_arg[1]; ip = namei(&uchar, 0); if(ip == NULL) return; if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) goto out; smp = NULL; for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { if(mp->m_bufp != NULL) { if(d == mp->m_dev) got# #include "param.h" #include "systm.h" #include "user.h" #include "reg.h" #include "file.h" #include "inode.h" /* * read system call */ read() { rdwr(FREAD); } /* * write system call */ write() { rdwr(FWRITE); } /* * common code for read and write calls: * check permissions, set base, count, and offset, * and switch out to readi, writei, or pipe code. */ rdwr(mode) { register *fp, m; m = mode; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; if((fp->f_flag&m) == 0) { u.u_error = EBADF; return; } u.u_base = u.u_arg[0]; u.u_count = u.u_arg[1]; u.u_segflg = 0; if(fp->f_flag&FPIPE) { if(m==FREAD) readp(fp); else writep(fp); } else { u.u_offset[1] = fp->f_offset[1]; u.u_offset[0] = fp->f_offset[0]; if(m==FREAD) readi(fp->f_inode); else writei(fp->f_inode); dpadd(fp->f_offset, u.u_arg[1]-u.u_count); } u.u_ar0[R0] = u.u_arg[1]-u.u_count; } /* * open system call */ open() { register *ip; extern uchar; ip = namei(&uchar, 0); if(ip == NULL) return; u.u_ar { case 1: case 4: n[0] =+ fp->f_offset[0]; dpadd(n, fp->f_offset[1]); break; default: n[0] =+ fp->f_inode->i_size0&0377; dpadd(n, fp->f_inode->i_size1); case 0: case 3: ; } fp->f_offset[1] = n[1]; fp->f_offset[0] = n[0]; } /* * link system call */ link() { register *ip, *xp; extern uchar; ip = namei(&uchar, 0); if(ip == NULL) return; /***/ if(ip->i_nlink >= 255) { u.u_error = EMLINK; goto out; } if((ip->i_mode&IFMT)==IFDIR && !suser()) goto out; /* * unlock to avut, PSLEP); } spl(0); } na++; if(ap == -1) goto bad; u.u_arg[1] =+ 4; /***/ for(;;) { c = fubyte(ap++); if(c == -1) goto bad; *cp++ = c; nc++; if(nc > 510) { u.u_error = E2BIG; goto bad; } if(c == 0) break; } } while((nc&03) != 0) { /***/ *cp++ = 0; nc++; } /* * read in first 4 words * of file for segment * sizes: * w0 = 407/410/411 (410 implies RO text) (411 implies sep ID) * w1 = text size * w2 = data size * w3 = bss size */ u.u_base = &u.u_arg[0]; u.otections, if no tracing */ if ((u.u_procp->p_flag&STRC)==0) { if(ip->i_mode&ISUID) if(u.u_uid != 0) { u.u_uid = ip->i_uid; u.u_procp->p_uid = ip->i_uid; } if(ip->i_mode&ISGID) u.u_gid = ip->i_gid; } /* * clear sigs, regs and return */ c = ip; for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++) if((*ip & 1) == 0) *ip = 0; ap = u.u_ar0[RSP]; /***/ for(ip = ®loc[0]; ip < ®loc[16];) /***/ u.u_ar0[*ip++] = 0; /***/ u.u_ar0[RSP] = ap; /***/ u.u_ar0[RPC]proc[NPROC]; p++) if(p->p_ppid == u.u_procp->p_pid) { f++; if(p->p_stat == SZOMB) { u.u_ar0[R0] = p->p_pid; bp = bread(swapdev, f=p->p_addr); mfree(swapmap, 1, f); p->p_stat = NULL; p->p_pid = 0; p->p_ppid = 0; p->p_sig = 0; p->p_ttyp = 0; p->p_flag = 0; p = bp->b_addr; u.u_cstime[0] =+ p->u_cstime[0]; dpadd(u.u_cstime, p->u_cstime[1]); dpadd(u.u_cstime, p->u_stime); u.u_cutime[0] =+ p->u_cutime[0]; dpadd(u.u_cutime, p->u_cutime[1]); dpadd(u.u_cutime, p->g[1]++; open1(ip, u.u_arg[1], 0); } /* * creat system call */ creat() { register *ip; extern uchar; ip = namei(&uchar, 1); if(ip == NULL) { if(u.u_error) return; ip = maknode(u.u_arg[1]&07777&(~ISVTX)); if (ip==NULL) return; open1(ip, FWRITE, 2); } else open1(ip, FWRITE, 1); } /* * common code for open and creat. * Check permissions, allocate an open file structure, * and call the device open routine if any. */ open1(ip, mode, trf) int *ip; { register struct file *fp; registoid possibly hanging the namei */ ip->i_flag =& ~ILOCK; u.u_dirp = u.u_arg[1]; xp = namei(&uchar, 1); if(xp != NULL) { u.u_error = EEXIST; iput(xp); } if(u.u_error) goto out; if(u.u_pdir->i_dev != ip->i_dev) { iput(u.u_pdir); u.u_error = EXDEV; goto out; } wdir(ip); ip->i_nlink++; ip->i_flag =| IUPD; out: iput(ip); } /* * mknod system call */ mknod() { register *ip; extern uchar; if(suser()) { ip = namei(&uchar, 1); if(ip != NULL) { u.u_error = EEXIST; goto out; F L ; A G M < B H N = C I O P Vu_count = 16; /***/ u.u_offset[1] = 0; u.u_offset[0] = 0; u.u_segflg = 1; readi(ip); u.u_segflg = 0; if(u.u_error) goto bad; sep = 0; if(u.u_arg[0] == 0407) { u.u_arg[2] =+ u.u_arg[1]; u.u_arg[1] = 0; } else if(u.u_arg[0] == 0411) sep++; else if(u.u_arg[0] != 0410) { u.u_error = ENOEXEC; goto bad; } if(u.u_arg[1]!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { u.u_error = ETXTBSY; goto bad; } /* * find text and data sizes * try them out for possible * exceed of max si = 0; for(ip = &u.u_fsav[0]; ip < &u.u_fsav[24];) /***/ *ip++ = 0; ip = c; bad: iput(ip); brelse(bp); if(execnt >= NEXEC) wakeup(&execnt); execnt--; } /* * exit system call: * pass back caller's r0 */ rexit() { u.u_arg[0] = u.u_ar0[R0] << 8; exit(); } /* * Release resources. * Save u. area for parent to look at. * Enter zombie state. * Wake up parent and init processes, * and dispose of children. */ exit() { register int *q, a; register struct proc *p; u.u_procp->p_flag =& ~STRu_utime); u.u_ar0[R1] = p->u_arg[0]; brelse(bp); return; } if(p->p_stat == SSTOP) { if((p->p_flag&SWTED) == 0) { p->p_flag =| SWTED; u.u_ar0[R0] = p->p_pid; u.u_ar0[R1] = (p->p_sig<<8) | 0177; return; } p->p_flag =& ~(STRC|SWTED); setrun(p); } } if(f) { sleep(u.u_procp, PWAIT); goto loop; } u.u_error = ECHILD; } /* * fork system call. */ fork() { register struct proc *p1, *p2; p1 = u.u_procp; for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++) if(p2->p_staer *rip, m; int i; rip = ip; m = mode; if(trf != 2) { if(m&FREAD) access(rip, IREAD); if(m&FWRITE) { access(rip, IWRITE); if((rip->i_mode&IFMT) == IFDIR) u.u_error = EISDIR; } } if(u.u_error) goto out; if(trf) itrunc(rip); prele(rip); if ((fp = falloc()) == NULL) goto out; fp->f_flag = m&(FREAD|FWRITE); fp->f_inode = rip; i =u.u_ar0[R0]; openi(rip, m&FWRITE); if(u.u_error == 0) return; u.u_ofile[i] = NULL; fp->f_count--; out: iput(rip); } /* * close system cal } } if(u.u_error) return; ip = maknode(u.u_arg[1]); if (ip==NULL) return; ip->i_addr[0] = u.u_arg[2]; out: iput(ip); } /* * sleep system call * not to be confused with the sleep internal routine. */ sslep() { char *d[2]; spl(7); d[0] = time[0]; d[1] = time[1]; dpadd(d, u.u_ar0[R0]); while(dpcmp(d[0], d[1], time[0], time[1]) > 0) { if(dpcmp(tout[0], tout[1], time[0], time[1]) <= 0 || dpcmp(tout[0], tout[1], d[0], d[1]) > 0) { tout[0] = d[0]; tout[1] = d[1]; } sleep(to# /* */ #include "param.h" #include "systm.h" #include "user.h" #include "proc.h" #include "buf.h" #include "reg.h" #include "inode.h" /* * exec system call. * Because of the fact that an I/O buffer is used * to store the caller's arguments during exec, * and more buffers are needed to read in the text file, * deadly embraces waiting for free buffers are possible. * Therefore the number of processes simultaneously * running in exec has to be limited to NEXEC. */ #define EXPRI -1 exec() { int apzes */ ts = ((u.u_arg[1]+255)>>8) & 07777; /***/ ds = ((u.u_arg[2]+u.u_arg[3]+255)>>8) & 07777; /***/ if(estabur(ts, ds, SSIZE, sep)) goto bad; /* * allocate and clear core * at this point, committed * to the new image */ u.u_prof[3] = 0; xfree(); expand(USIZE); xalloc(ip); c = USIZE+ds+SSIZE; expand(c); while(--c >= USIZE) clearseg(u.u_procp->p_addr+c); /* * read in data segment */ estabur(0, ds, 0, 0); u.u_base = 0; u.u_offset[1] = 32+u.u_arg[1]; /***/ u.u_count = C; for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];) *q++ = 1; for(q = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++) if(a = *q) { *q = NULL; closef(a); } iput(u.u_cdir); xfree(); a = malloc(swapmap, 1); if(a == NULL) panic("out of swap"); p = getblk(swapdev, a); bcopy(&u, p->b_addr, 128); /***/ bwrite(p); q = u.u_procp; mfree(coremap, q->p_size, q->p_addr); q->p_addr = a; q->p_stat = SZOMB; loop: for(p = &proc[0]; p < &proc[NPROC]; p++) if(q->p_ppid == p->p_pid) { wakeup(&proc[1t == NULL) goto found; u.u_error = EAGAIN; goto out; found: if(newproc()) { u.u_ar0[R0] = p1->p_pid; u.u_cstime[0] = 0; u.u_cstime[1] = 0; u.u_stime = 0; u.u_cutime[0] = 0; u.u_cutime[1] = 0; u.u_utime = 0; return; } u.u_ar0[R0] = p2->p_pid; out: u.u_ar0[RPC] =+ instrlen(u.u_ar0[RPC]); /***/ } /* * break system call. * -- bad planning: "break" is a dirty word in C. */ sbreak() { register a, n, d; int i; /* * set n to new data size * set d to new-old * set n to new l */ close() { register *fp; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; u.u_ofile[u.u_ar0[R0]] =NULL; closef(fp); } /* * seek system call */ seek() { int n[2]; register *fp, t; fp = getf(u.u_ar0[R0]); if(fp == NULL) return; if(fp->f_flag&FPIPE) { u.u_error = ESPIPE; return; } t = u.u_arg[1]; if(t > 2) { n[1] = u.u_arg[0]<<9; n[0] = u.u_arg[0]>>23; /***/ if(t == 3) n[0] =& 0777; } else { n[1] = u.u_arg[0]; n[0] = 0; if(t!=0 && n[1]<0) n[0] = -1; } switch(t) 7 8 > D J 9 ? E :, na, nc, *bp; int ts, ds, sep; register c, *ip; register char *cp; extern uchar; /* * pick up file names * and check various modes * for execute permission */ ip = namei(&uchar, 0); if(ip == NULL) return; while(execnt >= NEXEC) sleep(&execnt, EXPRI); execnt++; bp = getblk(NODEV); if(access(ip, IEXEC) /*** || (ip->i_mode&IFMT)!=0 ***/ ) goto bad; /* * pack up arguments into * allocated disk buffer */ cp = bp->b_addr; na = 0; nc = 0; while(ap = fuword(u.u_arg[1])) { u.u_arg[2]; readi(ip); /* * initialize stack segment */ u.u_tsize = ts; u.u_dsize = ds; u.u_ssize = SSIZE; u.u_sep = sep; estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep); cp = bp->b_addr; ap = (14<<16) + (SSIZE<<8) -nc - (na+2)*4; /***/ u.u_ar0[RSP] = ap; /***/ u.u_nostack = 0; /***/ suword(ap, na); c = (14<<16) + (SSIZE<<8) -nc; /***/ while(na--) { /***/ suword(ap=+4, c); /***/ do subyte(c++, *cp); while(*cp++); } suword(ap+4, -1); /***/ /* * set SUID/SGID pr]); wakeup(p); for(p = &proc[0]; p < &proc[NPROC]; p++) if(q->p_pid == p->p_ppid) { p->p_ppid = 1; if (p->p_stat == SSTOP) setrun(p); } swtch(); /* no return */ } q->p_ppid = 1; goto loop; } /* * Wait system call. * Search for a terminated (zombie) child, * finally lay it to rest, and collect its status. * Look also for stopped (traced) children, * and pass back status from them. */ wait() { register f, *bp; register struct proc *p; f = 0; loop: for(p = &proc[0]; p < &total size */ n = (((u.u_arg[0]+255)>>8) & 07777); /***/ if(!u.u_sep) n =- nseg(u.u_tsize) * 256; /***/ if(n < 0) n = 0; d = n - u.u_dsize; n =+ USIZE+u.u_ssize; if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep)) return; u.u_dsize =+ d; if(d > 0) goto bigger; a = u.u_procp->p_addr + n - u.u_ssize; i = n; n = u.u_ssize; while(n--) { copyseg(a-d, a); a++; } expand(i); return; bigger: expand(n); a = u.u_procp->p_addr + n; n = u.u_ssize; while(n--) { a--; copyseg(a-d, a); } while(d--) clearseg(--a); } /* * instrlen: * return the length of the instruction pointed to by ip * (in user space). */ instrlen(ip) char *ip; { register char *p; register op; p = ip; switch((op=fuibyte(p)) >> 4) { /* RR and SF */ case 0: case 1: case 2: case 3: case 9: default: return(2); /* RI2 */ case 15: return(6); /* RX1, RX2, RX3 */ case 5: case 6: case 7: case 13: rx: if ((fuibyte(p+2)&0300) == 0100) return(6); return(4); /* odd cases */ case 12: PA@юp(p(Ї'tX@%XP@PPA@&t'tX@%\P@PPA@&t$Q@%pX@%\PX@%XPA@"(PX@%XPA@"BPX@%XPA@"юp(p(Ї'tX(P@PPA@&t'tX,P@PPA@&tX@% C0`X@%pC0V$P@%p;T,C0"'tX@%XPX,PPAT&tC $T #6pȰA#PȰB'tP@PPA@&t'tX@%`P@PPA@&t'tX@%dP@#PPA@&tHPC@$ тЁB  CH~#3@xx }0|@zЂ,PЁPЁ$Ȱ PB'"Ȁ?A4$AC0ɀ-!7PЁ" ҋ&C$A|AC0f氁$HC0HKE!4'"# ʰЃ BCA>$PbP^A#3&" Xŀ!9$X P& :x&icAĐ`&iJ`F`栃JtЃ6?\AhC0ȰX PK'""@PA@"$T C02$PX@PA@"pP@PA@"C.$PX@PA@"PP@PA@"'tP@PPA@&t'tX ,P@PPA@&t$ @$&@$юp(p(ЇX($@$B0@P$PA@юp(p(Ї'tX(P@PPA@&t'tX,P@PPA@&tX(:$ B04$ XXP@$B0@P$PA@юp(p(ЇX@$C0bHP@PA@"X@PA@" P,C0.'tX@PX,PPA&t$ @$AZюp(p(ЇX,'tX(P@PPA@&t'tP@PPA@&t$@$X@$C0 B0$ XC0('tX@PPPA&t%P AC!6$P ,CHP@PA@"@PA@"P[&ĠQX  P $P ,'tX P@PPA@&tX &P #AC>CX #7X P P,$ X P PA@tAюp(p(ЇX(X'tX0PX$@%X P $@%X P@% X@%tP@%tPA@t$PA@2Aюp(p(Ї'x$P X(P@%(PPA@w&xюp(p(Ї'x$P X(P@%(P~PA@w&xюp(p(Ї+C$%x$T #7$@mCN$P P B@P PX(PA$T #5$@m@m!7X P юp(p(Ї+$%x$$T C0*&0PX(PAb0PX(PAN+C0 C0PX(PA(C8PX(PA$P if (op <= (12<<4)+2) goto rx; return(4); case 14: if (op <= (14<<4)+9) goto rx; return(4); } } ,PPA@ &t &  C $$ X P X P PA@tюp(p(Ї'x$P X(P@$PPA@w&xюp(p(Ї'x$P X(P@$P|PA@w&xюp(p(Ї@$B0X@PA@" Q#7$@mCh't$P@LPPA@&t$@$X@% !;P@% &M`xa`!&h-B=C BPMBBpG@P=C MBBp > ? < ; 8G60% #-B =C BP`Hp@$ #7PAC@$C0Ta!z!%C@[&C0, & B0 @PA%Q@%-#C CX@%&P@%CX@%B0X@%!8@$C0PX@%#6$ PA$Q@%X@%Y@%#&X@%#2$PA !5$P@%$P@%$P@%@$#5$P@%CX@%#%%Q@%CPA|C$Q@%CX@%#6$ PA$T@%#7$ PAl" C  BX@%Y@%C$ PA$P@%X@%Y@% C8X@%Y@%C  PA$Q@%CPA$Q@%$Q@%C@P@$&Y 3X$юp(p(Ї'tX@P@fPPA@&t'tX@PA@" P@nPPA@&tX@PA@" B0N@$PA@(B8'tP@uPPA@&tPX@PA@"C'tP@|PPA@&tюp(p(Ї'tX,P@PPA@&tAT,B0fAX@$FB T@$@C0F'tX@$P@PPA@&t@$@$@$PA@dюp(p(Ї'tX(P@PPA@&t$PA@!X@$BR@$@@$'tX@$P@PPA@&tKP@$PA@C@$PX(PA@A$PA@!юp(p(ЇX,C0,$P &X@% X@% @$P $C*4& P@% P@%X @$$#юp(p,Ї /C0fX@P/B0X@0PPA@ B02XU@C$@mB0XPA@m8Cю p,p,Ї /B0,X@|$P@|Q@xP@PA@0CdX@PA@mBN@mB0B/B0X@0cc -c *.[cs] mv low.o low.oo ar ru unix.a *.o rm *.o ld -x low.oo unix.a mv a.out /unix.test chmod 644 /unix.test PA8C$P X XPX XPX P PXPPX(P X,P $ #юp(p(ЇX($PA@!$T B0PPA@"$PA@!PANюp(p(ЇX($PA@!X XP X X PX P PA@!юp(p(ЇX('tP@P@PA@&tX P T #7PACX P PA@dюp(p(ЇX(X$P &' 5юp(p,Ї @$dP@$tP@$pP@$lP@$h$ɰC`0%P P$ тЁB  CH~#3@xx }0|@zЂ,PЁPЁ$Ȱ PB'"Ȁ?A4$AC0ɀ-!7PЁ" ҋ&C$A|AC0f氁$HC0HKE!4'"# ʰЃ BCA>$PbP^A#3&" Xŀ!9$X P& :x&icAĐ`&iJ`F`栃JtЃ6?\AhC0ȰX PK'""栃8PxPyPŝ] XĀŀA!ŀZ!#ƀ A ŀ ?$Px&QPX] Xj>&M`xa`!&h-B=C BPMBBpG@P=C MBBp > ? < @$dP X@$hP X@$hPP@$h$P PA &C$@PXXC0"XX  #5PP&QCP@ю p,p(Ї$$T #:@T@$4!4$4$PA@!$T C0"X @P PPA@CX4P X@P X0P X(P $X,P P@X@A$PA@!$T B0PPA@"@T #6PA@d$PA@!X P X #юp(p(Ї$PA@!X@$p$dC0JT C06X(#7X(Y B0 X P PAPAFCX C$PA@!юp(p,Ї X0X@xB0$T@|B0 Z@| C X@HPX@T#4$PYBh Z@|XZ@L!ɰBH Z@|X@PC.$PA@!$T C0"X @P PPA@CX8P X4P PX@4P PA@ % P@PA@P $X@|P $ (X@tPX,A$PA@!$T B0PPA@"X@t@T #6PA@d$PA@!X P X ,P@|PA#j@mю p,p(ЇX($T C0 (@m!5$@mюp(p(ЇX('tP@PPA@&t B"X P X P ,PA@tC X $&@B0X #7X P X P ,PA@tCX$$PX$0$P ,!$Q ,$$PA@!X C06X C0X Y ##$#$CX Y #$#$#4CP P B0"@$B0@P$PA@$PA@!юp(p(Ї$X@$!7$P@$'tP@PPA@&t$!$ Source for the Level 6 UNIX Kernel Copyright (C) 1975, Bell Telephone Laboratories, Inc. Copyright (C) 1977, 1978, University of Wollongong To recompile the entire system, see the "run" shell command file. B0NXB0X C0>P$P %W P ӡ@PA@" Ð#2" X Y B02 B0ÐC0'tPPPAp&t%P C|CÐC0($ 'tPP:PA@ @&tCÐbC0$ 'tPPPA&tC $ X PPA@"(BPPA@"'tP@PPA@&t'tX P@PPA@&t#CY@$B0 !9$PA@2CdP@$Xӡ@PA@" #2"HP@PA@"X P@PA@"2X Z 'P@PA@"2X PPA@"(X ,PX; 8G60% #-B =C BP`HpC"@  B0&CX#8XPA@qX4B0$ B0PPA@RB0@ CHX PPA@VX@PXPA@T !4$CCPA@V$#юp0p(ЇX@&P@#юp(p(ЇX@&P@PA@ !6j@m #юp(p8ЇX8X@|C0  X ` B0 X PX@8ACj% P@PA@P PX@PX@|P[PA<X ``C0j'xX@P X@PX P PA@F&x C PPAXPPA@j(P C0X# XX &P@X 8&YB0('tX@PX PPA@o&tPCX PPA@nPXP 8'x$P PXPXPAf&xXPA@q@m!6X@|B0юp8p4ЇX4  X ` B0 X PX@X4X PA@I!4$C^X $XZ4PCPX PA@nXXB0X8'PX XB0HX PA@IP!9PA@q$CXX$X." ,PPA@pC PA@qPX PA@nPXXX8PX XB0FX PA@IPC0.XX$X PXPA@pPA@p#PA@q$P@X#X XP@ #юp4p(Ї@l#:X(X@xC,X(PX@xPA@ 6#j@m%C2%Q@|$Q@!5$Q@$Q@xX@|!3%#$#юp(p(ЇX@|!4%Cf@l#8X@xC$X@xPA@ #j@m%C*%Q@|$Q@!5$Q@$Q@x #юp(p(Ї@mюp(p(Їюp(p(ЇX(X,X0X P &&' 7юp(p(ЇX,PX(PA$T #4 C4X P P P*X@APA2 #юp(p(ЇX($X,PPAB0DX,PPA$T B0(X P P P*X@AX0C0dX0PPAbB0NX0PPA$T #7PAVC(X P P P*X@A B0X,PPA#PA. #юp(p(ЇX(XX xP P PX@AB0PAPAC#8X P #PAHюp(p(ЇX(X@%#5$!7PA"CX P PA6юp(p(ЇX(X P PAюp(p(ЇX(@T #6PA@d@T@$dC0 X@$dP@$d@$dPA@d$T #4% $PA@!T C0($pXPX P P@$dP C$$tXP X P P@$dP ....ocdocncmanmctutlman{READ_MEX 7P PA@!юp(p(ЇX(*X@X C0X $Y,!7X  !3 #XC$#юp(p(Ї'tX,P@P PA@&tX(B*Y@!@PA@ X(#$dC*X@ !9@PA@ X C0~X $Y,B0jX Y(B0^$PA@!$T C0.X @P PPA@$PA@!Cj$PA@!PAJ CXC|$PA@!X@$p$dB08X@$d@P@$dP@$dPA@$PA@!C$PA@!X@$pPAT C0X P /dev/null 9600 156 d--755 0 0 $ Dxsetgid">getgid"?ssig"Buchar"dgetblk"r\readi"e xfree"Fxalloc"Fbrelse"q(closef"Qbcopy"nbwrite"p,bread"ndpadd#„instrlen"0nseg"_rdwr"1getf"Preadp"lwritep"C(X& #' #:VC0xCC0" X #& C0XІ!6BCBBCC0fC^XB|Cj ad,sd end P!B0>C8XxPnC!&CX0BCCfXXC0XXC0 !C@,#B@&@C0&@B0>&# @C0@ BB #& #& #&XPC0ÀB0 :X.CÀ#3'#B"  CXCH  #& #&İ CT&CNXCX <X@ Y8B0X <X@$YC0,$Q CXX&P PX 2#QCdPA@aX 2#$QC$  PA@ X B hX8P@JPA@^@m$#юp8p(ЇX(PA@ B0*X 2CX,X&P P$ юp(p(ЇCbX C0TX Y(B0HXXXX2!%Ű2C $X(P@XPA@^$P $P  C&C@bPA@юp(p(ЇX@B0$Q@CX C0XX @ C^@CT@dCJ@C@@6C6@~C,@C"@C@$# @f#@# Ȱ4##7JA`CPPPp Xpp8,P4P'P7PPp Xp~рЇрP(XnX4 X,C04@#8tA@`"4X(ЀZчЀ2,p8#9 A`Pp@ B0*  @PPA@N^PA@wCX #7X P P,$ X P PA@eA:юp(p(ЇX(X'tX0PX,PPA@&t &  C $$ X P X P PA@eюp(p(Ї'x$P X(P@hPHPA@h|&xюp(p(Ї'x$P X(P@hP PA@h|&xюp(p(CXC0HXXXC0b !C@*#B@$@B0$@C0&# @B0@ B*B0B B0CP #' !B0"B0B0.Đ BB0CCX!7ÀB0^C ÀC0'dXXB:C(CHXPA@$Q@$Q@'tP$P@TPA@Z&t&C'tX@$PX@$P@PA@&tPX@PA@YP@'tX@PX@P@PA@Z&tA@X@8XP@`$P@d$@L@M@M@LP@tA@A@fA@`$PX@PA@KP@tX@t$PX@PA@KP@X@A@%C0P$ PA@''x$P $P$P$PA&x'tP$P@(PA@v&t#A@!юp(p(ЇX@tXX@tX #4XX@4@'B' T #3 # Z P Cюp(p0ЇXX0Z4Z8&Y@B &$X0B  0P &Q0CX0C0 X00P &$X4B  P &Q4CX4C0" X4P &Z4#$P &"Z8X8B Q8' P CX8C0"[8' X8P A $#$ @m%#юp0p(ЇX(#юp(p(ЇX(X C0bX U,BPXX,Q X [,P B0&X P @X P @ C6X@P@CD$PX@PA@DBX@PX@PA@DC $PX@PA@DBX@PX@PA@DCX@!hB*$CX@@Z@ #6&CC`X@$ B0&X@P@X@XP@X@P C@X@X@t$C.A@1%P@C' ) X@L$#юp(p(Ї$PA(юp(p(Ї$PA юp(p(ЇX(X@XPA@G C0  !7$ @mCX@4P@xX@8P@|$@l C0 !7PA@u|#PA@vLCVX P@X P@!9X PA@U#X PA@WX@8[@|P &PA@X@8[@|X@Pюp(p(Ї$P@UPA@Q C0$$Q@8't$PX@8PPA&tюp(p(ЇtLg|P00C@HC@L8 (000$$$$$$$$$$$$$$$$#6 @ohC$T !4$P &" X@XP @CX&Z@$P"X X@PX@$P(h#$P &"PA@MXPA@aX@|!@|PA@ %Q@|ю$pDp(ЇX@XP@4A юp(p(ЇX@th#$P &"4CX#9$P PA@H&CX@PA@MA@D$P@PA@ !9@HPA@PX@PA@c'tPX P@PA@_D&tPA@`X@t'tX PX P@TPA@Z&tP$ LTCrX Y B0^@pPA@ PA@ LTC.X Y B0$P  !6PA@!ʰ$CA@$ʰ$C$P Ctюp(p(Ї$LTCX@tX YB0l& B0X X@PXPX@PA@_t'tP$P@PA@Z&t$ $P $P $ $P $ XX Q@X P@PA@X P@PA@X Q@X P@PA@X P@PA@X 4X@PPA@aC B0T  B02  X X@P X@PCH  PA@!ʰ$Cp C0(PX@tPA@CH$ @mюp(p(ЇX@tLTC C0$" $ @mC\A@%C0BX X@P$P@$P@$P@$P@$P@$P@C*X X@PX@X(PARX@Q(юp(p,Ї X@4X@T!;X@HPA@  #$[@LX@P& 'xX@TP X@PPX@L PX@HPA@&xB0Q@L B NX@tX [@PPX@P 'C0P PA@&"XPA@'CRPA@'X@tX X@P 'C0'P PA@" '#8'PA@" ю p,p(ЇX(PA@ CP$Cd$C^ &PA@@!4$C@$C:C $C,C $CCB BX@юp(p(ЇX@XPA@G C0X@4PX PAXюp(p(Ї$P@UPA@Q C0X@8PPAPA@Mюp(p(Ї@PX(PA@N^'t$PX(X&PA@&tPX(XPA@_t$PX(X&PA@Zʰ,X(&P($ C.X(&P(XPX,PA@D$Q,&C$C$X P&X,PA@D$Q,&CPA@aюp(p(ЇX@XPA@G C0 A@K BP@ & юp(p,Ї A|P@mB0|X@8P@$P@UPA@Q C0R B02 T B0&$C X #8XY C0# !2&C C0X@<#5$P#$PXP X@A@mB0$PXPA@_t@m#8PA@aCPXP %PA@cP 'tPXXPX PA@_D&tXX$ $ X@< PA@a  PA@w# @mPA@Mю p,p,Ї A@HAP@mB0CX #7XY C0&"@mCC(X C0XY !8@mCTX@hX @PX@8P@hX@t !7X@t$юp(p,Ї $PX@XX@tLTCj C0\ #6X B0N B0X Y B0<pC 2@n#8@n B0$QX@4PPA@$CX!5$@mю p,p(ЇC&X P&X@4PA@D$Q@4Cюp(p(ЇX@4P@X@8P@X@!4$CX$PXC.XZ4XP&XZ4$P$QCX $X4PPA@a`X4X P CX8Z4X B0@X PA@>C0,PA@a`X$X8Z4PX4$P@X8CX8Z4XP@ CX8PX#$$PXZ4XB0>X4X PA@>!4$C^X $XZ4PCPX PA@_tXXB0X8'PX XB0HX PA@>P!9PA@a$CXX$X." ,PPA@a`C PA@aPX PA@_tPXXX8PX XB0FX PA@>PC0.XX$X PXPA@a`PA@a`#PA@a$P@X#X XP@ #юp4p(Ї@l#:X(X@xC,X(PX@xPA@,#j@m%C2%Q@|$Q@!5$Q@$Q@xX@|!3%#$#юp(p(ЇX@|!4%Cf@l#8X@xC$X@xPA@#j@m%C*%Q@|$Q@!5$Q@$Q@x #юp(p(Ї@mюp(p(Їюp(p(ЇX(X,X0X P &&' 7юp(p(ЇX,PX(PA$T #4 C4X P P P*X@APA #юp(p(ЇX($X,PPAB0DX,PPA$T B0(X P P P*X@AX0C0dX0PPAbB0NX0PPA$T #7PAVC(X P P P*X@A B0X,PPA#PA  #юp(p(ЇX(XX xP P PX@AB0PAPAC#8X P #PAюp(p(ЇX(X@#5!7PA"CX P PA6юp(p(ЇX(X P PAюp(p(ЇX(@T #6PA@ @T@lC0 X@lP@l@lPA@ $T #4% $PA@T C0(xXPX P P@lP C$|XP X P P@lP X 7P PA@юp(p(ЇX(*X@X C0X $Y,!7X  !3 #XC$#юp(p(ЇX(B*Y@ʤ!@PA@X(#lC*X@ !9@#PA@X C0~X $Y,B0jX Y(B0^$PA@$T C0.X @P PPA@$PA@Cj$PA@PAJ CXC|$PA@X@xlB08X@l@P@lP@lPA@$PA@C$PA@X@xPAT C0X P PA\C$P X XPX XPX P PXPPX(P X,P $ #юp(p(ЇX($PA@$T B0PPA@"$PA@PA.юp(p(ЇX($PA@X XP X X PX P PA@юp(p(ЇX(X P T #7PA*CX P PA@ юp(p(ЇX(X$P &' 5юp(p,Ї @lP@|P@xP@tP@p$ɰC`0%P ʬP@lP X@pP X@pPP@p$P PAN&C$@PXXC0"XX  #5PP&QCP@ʤю p,p(Ї $T #:@T@X@DB0XPA@$CX P@D$P $P &PCBðB0:ʠX@DB0XPA@$C8X P@D$P &P&P$Q XPA@$#ю p,iinitno spacebad blockbno %d nfree %d %d Out of inodesbad countno fsMemory = %l.%l K @x@y&BX'C0B !3$-"c$:"P @"!5X'C #4  X" "4""@m@ >pcore J   J |#`{}@~ABCDEFGHIJKLMNOPQRSTUVWXYZ2<@V({)}!|^~'`@Sp %x Psw %x %x Display consoleR0123456789ABCDEFpanic: %s %s on dev %l/%l errbn %l st %x %x swap errorno procs +$)>)>)>)>)>)>)>)))))>)))>+>+D+JUseg = %x PSW = %x %x SP = %x trap type %d trap,1f5  ( 3@ ~ >,?<@@57 \>9;2=0=x<x+7+@@+>`>FBL<++9>tBCH+==AZ+++++++++++++++74747474747@7@7@747474747d7@7r7:out of swapunlink -- igetout of swap spaceswap errorout of textout of swap space_0_0xkl`mydz4zvzz_0_0jk_0_0_0F_x_0x~xxkl`slstH `HHI `I<IhIno file no imtInode table overflow XXQ$QXX[ #'[#!4!4/$X]$X]XXXX'!#&! blkdevdevtaboqopp|pp#0!8}}}}}}p$Ї$PX7$$0(XG( @A`@BЁJQӅ&&RӈXXrP   X 88 X $#$@ C$#$@8 sÐB0xÐ@C0*&&R4sC0fݍpZM怀4#6ݍVZM @A`@BlC HF#3C^&&RXʟC @A`@B*C H#3CCC0C0$C$ C'#$CLчp$XPCXXC!&C ! %C#&C  /CX#6B4C4C06B&"9!!$#&#&PC(&"X";X"9 !C@#!G@B0#@C0@<#6ʠ Cx&< 7BC^XP&& CXP&& C&XC>X"!F#Ǡ&C0" XXC0!&PPC&PPC"XXPPCXXPP&&` CXXPP&&` C%&BCz&CC08%B"< B@C.C0DB!9B"  BCX#XB,&CX#&C B0XU B0CBB0XUBB0CXX# XXXXP44 C0B&CPxC%P6W>C(X& #' #:VC0xCC0" X #& C0XІ!6BCBBCC0fC^XB|CjP!B0>C8XxPnC!&CX0BCCfXXC0XXC0 !C@,#B@&@C0&@B0>&# @C0@ BB #& #& #&XPC0ÀB0 :X.CÀ#3'#B"  CXCH  #& #&İ CT&CNXCCXC0HXXXC0b !C@*#B@$@B0$@C0&# @B0@ B*B0B B0CP #' !B0"B0B0.Đ BB0CCX!7ÀB0^C ÀC0'dXXB:C(CHXfubyte"fuibyte"fuword"fuiword"subyte",suibyte",suword"Dsuiword"Dcopyin"bcopyout"vclearseg"copyseg"lraddr"lra"savu"Tretu"baretu"incupc"spl"ss"oc" wd"wh"wdh"(rd"6rh">rdh"Fidle"Tiinit"`bdevsw#bread"_tgetblk"cpanic"bcopy"_Dbrelse"amount$time$alloc">getfs"sleep"badblock"wakeup" clrbuf"eprdev"^free"bwrite"`printf"putchar#ialloc"Viget"Kiput"Minode$ifree"\update"Hupdlock$iupdat"N^prele"wbflush"gcntladdr#hdskaddr#lrdskbuf$hdsktab$dsk$dskscq#tdskstart"dskscint"dskstrat"xiodone"eselchreq"`dskerror"dsknrdy"Ntimeout"Xselchfre"selchadd# deverror"dskread"physio"h|dskwrite"Fmaxmem$freemem$coremap$Tmfree"Zmin"Yswapmap$clkstart#cinit"binit"frootdir$tnewproc"%expand"'estabur"sched"!sureg"nseg"malloc"display#csw$selchtab$ipc$signal"Hpsignal"setrun"!issig"stop"Pprocxmt"exit"1psig"grow"`core"schar"Udnamei"Qmaknode"Paccess"Iitrunc"Oxwritei"Wptrace"xregloc#@read"rdwr" (write" getf"Greadp"u|writep"vLreadi"Udpadd#open" (uchar"Uopen1" creat" ~falloc"KZopeni"Iclose" closef"Hseek" \link" suser"Jwdir"Qrmknod"sslep"dpcmp#tout$maptab#cfree$cfreelis$Dgtty"@sgtty" stty"cdevsw#wflushtt"|flushtty"Bnchrdev$ʨgetc"~canon"canonb$Tputc"Fttyinput"ttyoutpu"2ttstart"partab#tmax"Yttrstrt"zttread"passc"]ttwrite":cpass"^ttystty"callout$lbolt$setpri"!curpri$ runin$trbuff#0cputype$xexecnt$|file$text$mpid$runout$rablock$buf$uregs#eregs#\panicstr$ʜprintn"xswap"Cswap"ffptrap#sysent#trap1"+nosys"+nullsys",rexit"1ffork"5wait"3@unlink">exec",chdir"?gtime"smount"9sumount";2setuid"=0getuid"=xstime"`sync">Fkill"BLgetswit"pipe"ttimes"Bprofil"CHsetgid"=getgid"=ssig"AZxfree"Dxalloc"ENinstrlen"7stat1"8C@4T@1e!4AL#A@ # @4T#6A@ C юp(p0Ї@4T@1d!3$#$P@1hAA@ X@4X&P 'tX@4\[ PX@8H&PX PA@&tP@8LX@8LU@#)@PA@0X@1l#4A@ p$PA@PXPA:A@ %Q@4DXHPA@юp0p(Ї$Q@4DA@ X@4X&P@4\$X@4X@X@4X@юp(p,Ї X@4XH&@ B@4T@1e!5$Q@4PX@4\&P@4\$X@4\&P@4\X@4X&PXH#8XHQ" X@4\[X@$X@4\&P@4\X@4\&P@4\ю p,p(ЇX(X @8H@HX @8H@X@8H$@юp(p,Ї 'tX,PA@t&tPA@PB0&@PA(P!9@PA@0X#ю$- &C#4 # #ю p,p(Ї$A@t#5 #2"юp(p(Ї$PA@J &@4T#5A@ " юp(p(Ї$PAC @X@@ $C .H ! & #J"& &@4T#5A@ " юp(p(Ї$PA@$PA@H PA@  J P't$PA@t&tPA@ юp(p(Ї@1tP't$PA@t&tPA@VC06A@ DX@4HC &X(!5A@ D# X@8HHPA@Fюp(p(Ї$$PA@t&#3&"PSO" export(I), import(I) .sh BUGS Doesn't know about "Dynamic OS/MT" directory format. 1Trevptr"dnl"quote":result"list"zbindec"getc"ftoa"fout#2write"putc"pread"Xerrno$@(#N##"//&&&(()$)((*X*****))+6+6++6+6+6+6+6+6)))))*:5@5h5H5h5P5h5X5h5`%.33s %5d %s0123456789ABCDEF0123456789ABCDEFCDEFLOSXcdeflosx67,777866767,77786676) 0Aюp(p,Ї $PA@tC06$C,$PA@t @1`!6 @1`&Cю p,p0Ї%PA@ X@@ PA@F$PA@t$PAP $PA@t!4#$PAPX CX 'Q$P %Q C #3&" X'PC B &X@@$&P@@$C08X@@$U@#)@PA@0CX@@$&P@@$$юp0C@"p(Ї@@,PA@#$# #юp(p(Ї,X( C0ɠ%#8PA@HC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@B8$ɠ.B0,&ӡɠ9B ɠ0B$ CP@B<'tPX PPA&t!&&C<юp(p(ЇX,B`X(C'X( %P(C #4'C #3&"C' 0  9C'@1x  ;C # [,'$$0 $$ ?X,CX(d#6X(D!6'- CbB@'xX(P X@B'tP & PX PA@X&t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@&t !$%C& & P P X$ тЁB ( Cx~xAȀ?A$AC0ɀ-!7PЁD" ҋV&C$ҋJAɠ>C0:A搀ʐ@Ѓ* "?$ӉKԋ <& 8s, #4A"s&$A˰ $Xŀ!9$X P& xH~@xP~PP] XĀŀA!ŀZ!#ƀ A ŀ ?$P~&QPtX] ATfc$ADXC &A2DBB ҁ&" &>A 'Cʝ"3` th * dskstart(), which will operate at a lower interrupt level. */ dsknrdy(dp) struct dsk *dp; { dp->d_active = 0; if (dsktab.d_active == 0) selchreq(NSELCH, &dskscq); } /* * Disk interrupt routine * - disk interrupts only after a seek * - status will be checked by dskstart() when controller is free */ dskintr(dev, stat) { register struct dsk *dp; trace(4<<16, "interrupt", dev); trace(4<<16, "status", stat); dp = devmap(dev); if (dp->d_active != DSEEK) return; dp->d_active = 0; dp->dk_cyl = dp->dk_actf->b_cyl; if (!dsktab.d_active) selchreq(NSELCH, &dskscq); } /* * Selch interrupt routine * - selch interrupt will be followed by a controller interrupt * (unless OVERRUN status is set) */ dskscintr(dev, stat) { register struct dsk *dp; if (!(dp = dsktab.d_actf)) return; oc(selchaddr[NSELCH], STOP); if ((stat = ss(cntladdr)) & OVERRUN) { dskerror(dp, stat, cntladdr); dsktab.d_active = dp->d_active = 0; dskstart(); } } /* * Disk controller interrupt routine * - ch.th EXPORT I 8/12/77 .sh NAME export - copy a file to an Interdata OS/MT disc .sh SYNOPSIS export device file [ recl ] .sh DESCRIPTION Copies the specified file onto the device, which must contain an Interdata OS file system. The OS filename is formed by translating the UNIX filename to uppercase, and taking any characters after the last period as an extension. (Name and extension are truncated to 8 and 3 characters respectively.) The created file will be INDEXED, with a logical record length of .it recl (default 256). Note that .it export does not format the file into fixed-length records: .it recl is used only to initialize the OS directory entry. .sh AUTHOR R Miller .br University of Wollongong .sh "SEE ALSO" dfi(I), import(I) .sh BUGS The OS disc must contain at least one directory block. .br No check is made for already existing files. This may result in multiple OS files with the same name. .br There is no way to delete an OS file . .br Doesn't know about "Dynamic OS/MT" directory format. .th FERR I 8/12/77 .sh NAME ferr - Fortran error messages .sh SYNOPSIS ferr error-number ... .sh DESCRIPTION Prints the error message(s) associated with each specified Fortran error number. Includes both compile-time and run-time errors. .sh BUGS Error message text is copied from Interdata manuals. Messages are ambiguous, misleading, and sometimes dead wrong. PX PA@n&tXX$ $ X@< PA@q  PA@^# @mPA@Vю p,p,Ї A@OAP@mB04ܔCX #7XY C0&"@mCC(X C0XY !8@mCTX0Z4Z8&Y@B &$X0B  0P &Q0CX0C0 X00P &$X4B  P &Q4CX4C0" X4P &Z4#$P &"Z8X8B Q8' P CX8C0"[8' X8P A $#$ @m%#юp0p(ЇX(#юp(p(ЇX(X C0bX U,BPXX,Q X [,P B0mkdir doc mkdir doc/cdoc mkdir doc/cman mkdir doc/ctut mkdir doc/man mkdir doc/man/man1 mkdir doc/man/man2 mkdir doc/man/man4 mkdir doc/man/man5 mkdir doc/man/man8 mkdir source mkdir source/as mkdir source/boot mkdir source/c mkdir source/chicago mkdir source/cmds mkdir source/cref mkdir source/cref/index mkdir source/cref/src mkdir source/cref/tab mkdir source/etc mkdir source/fort mkdir source/liba mkdir source/libc mkdir source/lpd mkdir source/lpd_melb mkdir source/ratfor mkdir source/ratfor/lib mkdir source/ratfor/ratinc mkdir source/sno mkdir source/stdio mkdir source/stdio/pdp11 mkdir source/stdio/src mkdir source/troff mkdir source/troff/cmds mkdir source/troff/doc mkdir source/troff/eqn mkdir source/troff/fonts mkdir source/troff/macros mkdir source/troff/neqn mkdir source/troff/programs mkdir source/troff/tbl mkdir source/troff/terms mkdir source/troff/tests mkdir source/wgong mkdir source/yacc tp mx find doc -type d -a -exec chmod 775 {} ";" find source -type d -a -exec chmod 775 {} ";" X@PX@$X@Pюp(p(ЇA@SC00X@XP@ X@XP@$@(PA@dюp(p(ЇX@@p #6A@S#<@nX@t@pюp(p(Ї@pX@@nX@юp(p(ЇX@@q #6A@S#7@o@qюp(p(Ї@qX@@oX@юp(p(ЇX@tX X @Pюp(p(ЇA@Oюp(p(ЇX@X## #A@S!2$X@tюp(p(Ї$P@dPA@a0 C0PA@^X@PX PA@T !9@pPA@ X `@!7A@SC0HQ@@P@xP@|$P@PA@f '   PA@VPA@Vюp(p(Ї$P@dPA@a0 C0`X `@C0@mPA@VC8@PPA@RB0X@PA@VP@PA@^юp(p(ЇA@SC0PX P @n#9X@8P@8X X@8P  PA@Vюp(p(ЇA@SC06A@SC0*@; @:  .th PRESS I 8/12/77 .sh NAME press - compress a file .sh SYNOPSIS press [ - ] [ infile [ outfile ] ] .sh DESCRIPTION Compresses input file by replacing strings of 4 or more identical characters by a single character and a count. The '-' option expands a previously compressed file. Usable as a filter. Generally useless with UNIX text files, but saves space with "fixed-record-length" files (e.g. imported from Interdata) containing lots of blanks. .sh AUTHOR R Miller .br University of Wollongong &X P @X P @ C$PA@CA@CA@:Cx't$PA@&tHPA@CTA@zCJ@1tP't$PA&tPA@VP@1lCC4B0" 'C0A@mB,ҽ&"C  'C0 P&A@mD!"юp(p4ЇX4XP T8#9@m$CX4X B0%T8C0X PA@I!4$CX$PXC.XZ4XP&XZ4$P$QCX $X4PPA@pX4X P CX8Z4X B0@X PA@IC0,PA@pX$X8Z4PX4$P@lX8CX8Z4XP@l CX8PX#$$PXZ4XB0>X4X PA@I!4$C^X $X P PA8C$P X XPX XPX P PXPPX(P X,P $ #юp(p(ЇX($PA@!$T B0PPA@"$PA@!PANюp(p(ЇX($PA@!X XP X X PX P PA@!юp(p(ЇX('tP@P@PA@ &tX P T #7PACX P PA@pюp(p(ЇX(X$P &' 5юp(p,Ї @*P@*P@*P@* P@*$ɰC`0p%P CC"@  B0&CX#8XPA@q(X4B0$ B0PPA@RB0@ CHX PPA@VX@PXPA@U !4$CCPA@V$#юp0p(ЇX@&P@#юp(p(ЇX@&P@PA@ !6j@m #юp(p8ЇX8X@|C0  X ` B0 X PX@ACj% P@PA@P PX@PX@|P[PA<X ``C0j'xX@P X@PP P*X@XA B0X,PPA#PA. #юp(p(ЇX(XX xP P PX@XAB0PAPAC#8X P #PAHюp(p(ЇX(X@\+`#5*4!7PA"CX P PA6юp(p(ЇX(X P PAюp(p(ЇX(@T #6PA@p@T@*C0 X@*P@*@*PA@p$T #4% $PA@!T C0(*XPX P P@*P C$*XP X P PTP@*P X@*P X@*PP@*$P PA &C$@PPXXC0"XX  #5PP&QCP@Hю p,p(Ї)$T #:@T@)!4)$PA@!$T C0"X @P PPA@CX4P X@P X0P X(P $X,P P@X@XA$PA@!$T B0PPA@"@T #6PA@p$PA@!X P X #юp(p(Ї$PA@!X@**C0JT C06X(#7X(Y B0 X P PAP@*P X 7P PA@!юp(p(ЇX(*X@\X C0X $Y,!7X  !3 #XC$#юp(p(Ї'tX,P@P PA@ &tX(B*Y@H!@PA@ X(#*C*X@\ !9@PA@ X C0~X $Y,B0jX Y(B0^$PA@!$T C0.X @P PPA@$PA@!Cj$PA@!PAJ CXC|$PA@!X@**B08X@*@P@*P@*PA@$PA@!C$PA@!X@*PAT C0AFCX C$PA@!юp(p,Ї X0X@xB0$T@|B0 Z@| C X@HPX@T#4$PYBh Z@|XZ@L!ɰBH Z@|X@PC.$PA@!$T C0"X @P PPA@CX8P X4P PX@4P PA@ % P@PA@P $X@|P $ (X@tPX,A$PA@!$T B0PPA@"X@t@T #6PA@p$PA@!X P X ,P@|PA#j@mю orw; iodone(bp); dskstart(); } /* * Common error routine */ dskerror(dp, stat, dev) register struct dsk *dp; { register struct buf *bp; bp = dp->dk_actf; deverror(bp, stat, dev); if (++dp->d_errcnt > NDSKERR) { dp->d_errcnt = 0; bp->b_flags |= B_ERROR; dp->dk_actf = bp->av_forw; iodone(bp); } } /* * 'Raw' disk interface */ dskread(dev) { physio(dskstrategy, &rdskbuf, dev, B_READ); } dskwrite(dev) { physio(dskstrategy, &rdskbuf, dev, B_WRITE); } p,p(ЇX($T C0 (@m!5$@mюp(p(Ї+!$@mC+<*8X(P 8 0B0h$ 0X $!5P $# .@ /P (PAT't+@PA@"LP@PPA@ &tX@tX!6X@tPюp(p(Ї+<*8PA@$ 0P+@PA@" юp(p(Ї+<*8PA@jюp(p(Ї+<*8PA@юp(p(Ї+<*8X,PPA@X,B0 0 !5PA юp(p(ЇTPX(;@PA@" #юp(p(ЇX( 0 B0( 0" 0XP;@PA@" юp(p(ЇX( PA@| #PARCC 2 0 0't PP@PA@ L&tCX 0 0P;@PA@"*'t;@PA@"P@PPA@ &tюp(p(ЇX(<) 0C0 0 C0 T,C0L't$P@PPA@ &t 0 0PA8PPA@C 0C0<'tX,PL74L75L76L77L78L10007 L790ttrstrt":L.10(L80\L.11(L82L81ttread"L.12(L83L10008L84L85L86passc ttwrite"L.13(L87L88cpass L89L90,L91TL92TL93ttystty"subprograms go on 'blockdata'.f and 'blockdata'.o. The resulting ......o files are linked together onto a file called .it a.out . The following flags are interpreted by rc. .nf .ta 6 -c Suppress the loading phase of compilation, as does any error. -f Save FORTRAN intermediate files. Used for debugging only. -r RATFOR only; dont't try to compile the FORTRAN. -v Don't list intermediate file names while compiling. .fi EXAMPLES: .in +5 .nf rc test.r a.out The above will eck transfer status * - on cylinder overflow, restart I/O on next cylinder * - signal I/O done */ cntlintr(dev, stat) register int stat; { register struct dsk *dp; register struct buf *bp; register int resid; trace(4<<16, "interrupt", dev); trace(4<<16, "status", stat); dsktab.d_active = 0; if (!(dp = dsktab.d_actf) || dp->d_active != DIO) return; dp->d_active = 0; bp = dp->dk_actf; if (stat & CNTL_UNRCV) { dskerror(dp, stat, cntladdr); dp->dk_cyl = -1; /* force seek */ dskstart(); return; } /* cylinder overflow */ if ((stat & CYL_OV) == 0) bp->b_resid = 0; else { oc(selchaddr[NSELCH], STOP); resid = (rdh(selchaddr[NSELCH])-bp->b_addr+2) & ~0xff; bp->b_addr += resid; bp->b_bcount -= resid; bp->b_sector = 0; trace(1<<16, "cylov", bp->b_cyl); if (++bp->b_cyl < NDSKBLK/24) { dskstart(); return; } else { if ((bp->b_flags&(B_PHYS|B_READ)) != (B_PHYS|B_READ)) bp->b_flags |= B_ERROR; bp->b_resid = resid; } } dp->d_errcnt = 0; dp->dk_actf = bp->av_f@C6X@P@@CD$PX@XHB"X&PX,PA*#5XCXHQC$#ю p,p(ЇX(&P(X.,B0X,!4$C$Q,C$#юp(p,Ї 'tX,PA@t&tPAPC0 XC $Q@1pX%@ю p,p4ЇX@4HB X@@ HC(X@@ P@@$X@@ HQ@@ %Q@1pCX@1pC X@@$&P@@$'x P PX@@ PX@@$PA&xXP XHC0TXPXHB0X P'tXHPX PXPA.th MC I MAR/76 .sh NAME mc \*- filter which splits output into columns .sh SYNOPSIS .bd mc [+m] [-n] [file] .sh DESCRIPTION .bd mc reads from the standard input ( or "file" if the argument is given ) and writes to the standard output splitting as many lines as possible per line. "-n" sets the line width (default 80) and "+m" sets the number of blanks to be printed between input lines (default 2). .sh EXAMPLES ls ^ mc .br nm /net/caltech/unix | mc -130 | pr -h "Cal conf" | lpr .sh AUTHOR University of Toron&tP XHQCX $@'x@@$P @@ P@P@PA &xюp4p(ЇX($@X,HC0HX([,X,@X,P(Q,X,!X,U@#)@PA@0CX(X0PX,X4Pюp(p(ЇX0'P0C $X(&P(X.,&P,CX,#юp(p(ЇX@8L&P@8LX@8H[@8LX@8L@X@8LP@8H$Q@8L$Q@4Hюp(p(Ї'x$PA@tP @1bPX@4HP@PA@&x$ C PA@t!3'"$ B F'|@     !)!X@<юp(p(Ї$@1tP'tPA@t&tPA@V!8&B PC &PA@t''tH &PX@8H&PPA@&tP@8L@1TPA@Fюp(p(ЇX(C0#:;,$10123456789ABCDEFCDEFLOSXcdeflosx bb bbmain",exit"l_exit""metas#1`one#1trescan#1htracefla#1ltrashfla#1plp$4Dlg$4Hlq$4Ll9$4Pc$4Tpf$4Xpe$4\pmax#p0$4`gf$8Hge$8Lgmax#g0$8Pdf$@ de$@$dmax#d0#dummy#p@Ї $PAP $PAPX@CPA@ $Q@d$Q@P'tP$P@ސPA@`6&t&C'tX@d$PX@d$P@PA@ &t@*PA@ @>PA@ @lPA@ @ÛPA@ @òPA@ PX@dPA@hP@d'tX@PX@P@ PA@`6&tA@X@8XP@֜$P@֠$@ֈ@։@։@ֈP@tA@xA@uA@I $PX@PA@UP@X@$PX@PA@UP@X@A@C0P$ PA@'x$P $P$P$PA&x'tP$P@PA@ &t#A@юp(p(ЇX@tXX@tX #4XX@4@'B' T #3 # Z P Cюp(p0ЇXX0Z4Z8&Y@dB &$X0B  0P &Q0CX0C0 X00P &$X4B  P &Q4CX4C0" X4P &Z4#$P &"Z8X8B Q8' P CX8C0"[8' X8P A $#$ @m%#юp0p(ЇX(#юp(p(ЇX(X C0bX U,BPXX,Q X [,P B0&X P @X P @ B0*  @PPA@WzPA@X@hX @PX@8P@hX@t !7X@t$юp(p,Ї $PX@XX@tֈݐCj C0\ #6X B0N B0X Y B0<֬C 2@to .sh BUGS It should break on lines terminated by a :. This would allow ls dir1 dir2^mc to work. n#8@n B0$QX@4PPA@.$CX!5$@mю p,p(ЇC&X P&X@4PA@ Z$Q@4Cюp(p(ЇX@4P@X@8P@X@ B0& #7 B0  #%Pӽ$CɰBrX$PA@!  't$P$PPA@D&tC\'tXX P@dP$PA@ &tXX C0F B02'x$P X PPX PA@vn&xB0PZ & X'x$P X PPX PA@vn&xB0J'tX PX&$P@ PA@`6&tP  $ Cl@jPA@ ю p,p8ЇX@D!7@ֈP@D'tX4P@uP$PA@ &t@PA@!jX@֜PA@!x$@\X@D$P@D2ʰ$ݐ!ֈ B0& C0ӫɠ##ʠ #P@D'B0X@D!9P@DA@"jCX@DP@`'tX P@{P$PA@ &tX PA@!xA@] C0  @`PA@!$#юp8p8Ї$P $Q@PX@.th STAT II .sh NAME stat \*- get file status .sh SYNOPSIS .nf stat equ 18 svc stat dc name,buf .fi .s3 stat(name, buf) char *name; struct inode *buf; .fi .sh DESCRIPTION .it Name points to a null-terminated string naming a file; .it buf is the address of a 17(10) word buffer into which information is placed concerning the file. It is unnecessary to have any permissions at all with respect to the file, but all directories leading to the file must be readable. After .it stat, .it buf has the followingA`,B$Q$P $@!2$X'!3@!XXXXXXXX4"p(Ї'tX(P@ P$PA@ &t'tXXP@%P$PA@ &tXT!7X(P(0P@X(C>X@8XP@)PA@ 'tXXPXTP@4PA@ &tXLP@APA@ X(P@JPA@ @XPA@ $C@P0PA@B0C$C$C$C$@mXTPTX,İ?ddB0jXXPA@ ($QXPA@ ( #3?İ?d$YC&PA@ (P@4&CC.$YC$XXPA@ (P@4$QX&C't dP@]P$PA@ &tX@4P@X PA@#5$@m@mdC&@mC0XTPT@mP0Cf$CL$PX@tPA@.Cf$C,$C&$C C'B BX@PX@tPA@.A@#4A@nX@tPA@ юp(p(Ї$@@XPA@!jX(A$@юp(p(Їd@mюpP#$P@P" ֈݐC( !6X !3P X Y@PC0$CX !9@PA@ X@tP$ $   X P   X P X@PP X P $ 4C&X#6 & "XX C0 &  & X@&@PA@!jX P@tXXX PPP@ސPA@_PXB0N$ XP @`PA@!j't$P$PPA@D&t  $ C@CEFGOPHK12345689/0()*+,-.#$%&' HN T   p r yefgh o]_`ab_h00CC@ C@ @8 (000DLDLDLDLDLDLDLDLDLDLDLDLDLDLDLDL<[@LX@P& 'xX@TP X@PPX@L PX@HPA@]&xB0Q@L B NX@tX [@PPX@P 'C0P PA@ &"XPA@CRPA@X@tX X@P 'C0'P PA@ " '#8'PA@ " ю p,p(ЇX(PA@  CP$Cd$C^ &PA@ @!4$C@$C:C $C,C $CCB BX@юp(p(Ї$PA(юp(p(Ї$PA юp(p(ЇX(X@XPA@P C0 #/etc/initXA`BXA`Bs4sXA`BjX$XA`BRX@4@$XA`B4X'CXA`~B !XXG'DXDPD'D"$%X$ PB'$"X'(X0XCPC'4"$XWXX'A`P @mtstart"mtseek"mtcmds#plock"bselchtab$+syttyp"maptab#Ɣcfree$+cfreelis$2(sgtty"flushtty"canon"lttyoutpu"ttstart":partab#ǐvdubase# B0& #7 B0  #%Pӽ$CɰBrX$PA@!  't$P$PPA@D&tC\'tXX P@P$PA@&tXX C0F B02'x$P X PPX PA@vb&xB0PZ & X'x$P X PPX PA@vb&xB0J'tX PX&$P@ڀPA@`*&tP  $ Cl@PA@ ю p,p8ЇX@!7@P@'tX4P@!P$PA@&t@PA@!^X@PA@!l$@X@$P@2ʰ$! B0& C0ӫɠ##ʠ #P@'B0X@!9P@A@"^CX@P@'tX P@'P$PA@&tX PA@!lA@]v C0  @`PA@!$#юp8p8Ї$P $Q@X@#$P@Ǡ&B0*#4!'ǰ&&C&CB0&B" $PACVɐddddddrȒȖȖȖȖȖȖȒȖzzzzzzӴVȨȬȬȬȬȬȬȨȬɐɼː˖Rɐɰɼː˖R0\θVɐll0\θV̀͞  HLPTX\`d$(,048<h@Dlptx|(,048<@D Hstart" dump" @consaddr"xconscmd2"yproc$ֈtrmask"memtop"consdev" rootdev"swapdev"swplo"nswap"kisa0"uisa0"kisa"0uisa"4ka6"8ksp"X@8XP@PA@ 'tXXPXTP@PA@ &tXLP@PA@ X(P@PA@ @PA@ $C@P0PA@pB0C$C$C$C$@mXTPTX,İ?B0jXXPA@ ڀPA@_ !9@PPA@ PX@PA@rP'tPX P@PA@n&tPA@p X@t'tX PX P@PA@`*&tP$ CrX Y B0^@ PA@dPA@dC.X Y B0$P  !6PA@ʰ$CA@`ʰ$C$P Ctюp(p(Ї$CX@tX YB0l& B0X X@PXPX@PA@n'tP$P@ڀPA@`*&t$ $P $P $ $P $ XX Q@X P@PA@0X юp(pDЇ$$P@dPA@a0 C0X@B%P@PA@C$Q@%PA@rPP@PPA@RB0XX$P$PX@8PA@ P C0h$QX C0D$Q@8X &P PA@ C0&$QX#'$@mC #3CC~$TC0$ &$Q" @4P@xP@|$P@$P@$@lPA@e$@l@mB0$PX@4B0X@8Q@<$P@8C.X@4 !6$QCX@4#7$@mC.X@8C0$ B0 $QXPA@  #3?İ?$YC&PA@ P@4&CC.$YC$XXPA@ P@4$QX&C't P@ P$PA@&tX@4P@X PA@#5$@m@mdC&@mC0XTPT@mP0Cf$CL$PX@tPA@"Cf$C,$C&$C C'B BX@PX@tPA@"A@#4A@bX@tPA@юp(p(Ї$@@XPA@!^X(A$@юp(p(Їd@mюp(p(ЇP@PA@0X Q@X P@PA@0X P@PA@0X 4X@PPA@qC B0T  B02  X X@P X@PCH  PA@ʰ$Cp C0(PX@tPA@CH$ @mюp(p(ЇX@tC C0$" $ @mC\A@C0BX X@P$P@$P@$P@$P@$P@$P@C*X X@PX@X(PARX@Q(юp(p,Ї X@4X@T!;X@HPA@_  #$&A@ 6& ?C%PX &PA@ NX@tB0DT C0$@nC0 @n X@tT #6 @ohC$T !4$P &" X@XP 8xCX&Z@$P"X X@PX@$P(h#$P &"PA@VXPA@qX@!@PA@d%Q@ю$pDp(ЇX@XP@4A юp(p(ЇX@th#$P &"4CX#9$P PA@Q&CX@PA@VA@E$P@#8@mCX@8PX@=100 is OK) 84-85 100 register save area .DE .pp "Loading uboot From Magtape" .lp +6 4 1. Set up '50 sequence' low-core definitions as described below. .ti -4 2. Mount the tape containing the .it uboot image on drive\ 0. .ti -4 3. Execute at location x'30' (DTA 30 ADD RUN). The tape moves and a `?' prompt should appear on the console. .ti -4 4. Follow steps 4-8 as for disk. .i0 .pp "Low-Core Initialization for Tape Boot" .DS 13 .ul 1 Address Value Meaning 30-33 0000 0050 illegal instruction new PSW 50-53 D500 0300 al x'300' load from tape 54-57 4300 0080 b x'80' branch to loaded program 78 85 magtape address 79 A1 magtape read command 7A-7D as for disk boot 7E 10 console address (copied to x'78' by \fIuboot\fR) 7f 38 PALS `command 2' to initialize console 80-85 as for disk boot .DE .pp "How it Works" The .it uboot program has been copied onto the disk (after the swap area) by the .it mkboot command. .it mkboot also initialized block\ 0 of the disk to look like an OS/MT `volume descriptor', which the LSU uses to locate the .it uboot image. If either of these areas has been corrupted, the LSU operation will fail and no `?' prompt will appear; .it uboot must then be loaded from a backup disk or magtape. Once loaded, .it uboot relocates itself to address x'20000', reads a filename from the console, and searches for the file in the root directory. If a disk I/0 error occurs, .it uboot goes into a one-instruction loop; if the file is not found, it repeats the `?' prompt. Otherwise, the file is read into core at address\ 0 (skipping the .it a.out header), and executed beginning at x'60'. .pp "Alternate System Devices" In case of hardware or other problems, UNIX can be loaded from a removable backup disk or with a different console tty, by changing the low-core device definitions. Once the system is loaded, it may also B0$QX@4PPA@"$CX!5$@mю p,p(ЇC&X P&X@4PA@ N$Q@4Cюp(p(ЇX@4P@X@8P@X@ B0*  @ PPA@WnPA@^X@hX @PX@8P@hX@t !7X@t$юp(p,Ї $PX@XX@tCj C0\ #6X B0N B0X Y B0< C 2@n#8@n$#юp(p(Ї@n!3$#$@m$#юp(p(Ї$C"X@!9X@P C&C@m%#юp(p(ЇA#$CfC8 B0&P@ & $P $P  C&C@PA@ @m$#юp(p,Ї $CX,Y B0X0Y B0 C0"  PPA@C C0B4ܔC"X  B0X P,$P0Cp&C@PA@ &    C  !6 !2%QCX PA@qX PX PA@K>'CNPA@qX0XPX PA@K>X0$P%Q0CX P $ $P   юp0p(ЇX@XPA@L !4$C@  X(P $ @n @o PA #юp(p(ЇX(XP@C &&" P@|$@l@P@xX@PA@fX@PAюp(p(Ї$P@X@8X& U@C>PA@ $Q@$Q@'tP$P@PA@`*&t&C'tX@$PX@$P@PA@ &t@PA@ @PA@ @"swapdev"swplo"nswap"kisa0"kisaeuisa0"kisa"0uisa"4ka6"8ksp"vdubase#vdu$,Pvdustart"pvduenab"vdudisab"+6fork".read"1xwrite"1open"2close"4wait"-creat"3 link"6unlink"?exec"%chdir"@gtime"=mknod"7 chmod"A8chown"Asbreak"/stat"9seek"4getpid"?Bsmount":sumount"Tgetuid">stime">fstat"8smdate"Astty"gtty"nice"?sslep"7sync"?jkill"Cpgetswit"=dup":bpipe"Htimes"D"profil"Dlsetgid">getgid"?ssig"B~uchar"dgetblk"rPreadi"exfree"Exalloc"Fbrelse"qclosef"Qbcopy"nbwrite"p bread"ndpadd#0instrlen"0nseg"_rdwr"1getf"Preadp"writep"open1"3prele"^falloc"Tjopeni"R*suser"Swdir"Zdpcmp#Fstat1"9`iupdat"Wnldiv#|lrem#ufalloc"Tgetmdev"=ialloc"Lifree"Nbflush"wvnulldev"nldskstrat"zdsktab$$mtopen"mtclose"Hmtstrate"mtab$%msmstrat"msmtab$%cdevsw#0vduopen"vduclose"ttstart"fL.9,L10005L470L48JL51,L49C(X& #' #:VC0xCC0" X #& C0XXCH  #& #&İ CT&CNXCCXC0HXXXC0b !C@*#B@$@B0$@C0&# @B0@ B*B0B B0CP #' !B0"B0B0.Đ BB0CCX!7ÀB0^C ÀC0'dXXB:C(CHX!F#Ǡ&C0" XXC0!&PPC&PPC"XXPPC!6BCBBCC0fC^XB|CjP!B0>C8XxPnC!&CX0BCCfXXC0XXC0 !C@,#B@&@C0&@B0>&# @C0@ BB #& #& #&XPC0ÀB0 :X.CÀ#3'#B"  CC0@BCǠ&C8 XX4Ġˠ@C X'B @Ǡ&B0*#4!'ǰ&&C&CB0&B" $PACVĀҀFڀͶ  TIJf\TIJf0Fǐȼ&ʶH̀ǐȼ&ʶHC0$C$ C'#$CLчp$XPCXXC!&C ! %C#&C  /CX#6B4C4C06B&"9!!$#&#&PC(&"X";X"9 !C@#!G@B0#@C0@<#6ʠ Cx&< 7BC^XP&& CXP&& C&XC>X"X,!5PA`юp(p(ЇX(X8Z@&'tP@P PA@&t 0B0 PA@(BC 2 0 0't PP@PA@ @&tCP 0 0 @PPA@"'tPA@" P@P@PA@&tюp(p(ЇX([@<,P 0C0Z'tX(P@P@PA@&t'tX,P@P@PA@&tX$PA@!PA@(!"$ ,PA@!юp(p,Ї X,$PA@! ,B0$ 0!4$C$ PPA@C$PA@!PA@(Bɰ!8 ,' ,C T $B0n @\C0, . !8#"'C / C0ɰC0C4 @C0( @ #6$T $C0 @\#4ӻ@'ҽ&#CPP&UCP P&A@"$#ю p,p(ЇX,X(X$ !5#2$ B08#5B0*!5$P#$PPA@ PACX !PAC(PA@"@'tP@P@PA@&t$T,C06 0C0$PPA@ PA@ 0 0C 0B0 0 0PA@dCxB0 T $!9 0 0CVB0@ T $B04 0C0& 0 0 PA@dPA@#PPA@\юp(p(ЇX([@<,P 0C0'tX(P@P@PA@&t'tX,P@P@PA@&t 0 0PA@X X@,LB0XPA@!$CX P@,L$P $P &PCBðB0:ʠX@,LB0XPA@!$C8X P@,L$P &P&P$Q XPA@!$#ю p,X!"4""@@8e$C@ $@P" X7e4XT@?p,Ї PPP7A@ ч p,%s %x @Sp %x Psw %x %x Display console :0123456789ABCDEFpanic: %s %s on dev %l/%l errbn %l st %x %x @x@y&BX'C0B !3$-"c$:"P @0"!5X'C #4  X" "4""@m@PPPPPP~PPP.h2Hcoresswapswap errorswtchretuno procs $"""""""#h#n##"##"%%%trappswUseg = %x PSW = %x %x SP = %x trap type %d trapsvc%+6.1x124-3 6?%@=7 A8A/94?B:T>> %8%A%?7?jCp=%%:bHD"Dl%>?B~%%%%%%%%%%%%%%%1111111111111411B1 out of swap55555unlink -- igetxswapout of swap spaceswap errorout of textout of swap spaceiinitno spacebad blockOut of inodesbad countno fsnlnlz$H%nlnl%*nlnljnlnlnl2pnN$nlH TnNnNnNnNnN\nNrnlnl8vnN `QQR `RLRxRno file no imtInode table overflow XXQ$QXX[ #'[#!4!4/$X]$X]XXXX'!#&! Memory = %l.%l K RESTRICTED@PA@"'tX@%hP@*PPA@&t'tX@%lP@3PPA@&tX@%hP@PA@"2X@%lP@PA@"2X@%`PX@%XPA@"(PX@%XPA@"X@PA@" !2" X@%dPX@PA@"X@%` Z@%\PX@PA@"(X@%`PX@%XPA@"(PX@%XPA@"X@PA@" !2" PX@PA@"P@PA@"юp(p(ЇHP@PA@"юp(p(Ї'tX(P@:PPA@&t'tX,P@DPPA@&tX@% C0X@%pB0T,C08$PX@PA@"'tX@PX,PPAP&tC@$P ,T,C0$PX@PA@"HP@PA@"@PA@"P[@%h&Q@%h'tX@%hP@KPPA@&t$P@%`P@%dX@%l[@%hP ,X@%\&P@%\X,Z, #AC`CX #7X P $@%$@%X P@% X@%tP@%tPA@t$PA@2Atюp(p(ЇX('tX0PX,PPA@ &t@%&@% !%ACN.th ATTACH VIII .sh NAME attach - logically connect terminals .sh SYNOPSIS /etc/attach ttyid ... .sh DESCRIPTION .it attach starts a .it login process on the named terminals (single-character id's only) by changing the /etc/ttys file and sending a .it hangup signal to the .it init process. .sh FILES /etc/ttys .sh "SEE ALSO" ttys(V), init(VIII), detach(VIII) .th DETACH VIII .sh NAME detach - logically disconnect terminals .sh SYNOPSIS /etc/detach ttyid ... .sh DESCRIPTION .it detach logically disconnects the named terminals (single-character id's only) by changing the /etc/ttys file and sending a .it hangup signal to the .it init process. Any currently active shells will be terminated. .sh FILES /etc/ttys .sh "SEE ALSO" ttys(V), init(VIII), attach(VIII) .th MKBOOT VIII 8/12/77 .sh NAME mkboot - convert a.out file to LSU bootstrap image .sh SYNOPSIS mkboot [ -block ] file device .sh DESCRIPTION Reads .it file, which must be an executable a.out file, and copies it onto .it device beginning at block number .it block (default 9600) as an operating system image to be loaded by the LSU (loader storage unit). .it mkboot also writes an Interdata OS/MT 'volume descriptor' onto block 0 with a pointer to the bootstrap image. .sh DIAGNOSTICS .it mkboot reads the superblock of .it device before copying, and gives an error message if the target area would overlap the file system. .sh AUTHOR R Miller .br University of Wollongong UNIX Programmer's Reference Manual - nroff input for the 'Green Book' (UNIX Programmer's Manual) - only those entries which must be changed for the Interdata version and new commands See 'make' to run off copies .sp 10 .ce 99 .ul UNIX PROGRAMMER'S MANUAL .sp 3 .ul Sixth Edition .sp 10 .ul Appendix: University of Wollongong .ce 0 .th MISC "" 8/12/77 misc - other changes to Sixth Edition manual .sp .ti -5 SECTION I .br Minor differences exist in the following commands: .lp +8 8 file Doesn't recognize Interdata assembler source files. .lp +8 8 mail mail file is in /usr/mail/, not .mail .lp +8 8 nm New option: .br .it -h Print addresses in hexadecimal .lp +8 8 nroff Level 6 manual is obsolete - see "new blue book". .lp +8 8 od \c .it -a option displays Interdata assembler op-codes. .lp +8 8 opr \c .it destination operand is ignored. .lp +8 8 passwd if typed without arguments, promts for a new password for the current user. .it -e flag turns off echoing while the password is entered. .lp +8 8 tp \c .it -o option takes first filename argument as a file to be used instead of a tape drive. .io .sp .ul Not Implemented .br Commands marked with * are to be considered "coming soon". .ta 24 40 .nf *bc cdb - see ddt(I) db - see ddt(I) *dc eqn - see neqn(I) fortran - see fort(I) libr link man pfe rev roff - see nroff(I) spell troff - see troff(I) *typo .sp .ti -5 SECTION III .br .fi .it Only the following subroutines are available: .nf .ta 32 abort alloc, free atof atoi crypt ctime end, etext, edata getc,getw,fopen getpw getchar ldiv,lrem monitor perror printf putc, putw, fcreat, fflush putchar,flush qsort reset, setexit ttyn .sp monitor() requires an extra fifth argument, which must be 0 .sp .ti -5 SECTION VI .br .fi .it Only the following commands exist: .nf .ta 10 20 30 40 50 cal chess col quiz sno tbl units .sp .ti -5 SECTION VIII .br .fi The dpd command requires hardware which we don't have! : loop if $1x = x exit nroff -mm $1 shift goto loop do title.nr misc.0 chdir man1;../do *.1 chdir ../man2;../do *.2 chdir ../man4;../do *.4 chdir ../man5;../do *.5 chdir ../man8;../do *.8 C Reference Manual, by Dennis Ritchie - revised for Interdata version - requires special Carousel terminal table (or postprocessing) because of subscripts/superscripts generating half-line motions To run: tbl cman? | neqn | nroff -ms -Tcar .fp 3 G .TL C Reference Manual .AU Dennis M. Ritchie .AI .MH .sp May 1, 1977 .PP .so manmacs .EQ delim $$ .EN .FS .nh Revised June, 1978 by R. Miller, University of Wollongong. .hy .FE .SH .ti 0 1. Introduction .LP C is a computer language which offers a rich selection of operators and data types and the ability to impose useful structure on both control flow and data. All the basic operations and data objects are close to those actually implemented by most real computers, so that a very efficient implementation is possible, but the design is not tied to any particular machine and with a little care it is possible to write easily portable programs. .PP This manual describes the current version of the C language as it exists on the \*(pd, the Honeywell 6000, the \s8IBM\s10 System/370, .MC and the \*I 16-bit and 32-bit series. .mc Where differences exist, it concentrates on the \*(pd .MC and \*I, .mc but tries to point out implementation-dependent details. With few exceptions, these dependencies follow directly from the underlying properties of the hardware; the various compilers are generally quite compatible. .bp .SH 2. Lexical conventions .LP Blanks, tabs, newlines, and comments as described below are ignored except as they serve to separate tokens. Some space is required to separate otherwise adjacent identifiers, keywords, and constants. .PP If the input stream has been parsed into tokens up to a given character, the next token is taken to include the longest string of characters which could possibly constitute a token. .SH 2.1 Comments .LP The characters .Bd /\** introduce a comment, which terminates with the characters .Bd \**/ "" . Comments do not nest. .SH 2.2 Identifiers (Names) .LP An identifier is a sequence of letters and digits; the first character must be alphabetic. The underscore `\(ru' counts as alphabetic. Upper and lower case letters are considered different. .MC No more than the first eight characters are significant (although more may be used). External identifiers, which are used by various assemblers and loaders, are more restricted: .TS center; l l . DEC \*(pd 7 characters, 2 cases Honeywell 6000 6 characters, 1 case IBM 360/370 7 characters, 1 case \*I \*(I2 8 characters, 2 cases \*I \*(I1 6 characters, 1 case .TE .mc .SH 2.3 Keywords .LP The following identifiers are reserved for use as keywords, and may not be used otherwise: .DS L .TS center; LfG LfG LfG . int extern else char register for float typedef do double static while struct goto switch union return case long sizeof default short break entry unsigned continue auto if .TE .DE The .Bd entry keyword is not currently implemented by any compiler but is reserved for future use. Some implementations also reserve the words .Bd fortran .MC and .Bd asm. .mc .SH 2.4 Constants .LP There are several kinds of constants, .MC as described below. Hardware differences between implementations are summarized in \(sc2.6. .mc .SH 2.4.1 Integer constants .LP An integer constant consisting of a sequence of digits is taken to be octal if it begins with \fG0\fR (digit zero), decimal otherwise. The digits \fG8\fR and \fG9\fR have octal value 10 and 11 respectively. A sequence of digits preceded by .Bd 0x or .Bd 0X (digit zero) is taken to be a hexadecimal integer. The hexadecimal digits include .Bd a or .Bd A through .Bd f or .Bd F with values 10 through 15. A decimal constant whose value exceeds the largest .MC signed machine integer is taken to be .mc .Bd long "" ; an octal or hex constant which exceeds the largest unsigned machine integer .MC is likewise taken to be .mc .Bd long. .SH 2.4.2 Explicit long constants .LP A decimal, octal, or hexadecimal integer constant immediately followed by .Bd l (letter ell) or .Bd L .MC is a long constant. As discussed below, on some machines .mc integer and long values may be considered identical. .SH 2.4.3 Character constants .LP A character constant is a sequence of characters enclosed in single quotes .Bd \|\(aa ` '. Within a character constant a single quote must be preceded by a backslash `\e'. Certain non-gra   phic characters, and `\e' itself, may be escaped according to the following table: .DS L .TS center; L L . \s8BS\s10 \eb \s8NL (LF)\s10 \en \s8CR\s10 \er \s8HT\s10 \et \s8FF\s10 \ef \fIddd\fR \e\fIddd\fR \e \e\e .TE .DE The escape `\e\fIddd\|\fR' consists of the backslash followed by 1, 2, or 3 octal digits which are taken to specify the value of the desired character. A special case of this construction is `\e0' (not followed by a digit) which indicates the character .SM NUL. .NL If the character following a backslash is not one of those specified, the backslash vanishes. .PP The value of a single-character constant is the numerical value of the .MC character in the machine's character set (\s8ASCII\s10 for the \*I and \*(pd). .mc On the \*(pd at most two characters are permitted in a character constant and the second character of a pair is stored in the high-order byte of the integer value. .MC On the \*I up to two (\*(I1) or four (\*(I2) characters are permitted, and are stored right-justified in a word. .mc Character constants with more than one character are inherently machine-dependent and should be avoided. .SH 2.4.4 Floating constants .LP A floating constant consists of an integer part, a decimal point, a fraction part, an .Bd e or .Bd E, and an optionally signed integer exponent. The integer and fraction parts both consist of a sequence of digits. Either the integer part or the fraction part (not both) may be missing; either the decimal point or the \fGe\fR and the exponent (not both) may be missing. &"9!!$#&#&PC(&"X";X"9 !C@#!G@B0#@C0@<#6ʠ Cx&< 7BC^XP&& CXP&& C&XC>X"!F#Ǡ&C0" XXC0!&PPC&PPC"XXPPCXXPP&&` CXXPP&&` C%&BCz&CC08%B"< B@C.C0DEvery floating constant is taken to be double-precision. .SH 2.5 Strings .LP A string is a sequence of characters surrounded by double quotes `\|"\|'. A string has type `array of characters' and storage class `static' (see below) and is initialized with the given characters. The compiler places a null byte `\|\e0\|' at the end of each string so that programs which scan the string can find its end. In a string, the character `\|"\|' must be preceded by a `\e'\|; in addition, the same escapes as described for character constants may be used. Finally, a `\e' and an immediately following new-line are ignored. .PP All strings, even when written identically, are distinct. .ne 13 .SH 2.6 Hardware Characteristics .LP .TS c c c c c c c c c c c c l l l l l l . DEC Honeywell IBM \*I \*I \*(pd 6000 370 \*(I1 \*(I2 ASCII ASCII EBCDIC ASCII ASCII char 8 bits 9 bits 8 bits 8 bits 8 bits int 16 36 32 16 32 short 16 36 16 16 16 long 32 36 32 32 32 float 32 36 32 32 32 double 64 72 64 32 32 range $\(+-10 sup \(+-38$ $\(+-10 sup \(+-38$ $\(+-10 sup \(+-76$\ $\(+-10 sup \(+-76$ $\(+-10 sup \(+-76$ .TE .SH 3. Syntax notation .LP In the syntax notation used in this manual, syntactic categories are indicated by .MC \fIunderlining\fR, and literal words and characters in \fGbold\fR type. .mc Alternatives are listed on separate lines. An optional terminal or non-terminal symbol is indicated by the subscript `opt,' so that .SY { expression\*(op } .ES would indicate an optional expression in braces. The complete syntax is given i!&CX0BCCfXXC0XXC0 !C@,#B@&@C0&@B0>&# @C0@ BB #& #& #&XPC0ÀB0 :X.CÀ#3'#B"  CXCH  #& #&İ CT&CNXCCXC0HXXXC0b !C@*#B@$@B0$agbaese.2aese.2abgaNaese.54fxrbfxrzerofxrovffxr.1fxr.2fxrstorefxr.2afxr.6fxr.5flr.1flr.2flr.3flr.4 ld normlizeld.506stmdHstpd:stadJstzdVstd\lmdplmd.10pstmd.00stmd.10overfldunderfldn \(sc16, in the notation of YACC. .SH 4. What's in a Name? .LP C bases the interpretation of an identifier upon two attributes of the identifier: its .It "storage class" and its .It type. The storage class determines the location and lifetime of the storage associated with an identifier; the type determines the meaning of the values found in the identifier's storage. .PP There are four declarable storage classes: automatic, static, external, and register. Automatic variables are local to each invocation of a block, and are discarded upon exit from the block; static variables are local to a block, but retain their values upon reentry to a block even after control has left the block; external variables exist and retain their values throughout the execution of the entire program, and may be used for communication between functions, even separately compiled functions. Register variables are (if possible) stored in the fast registers of the machine; like automatic variables they are local to each block and disappear on exit from the block. .PP C supports several fundamental types of objects: .PP Objects declared as characters .Bd (char) are large enough to store any member of the implementation's character set, and if a genuine character is stored in a character variable, its value is equivalent to the integer code for that character. Other quantities may be stored into character variables, but .MC the implementation is machine-dependent. .mc .PP Up to three sizes of integer, declared .Bd "short int," .Bd int, and .Bd "long int" are available. Longer integers provide no less storage than shorter ones, but the implementation may make either short integers, or long integers, or both equivalent to plain integers. `Plain' integers have the natural size suggested by the host machine architecture; the other sizes are provided to meet special needs. On the \*(pd and \*I, .MC integers are represented in 2's complement notation. .mc .PP Unsigned integers, declared .Bd unsigned, obey the laws of arithmetic modulo $2 sup n$ where $n$ is the number of bits in the representation. .MC On the \*I and \*(pd, long and short unsigned quantities are not supported. .mc .PP Single precision floating point (\fGfloat\fR) .MC and double-precision floating-point (\fGdouble\fR) quantities are available. The \*I implementations currently make .mc .Bd float and .Bd double synonymous. .PP Because objects of these types can usefully be interpreted as numbers, they will be referred to as .It arithmetic types. Types .Bd char and .Bd int of all sizes will collectively be called .It integral types. .Bd Float and .Bd double will collectively be called .It floating types. .PP Besides the fundamental arithmetic types there is a conceptually infinite class of derived types constructed from the fundamental types in the following ways: .IP .It arrays of objects of most types; .IP .It functions which return objects of a given type; .IP .It pointers to objects of a given type; .IP .It structures containing a sequence of objects of various types; .IP .It unions capable of containing any one of several objects of various types. .LP In general these methods of constructing objects can be applied recursively. .SH 5. Objects and lvalues .LP An .It object is a manipulatable region of storage; an .It lvalue is an expression referring to an object. An obvious example of an lvalue expression is an identifier. There are operators which yield lvalues: for example, if E is an expression of pointer type, then \**E is an lvalue expression referring to the object to which E points. The name `lvalue' comes from the assignment expression `$E1@=@E2$' in which the left operand E1 must be an lvalue expression. The discussion of each operator below indicates whether it expects lvalue operands and whether it yields an lvalue. .SH 6. Conversions .LP A number of operators may, depending on their operands, cause conversion of the value of an operand from one type to another. This section explains the result to be expected from such conversions. \(sc6.6 summarizes the conversions demanded by most ordinary operators; it will be supplemented as required by the discussion of each operator. .SH 6.1 Characters and integers .LP A character or a short integer may be used wherever an integer may be used. In all cases the value is converted to an integer. Conversion of a short integer always involves sign extension; short integers are signed quantities. Whether or not sign-extension occurs for characters is machine dependent, but it is guaranteed that a member of the standard character set is non-negative. On the \*(pd, character variables range in value from \-128 to 127; a character constant specified using an octal escape also suffers sign extension and may appear negative, for example .MC \|\(aa\|\e377\(aa\| when converted to an integer becomes -1. .mc .PP When a longer integer is converted to a shorter or to a .Bd char, it is truncated on the left. .SH 6.2 Float and double .LP All floating arithmetic in C is carried out in double-precision; whenever a \fGfloat\fR appears in an expression it is B!9B"  BCX#XB,&CX#&C B0XU B0CBB0XUBB0CXX# XXXXP44 C0B&CPxC%P6W>C(X& #' #:VC0xCC0" X #& C0XІ!6BCBBCC0fC^XB|CjP!B0>C8XxPnClengthened to \fGdouble\fR by zero-padding its fraction. When a \fGdouble\fR must be converted to \fGfloat\fR, for example by an assignment, the \fGdouble\fR is rounded before truncation to \fGfloat\fR length. .SH 6.3 Floating and integral .LP Conversions of floating values to integral type .MC tend to be rather machine-dependent; in particular, the direction of truncation of negative numbers varies from machine to machine. .mc The result is undefined if the value will not fit in the space provided. .PP Conversions of integral values to floating type are well behaved. Some loss of precision occurs if the destination lacks sufficient bits. .SH 6.4 Pointers and integers .LP An integer or long integer may be added to or subtracted from a pointer; in such a case the first is converted as specified in the discussion of the addition operator. .PP Two pointers to objects of the same type may be subtracted; in this case the result is converted to an integer as specified in the discussion of the subtraction operator. .SH 6.5 Unsigned .LP Whenever an unsigned integer and a plain integer are combined, the plain integer is converted to unsigned and the result is unsigned. .MC The value is the least unsigned integer congruent to the signed integer (modulo $2 sup wordsize$). In a 2's complement representation .mc this conversion is conceptual and there is no actual change in the bit pattern. .PP When an unsigned integer is converted to long, the value of the result is the same numerically as that of the unsigned integer. Thus the conversion amounts to padding with zeros on the left. .SH 6.6 Arithmetic conversions .LP A great many operators cause conversions and yield result types in a similar way. This pattern will be called the `usual arithmetic conversions.' .IP First, any operands of type .Bd char or .Bd short are converted to .Bd int, and any of type .Bd float are converted to .Bd double. .IP Then, if either operand is .Bd double, the other is converted to .Bd double and that is the type of the result. .IP Otherwise, if either operand is .Bd long, the other is converted to .Bd long and that is the type of the result. .IP Otherwise, if either operand is .Bd unsigned, the other is converted to .Bd unsigned and that is the type of the result. .IP Otherwise, both operands must be .Bd int, and that is the type of the result. .SH 7. Expressions .LP The precedence of expression operators is the same as the order of the major subsections of this section (highest precedence first). Thus the expressions referred to as the operands of \fG+\fR (\(sc7.4) are those expressions defined in \(sc\(sc7.1-7.3. Within each subsection, the operators have the same precedence. Left- or right-associativity is specified in each subsection for the operators discussed therein. The precedence and associativity of all the expression operators is summarized in the collected grammar. .PP Otherwise the order of evaluation of expressions is undefined. In particular the compiler considers itself free to compute subexpressions in the order it believes most efficient, even if the subexpressions involve side effects. Expressions involving a commutative and associative operator may be rearranged arbitrarily, even in the presence of parentheses; to force a particular order of evaluation an explicit temporary must be used. .SH 7.1 Primary expressions .LP Primary expressions involving \fG.\fR\|, \fG\(mi>\fR, subscripting, and function calls group left to right. .SY primary-expression: \fIidentifier\fR \fIconstant\fR \fIstring\fR \fG(\fI expression \fG)\fR \fIprimary-expression\fG [\fI expression \fG]\fR \fIprimary-expression \fG( \fIexpression-list\*(op \fG) \fIprimary-lvalue \fG.\fI identifier\fR \fIprimary-expression \fG\(mi>\fI identifier\fR .ES .SY expression-list: expression expression-list \fG,\fI expression .ES An identifier is a primary expression, provided it has been suitably declared as discussed below. Its type is specified by its declaration. However, if the type of the identifier is `array of .\|.\|.', then the value of the identifier-expression is a pointer to the first object in the array, and the type of the expression is `pointer to .\|.\|.'. Moreover, an array identifier is not an lvalue expression. Likewise, an identifier which is declared `function returning .\|.\|.', when used except in the function-name position of a call, is converted to `pointer to function returning .\|.\|.'. .PP A decimal, octal, character, or floating constant is a primary expression. Its type may be .Bd int, .Bd long, or .Bd double depending on its form. .PP A string is a primary expression. Its type is originally `array of \fGchar\fR'; but following the same rule given above for identifiers, this is modified to `pointer to \fGchar\fR' and the result is a pointer to the first character in the string. (There is an exception in certain initializers; see \(sc8.6.) .PP A parenthesized expression is a primary expression whose type and value are identical to those of the unadorned expression. The presence of parentheses does not affect whether the expression is an lvalue. .PP A primary expression followed by an expression in square brackets is a primary expression. The intuitive meaning is that of a subscript. Usually, the primary expression has type `pointer to .\|.\|.', the subscript expression is \fGint\fR, and the type of the result is `\|.\|.\|.\|'. The expression `E1[E2]' is identical (by definition) to `\**\|(\|\|(\|E1\|)\|+\|(\|E2\|)\|\|)\|'. All the clues needed to understand this notation are contained in this section together with the discussions in \(sc\(sc 7.1, 7.2, and 7.4 on identifiers, \fG\**\fR, and \fG+\fR respectively; \(sc14.3 below summarizes the implications. .PP A function call is a primary expression followed by parentheses containing a possibly empty, comma-separated list of expressions which constitute the actual arguments to the function. The primary expression must be of type `function returning .\|.\|.', and the result of the function call is of type `\|.\|.\|.\|'. As indicated below, a hitherto unseen identifier followed immediately by a left parenthesis is contextually declared to represent a function returning an integer; thus in the most common case, integer-valued functions need not be declared. .PP Any actual arguments of type \fGfloat\fR are converted to \fGdouble\fR before the call; any of type \fGchar\fR or \fGshort\fR are co !"#$&'*+,7;<=>?@DEFGHKQRUVWXYZ[\]^_nverted to \fGint\fR. .PP In preparing for the call to a function, a copy is made of each actual parameter; thus, all argument-passing in C is strictly by value. A function may change the values of its formal parameters, but these changes cannot affect the values of the actual parameters. On the other hand, it is possible to pass a pointer on the understanding that the function may change the value of the object to which the pointer points. The order of evaluation of arguments is undefined by the language; take note that the various compilers differ. .PP Recursive calls to any function are permitted. .PP A primary expression followed by a dot followed by an identifier is an expression. The first expression must be an lvalue naming a structure or union, and the identifier must name a member of the structure or union. The result is an lvalue referring to the named member of the structure or union. .PP A primary expression followed by an arrow (built from a `\(mi' and a `>') followed by an identifier is an expre,mdFmd.04tmd.08md.06xmd.10md.75 md.12md.50 xmd.15md.20 md.30 md.40 6md.70 md.35 *statushmd.42 @md.43 Jmd.45 lmd.55 md.60 dd dd.70 ,dd.04 dd.08 .dd.06 dd.10 8dd.12 >dd.75 2dd.30 dd.20 xdd.40 dd.22 ~dd.35 dd.45 dd.80 :dd.50 dd.55 dd.60 fldr.00 Ffldr \fldr.20 fldr.10 pfxdr fxdr.30 fxdr.25 fxdr.20 fxdr.05 fxdr.07 fxdr.15 fxdr.08 fxdr.10 fxdr.6 "fxdr.17 lvHssion. The first expression must be a pointer to a structure or a union and the identifier must name a member of that structure or union. The result is an lvalue referring to the named member of the structure or union to which the pointer expression points. .PP Thus the expression `E1\(mi>MOS' is the same as `(\**E1)\fB.\fRMOS'. Structures and unions are discussed in \(sc8.5. The rules given here for the use of structures and unions are not enforced strictly, in order to allow an escape from the typing mechanism. See \(sc14.1. .SH 7.2 Unary operators .LP Expressions with unary operators group right-to-left. .SY unary-expression: \fG\**\fI expression\fR \fG&\fI lvalue\fR \fG\(mi\fI expression\fR \fG!\fI expression\fR \fG\*~\fI expression\fR ++ \fIlvalue\fR \fR\(mi\(mi\fI lvalue\fR \fIlvalue ++ \fIlvalue \(mi\(mi \fG( \fItype-name \fG) \fIexpression\fG \fGsizeof \fIexpression \fGsizeof ( \fItype-name \fG) .ES The unary \fG\**\fR operator means .It indirection: the expression must be a pointer, and the result is an lvalue referring to the object to which the expression points. If the type of the expression is `pointer to .\|.\|.', the type of the result is `\|.\|.\|.\|'. .PP The result of the unary \fG&\fR operator is a pointer to the object referred to by the lvalue. If the type of the lvalue is `\|.\|.\|.\|', the type of the result is `pointer to .\|.\|.'. .PP The result of the unary .Bd \- operator is the negative of its operand. The usual arithmetic conversions are performed. The nega(,048<@D H)9)9)9@C0&# @B0@ B*B0B B0CP #' !B0"B0B0.Đ BB0CCX!7ÀB0^C ÀC0'dXXB:C(CHXrx3.2grtabLrx3.5 noindexrx1.1rx3.4noindx1rx3no1^dpfinaldnofaultsigfptetcreturnflt.iihcrasherrfreestecece.2ce.1stpsstmsce.3lele.2stm.stp2stz>le.4 underflo>\fR group left-to-right. Both perform the usual arithmetic conversions on their operands, each of which must be integral. Then the right operand is converted to .Bd int; the type of the result is that of the left operand. The result is undefined if the right operand is negative or larger than the number of bits in the object. .SY shift-expression: \fIexpression \fG<< \fIexpression\fR \fIexpression \fG>> \fIexpression\fR .ES The value of `E1<>E2' is E1 right-shifted E2 bit positions. The shift is guaranteed to be logical (0-fill) if E1 is .Bd unsigned; otherwise it may be (and is, on the \*(pd) arithmetic (fill by a copy of the sign bit). .SH 7.6 Relational operators .LPIiadcladcr0r1r2r3r4r5r6spr8rfargs masklabelvaluedtrace"trbuff tr.abl&tr.ablok:trmask tr.fmtvprintf fptrap.o~+tp$Ї$PX7$$0(XG( @A`@BЁJQӅ&&RӈXXrP   X 88 X $#$@ C$#$@8 sÐB0xÐ@C0*&&R4sC0fݍpZM怀4#6ݍVZM @A`@BlC HF#3C^&&RXʟC @A`@B*C H#3CCC0C0$C$ C'#$CLчp$XPCXXC!&C ! %C#&C  /CX#6B4C4C06B The relational operators group left-to-right, but this fact is not very useful; `a\fI expression\fR \fIexpression \fG<=\fI expression\fR \fIexpression \fG>=\fI expression\fR .ES The operators < (less than), > (greater than), <= (less than or equal to) and >= (greater than or equal to) all yield 0 if the specified relation is false and 1 if it is true. The type of the result is .Bdr0r1r2r3r4r5r6r7r8r9 r10 r11 r12 r13 r14r15sprfvdubase#lvdu$vduopen"L.1(L2 u L1L3zL4Zvdustart"vduenab" spl L5L6sleep L7vduclose"L.2(wflushtt vdudisab"L8vduread"L.3(ttread L96vduwrite"@L.4(ttwrite L10dvdusgtty"nL.5(ttystty L12L11L.6(L14dtrace L13getc L15Pttrstrt timeout L16partab wd ss L17vdurint"L.7(L184L19L20rd L21L22L23signal flushtty L24wakeup L25L264L27&L28$ttstart L294ttyinput vduxint">L.8(L30L31L32L33L.9(L36NL37$L35fL38,L394L40X@B0XPA@$CX P@$P $P &PCBðB0:ʠX@B0XPA@$C8X P@$P &P&P$Q XPA@$#ю p,iiiiii int. The usual arithmetic conversions are performed. Two pointers may be compared, and the result depends on the relative locations in the address space of the pointed-to objects. Pointer comparison is portable only when the pointers point to objects in the same array. .SH 7.7 Equality operators .LP .SY equality-expression: \fIexpression \fG==\fI expression\fR \fIexpression \fG!=\fI expression\fR .ES The \fG==\fR (equal to) and the \fG!=\fR (not equal to) operators are exactly analogous to the relational operators except for their lower precedence. (Thus `a> = \fIexpression\fR \fIlvalue \fG<< = \fIexpression\fR \fIlvalue \fG& = \fIexpression\fR \fIlvalue \fG\*^ = \fIexpression\fR \fIlvalue \fG\(or = \fIexpression\fR .ES Notice that the representation of the compound assignment operators has changed; formerly the `=' came first and the other operator came second (without any space). The compiler continues to accept the previous notation. .PP In the simple assignment with `=', the value of the expression replaces that of the object referred to by the lvalue. If both operands have arithmetic type, the right operand is converted to the type of the left preparatory to the assignment. .PP The behavior of an expression of the form `E1\ op =\ E2' may be inferred by taking it as equivalent to `E1\ =\ E1\ op\ E2'; however, E1 is evaluated only once. In .Bd += and .Bd \(mi=, the left operand may be a pointer, in which case the (integral) right operand is converted as explained in \(sc7.4; all right operands and all non-pointer left operands must have arithmetic type. .PP The compiler currently allows a pointer to be assigned to an integer, an integer to a pointer, and a pointer to a pointer of another type. The assignment is a pure copy operation, with no conversion. This usage is nonportable, and may produce pointers which cause addressing exceptions when used. However, it is guaranteed that assignment of the constant 0 to a pointer will produce a null pointer distinguishable from a pointer to any object. .SH 7.15 Comma operator .LP .SY comma-expression: \fIexpression \fG,\fI expression\fR .ES A pair of expressions separated by a comma is evaluated left-to-right and the value of the left expression is discarded. The type and value of the result are the type and value of the right operand. This operator groups left-to-right. In contexts where comma is given a special meaning, for example in a list of actual arguments to functions (\(sc7.1) and lists of initializers (\(sc8.6), the comma operator as described in this section can only appear in parentheses; for example, `f(a, (t = 3, t+2), c)' has three arguments, the second of which has the value 5. .bp .SH 8. Declarations .LP Declarations are used within function definitions to specify the interpretation which C gives to each identifier; they do not necessarily reserve storage associated with the identifier. Declarations have the form .SY declaration: decl-specifiers declarator-list\*(op \fG; .ES The declarators in the declarator-list contain the identifiers being declared. The decl-specifiers consist of a sequence of type and storage class specifiers. .SY decl-specifiers: type-specifier decl-specifiers\*(op sc-specifier decl-specifiers\*(op .ES The list must be self-consistent in a way described below. .SH 8.1 Storage class specifiers .LP The sc-specifiers are: .SY sc-specifier: .ft G auto static extern register typedef .ES The .Bd typedef specifier does not reserve storage and is called a `storage class specifier' only for syntactic convenience; it is discussed in \(sc8.8. .PP The meanings of the various storage classes were discussed in \(sc4. .PP The .Bd "auto, static," and .Bd register declarations also serve as definitions in that they cause an appropriate amount of storage to be reserved. In the \fGextern\fR case there must be an external definition (\(sc10) for the given identifiers somewhere outside the function in which they are declared. .PP A .Bd register declaration is best thought of as an .Bd auto declaration, together with a hint to the compiler that the variables declared will be heavily used. .MC Only the first few (\*(pd: three; \*I: five) such declarations are effective. Moreover, only variables of certain types will be stored in registers; on the \*(pd and \*I they are .Bd int, .Bd char, or pointer. .mc One restriction applies to register variables: the address-of operator .Bd & cannot be applied to them. Smaller, faster programs can be expected if register declarations are used appropriately, but future developments may render them unnecessary. .PP At most one sc-specifier may be given in a declaration. If the sc-specifier is missing from a declaration, it is takenorm.10 norm.05norm.15 norm.208cdLcd.10dcd.30cd.5^cd.20pcd.15jadadsd.00sdsource`adsd.60adsd.70adsd.55adsd.03expbpadsd.40adsd.05 adsd.12*expdadsd.25^adsd.15@adsd.20Vadsd.17Dadsd.30hadsd.35adsd.85count .EP refers to the .It count field of the structure to which .It sp points; .PR s\fB.\fGleft .EP refers to the left subtree pointer of the structure .It s. Finally, .PR s.right\(mi>tword[0] .EP refers to the first character of the .It tword member of the right subtree of .It s. .SH 8.6 Initialization .LP A declarator may specify an initial value for the identifier being declared. The initializer is preceded by `=', and consists of an expression or a list of values nested in braces. .SY initializer: \fB=\fI expression \fB= { \fIinitializer-list } \fB= { \fIinitializer-list \fB, } .ES .SY initializer-list: expression initializer-list \fG,\fI initializer-list { initializer-list } .ES The `=' is a new addition to the syntax, intended to alleviate potential ambiguities. The current compiler allows it to be omitted when the rest of the initializer is a very simple expression (just a name, string, or constant) or when the rest of the initializer is enclosed in braces. .PP All the expressions in an initializer for a static or external variable must be constant expressions, which are described in \(sc15, or expressions which reduce to the address of a previously declared variable, possibly offset by a constant expression. Automatic or register variables may be initialized by arbitrary expressions involving previously declared variables. .MC .PP Static and external variables which are not initialized are guaranteed to start off as .Bd 0 "" ";" automatic and register variables which are not initialized are guaranteed to start off as garbage. .mc .PP When an initializer applies to a .It scalar (a pointer or an object of arithmetic type), it consists of a single expression, perhaps in braces. The initial value of the object is taken from the expression; the same conversions as for assignment are performed. .PP When the declared variable is an .It aggregate (a structure or array) then the initializer consists of a brace-enclosed, comma-separated list of initializers for the members of the aggregate, written in increasing subscript or member order. If the aggregate contains subaggregates, this rule applies recursively to the members of the aggregate. If there are fewer initializers in the list than there are members of the aggregate, then the aggregate is padded with 0's. .MC It is not permitted to initialize unions or automatic aggregates. .mc .PP Braces may be elided as follows. If the initializer begins with a left brace, then the succeding comma-separated list of initializers initialize the members of the aggregate; it is erroneous for there to be more initializers than members. If, however, the initializer does not begin with a left brace, then only enough elements from the list are taken to account for the members of the aggregate; any remaining members are left to initialize the next member of the aggregate of which the current aggregate is a part. .PP A final abbreviation allows a .Bd char array to be initialized by a string. In this case successive members of the string initialize the members of the array. .PP For example, .PR int x[ ] = { 1, 3, 5 }; .EP declares and initializes .It x as a 1-dimensional array which has three members, since no size was specified and there are three initializers. .PR float y[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 }, }; .EP is a completely-bracketed initialization: 1, 3, and 5 initialize the first row of the array $y [ 0 ]$, namely $y [ 0 ] [ 0 ]$, $y [ 0 ] [ 1 ]$, and $y [ 0 ] [ 2 ]$. Likewise the next two lines initialize $y [ 1 ]$ and $y [ 2 ]$. The initializer ends early and therefore $y [ 3 ]$ is initialized with 0. Precisely the same effect could have been achieved by .PR float y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7, }; .EP The initializer for $y$ begins with a left brace, but that for $y [ 0 ]$ does not, therefore 3 elements from the list are used. Likewise the next three are taken successively for $y [ 1 ]$ and $y [ 2 ]$. Also, .PR float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } }; .EP initializes the first column of .It y (regarded as a two-dimensional array) and leaves the rest 0. .PP Finally, .PR char msg[\|] = "Syntax error on line %s\en"; .EP shows a character array whose members are initialized with a string. .SH 8.7 Type names .LP In two contexts (to specify type conversions explicitly, and as an argument of .Bd sizeof) it is desired to supply the name of a data type. This is accomplished using a `type name,' which in essence is a declaration for an object of that type which omits the name of the object. .SY type-name: type-specifier abstract-declarator .ES .SY abstract-declarator: empty \fG( \fIabstract-declarator \fG) \fG\** \fIabstract-declarator\fI abstract-declarator \fG( )\fI abstract-declarator \fG[ \fIconstant-expression\*(op \fG] .ES To avoid ambiguity, in the construction .SY \fG( \fIabstract-declarator \fG) .ES the abstract-declarator is required to be nonempty. Under this restriction, it is possible to identify uniquely the location in the abstract-declarator where the identifier would appear if the construction were a declarator in a declaration. The named type is then the same as the type of the hypothetical identifier. For example, .PR int int \** int \**[3] int (\**)[3] .EP name respectively the types `integer,' `pointer to integer,' `array of 3 pointers to integers,' and `pointer to an array of 3 integers.' As another example, .PR int i; . . . sin( (double) i); .EP calls the .It sin routine (which accepts a .Bd double argument) with an argument appropriately converted. .SH 8.8 Typedef .LP Declarations whose `storage class' is .Bd typedef do not define storage, but instead define identifiers which can be used later as if they were type keywords naming fundamental or derived types. Within the scope of a declaration involving .Bd typedef, each of the identifiers appearing as part of any declarators therein become syntactically equivalent to type keywords naming the type associated with the identifiers in the way described in \(sc8.4. .SY typedef-name: identifier .ES For example, after .PR typedef int MILES, \**KLICKSP; typedef struct { double re, im;} complex; .EP the constructions .PR MILES distance; extern KLICKSP metricp; complex z, \**zp; .EP are all legal declarations; the type of .It distance is .Bd `int', that of .It metricp is `pointer to .Bd int,' and that of .It z is the specified structure. .It zp is a pointer to such a structure. .PP .It Typedef does not introduce brand new types, only synonyms for types which could be specified in another way. Thus .Id distance in the example above .It distance is considered to have exactly the same type as any other .Bd int variable. .bp .SH 9. Statements .LP Except as indicated, statements are executed in sequence. .SH 9.1 Expression statement .LP Most statements are expression statements, which have the form .SY expression \fG; .ES Usually expression statements are assignments or function calls. .SH 9.2 Compound statement, or block .LP So that several statements can be used where one is expected, the compound statement (also, and equivalently, called `block') is provided: .SY compound-statement: { declaration-list\*(op statement-list\*(op } .ES .SY declaration-list: declaration declaration declaration-list .ES .SY statement-list: statement statement statement-list .ES If any of the identifiers in the declaration-list were previously declared, the outer declaration is pushed down for the duration of the block, at which time it resumes its force. .PP Any initializations of .Bd auto or .Bd register variables are performed each time the block is entered at the top. It is currently possible (but a bad practice) to transfer into a block; in that case the initializations are not performed. Initializations of .Bd static variables are performed only once when the program begins execution. Inside a block, .Bd external declarations do not reserve storage so initialization is not permitted. .SH 9.3 Conditional statement .LP The two forms of the conditional statement are .SY \fGif ( \fIexpression \fG) \fIstatement \fGif ( \fIexpression \fG) \fIstatement \fGelse \fIstatement .ES In both cases the expression is evaluated and if it is non-zero, the first substatement is executed. In the second case the second substatement is executed if the expression is 0. As usual the `else' ambiguity is resolved by connecting an \fGelse\fR with the last encountered elseless \fGif\fR. .SH 9.4 While statement .LP The \fGwhile\fR statement has the form .SY \fGwhile ( \fIexpression \fG) \fIstatement .ES The substatement is executed repeatedly so long as the value of the expression remains non-zero. The test takes place before each execution of the statement. .SH 9.5 Do statement .LP The \fGdo\fR statement has the form .SY \fGdo \fIstatement \fGwhile ( \fIexpression \fG) ; .ES The substatement is executed repeatedly until the value of the expression becomes zero. The test takes place after each execution of the statement. .SH 9.6 For statement .LP The \fGfor\fR statement has the form .SY .ft G for ( \fIexpression-1\*(op \fG; \fIexpression-2\*(op \fG ; \c \fIexpression-3\*(op \fG) \fIstatement .ES This statement is equivalent to .SY expression-1; \fGwhile (\fI\|expression-2\fG\|) { \fIstatement expression-3\|\fG; } .ES Thus the first expression specifies initialization for the loop; the second specifies a test, made before each iteration, such that the loop is exited when the expression becomes 0; the third expression typically specifies an incrementation which is performed after each iteration. .PP Any or all of the expressions may be dropped. A missing expression-2 makes the implied \fGwhile\fR clause equivalent to `while(\|1\|)'; other missing expressions are simply dropped from the expansion above. .SH 9.7 Switch statement .LP The \fGswitch\fR statement causes control to be transferred to one of several statements depending on the value of an expression. It has the form .SY \fGswitch ( \fIexpression \fG) \fIstatement .ES The usual arithmetic conversion is performed on the expression, but the result must be .Bd int. The statement is typically compound. Any statement within the statement may be labelled with one or more case prefixes as follows: .SY \fGcase \fIconstant-expression \fG: .ES where the constant expression must be .Bd int. No two of the case constants in the same switch may have the same value. Constant expressions are precisely defined in \(sc15. .PP There may also be at most one statement prefix of the form .SY \fGdefault : .ES When the \fGswitch\fR statement is executed, its expression is evaluated and compared with each case constant If one of the case constants is equal to the value of the expression, control is passed to the statement following the matched case prefix. If no case constant matches the expression, and if there is a \fGdefault\fR prefix, control passes to the prefixed statement. If no case matches and if there is no .Bd default then none of the statements in the switch is executed. .PP .Bd Case and .Bd default prefixes in themselves do not alter the flow of control, which continues unimpeded across such prefixes. To exit from a switch, see .Bd break, \(sc9.8. .PP Usually the statement that is the subject of a switch is compound. Declarations may appear at the head of this statement, initializations of automatic or register variables are ineffective. .SH 9.8 Break statement .LP The statement .SY \fGbreak ; .ES causes termination of the smallest enclosing \fGwhile\fR, \fGdo\fR, \fGfor\fR, or \fGswitch\fR statement; control passes to the statement following the terminated statement. .SH 9.9 Continue statement .LP The statement .SY \fGcontinue ; .ES causes control to pass to the loop-continuation portion of the smallest enclosing \fGwhile\fR, \fGdo\fR, or \fGfor\fR statement; that is to the end of the loop. More precisely, in each of the statements .SY .ta .5i 2.5i 4.5i \fGwhile (\|\|.\|.\|.\|\|) { do { for (\|\|.\|.\|.\|\|) { \|.\|.\|.\| \|.\|.\|.\| \|.\|.\|.\| contin:\|; contin:\|; contin:\|; } } while (\|\|.\|.\|.\|\|)\|; } .RT .ES a \fGcontinue\fR is equivalent to `goto contin'. (Following the `contin:' is a null statement, \(sc9.13.) .SH 9.10 Return statement .LP A function returns to its caller by means of the \fGreturn\fR statement, which has one of the forms .SY .ft G return ; return \fIexpression \fG; .ES In the first case the returned value is undefined. In the second case, the value of the expression is returned to the caller of the function. If required, the expression is converted, as if by assignment, to the type of the function in which it appears. Flowing off the end of a function is equivalent to a return with no returned value. .SH 9.11 Goto statement .LP Control may be transferred unconditionally by means of the statement .SY .ft G goto \fIidentifier \fG; .ES The identifier must be a label (\(sc9.12) located in the current function. Previous versions of C had an incompletely implemented notion of label variable, which has been withdrawn. .SH 9.12 Labelled statement .LP Any statement may be preceded by label prefixes of the form .SY identifier \fG: .ES which serve to declare the identifier as a label. The only use of a label is as a target of a .Bd goto. The scope of a label is the current function, excluding any sub-blocks in which the same identifier has been redeclared. See \(sc11. .SH 9.13 Null statement .LP The null statement has the form .SY \fG; .ES A null statement is useful to carry a label just before the `}' of a compound statement or to supply a null body to a looping statement such as \fGwhile\fR. .SH 10. External definitions .LP A C program consists of a sequence of external definitions. An external definition declares an identifier to have storage class .Bd extern (by default) or perhaps .Bd static, and a specified type. The type-specifier (\(sc8.2) may also be empty, in which case the type is taken to be \fGint\fR. The scope of external definitions persists to the end of the file in which they are declared just as the effect of declarations persists to the end of a block. The syntax of external definitions is the same as that of all declarations, except that only at this level may the code for functions be given. .SH 10.1 External function definitions .LP Function definitions have the form .SY function-definition: decl-specifiers\*(op function-declarator function-body .ES The only sc-specifiers allowed among the decl-specifiers are .Bd extern or .Bd static; See \(sc11.2 for the distinction between them. A function declarator is similar to a declarator for a `function returning ...' except that it lists the formal parameters of the function being defined. .SY function-declarator: declarator \fG( \fIparameter-list\*(op \fG) .ES .SY parameter-list: identifier identifier \fG,\fI parameter-list .ES The function-body has the form .SY function-body: declaration-list compound-statement .ES The identifiers in the parameter list, and only those identifiers, may be declared in the declaration list. Any identifiers whose type is not given are taken to be .Bd int. The only storage class which may be specified is .Bd register; if it is specified, the corresponding actual parameter will be copied, if possible, into a register at the outset of the function. .PP A simple example of a complete function definition is .PR int max\|(\|a, b, c) int a, b, c; { int m; m = \|(\|a\|>\|b\|)? a\|:\|b\|; return\|(\|m\|>\|c? m\|:\|c\|)\|; } .EP Here `int' is the type-specifier; `max(a,@b,@c)' is the function-declarator; `int@a,@b,@c;' is the declaration-list for the formal parameters; `{@.\|.\|.@}' is the block giving the code for the statement. The parentheses in the .Bd return are not required. .PP C converts all \fGfloat\fR actual parameters to \fGdouble\fR, so formal parameters declared \fGfloat\fR have their declaration adjusted to read \fGdouble\fR. Also, since a reference to an array in any context (in particular as an actual parameter) is taken to mean a pointer to the first element of the array, declarations of formal parameters declared `array of ...' are adjusted to read `pointer to ...'. Finally, because neither structures nor functions can be passed to a function, it is useless to declare a formal parameter to be a structure or function (pointers to structures or functions are of course permitted). .PP A free \fGreturn\fR statement is supplied at the end of each function definition, so running off the end causes control, but no value, to be returned to the caller. .SH 10.2 External data definitions .LP An external data definition has the form .SY data-definition: declaration .ES The storage class of such data may be .Bd extern (which is the default) or .Bd static, but not .Bd auto or .Bd register. .SH 11. Scope rules .LP A C program need not all be compiled at the same time: the source text of the program may be kept in several files, and precompiled routines may be loaded from libraries. Communication among the functions of a program may be carried out both through explicit calls and through manipulation of external data. .PP Therefore, there are two kinds of scope to consider: first, what may be called the \fIlexical scope\fR of an identifier, which is essentially the region of a program during which it may be used without drawing `undefined identifier' diagnostics; and second, the scope associated with external identifiers, which is characterized by the rule that references to the same external identifier are references to the same object. .SH 11.1 Lexical scope .LP The lexical scope of identifiers declared in external definitions persists from the definition through the end of the file in which they appear. The lexical scope of identifiers which are formal parameters persists through the function with which they are associated. The lexical scope of identifiers declared at the head of blocks persists until the end of the block. The lexical scope of labels is the whole of the function in which they appear. .PP Because all references to the same external identifier refer to the same object (see \(sc11.2) the compiler checks all declarations of the same external identifier for compatibility; in effect their scope is increased to the whole file in which they appear. .PP In all cases, however, if an identifier is explicitly declared at the head of a block, including the block constituting a function, any declaration of that identifier outside the block is suspended until the end of the block. .PP Remember also (\(sc8.5) that identifiers associated with ordinary variables on the one hand and those associated with structure and union members and tags on the other form two disjoint classes which do not conflict. .Bd Typedef names are in the same class as ordinary identifiers. They may be redeclared in inner blocks, but an explicit type must be given in the inner declaration: .PR typedef float distance; \&. . . { auto int distance; . . . .EP The .Bd int must be present in the second declaration, or it would be taken to be a declaration with no declarators and type .Bd distance.* .FS *It is agreed that the ice is thin here. .FE .SH 11.2 Scope of externals .LP .MC If a function refers to an identifier declared to be .mc \fGextern\fR, then somewhere among the files or libraries constituting the complete program there must be an external definition for the identifier. All functions in a given program which refer to the same external identifier refer to the same object, so care must be taken that the type and extent specified in the definition are compatible with those specified by each function which references the data. .PP The appearance of the .Bd extern keyword in an external definition indicates that storage for the identifiers being declared will be allocated in another file. Thus in a multi-file program, an external data definition without the .Bd extern specifier must appear in exactly one of the files. Any other files which wish to give an external definition for the identifier must include the .Bd extern in the definition. The identifier can be initialized only in the declaration where storage is allocated. .PP Identifiers declared .Bd static at the top level in external definitions are not visible in other files. .MC Functions may be declared .Bd static to make their definition local to a file. .mc .SH 12. Compiler control lines .LP The C compiler contains a preprocessor capable of macro substitution, conditional compilation, and inclusion of named files. Lines beginning with `#' communicate with this preprocessor. These lines have syntax independent of the rest of the language; they may appear anywhere and have effect which lasts (independent of scope) until the end of the source program file. .SH 12.1 Token replacement .LP A compiler-control line of the form .SY \fG# define \fIidentifier token-string .ES (note: no trailing semicolon) causes the preprocessor to replace subsequent instances of the identifier with the given string of tokens. A line of the form .SY \fG# define \fIidentifier\fG( \fIidentifier\fG , ... ) \fItoken-string .ES where there is no space between the first identifier and the `(', is a macro definition with arguments. Subsequent instances of the first identifier followed by a `(', a sequence of tokens delimited by commas, and a `)' are replaced by the token string in the definition. Each occurrence of an identifier mentioned in the formal parameter list of the definition is replaced by the corresponding token string from the call. The actual arguments in the call are token strings separated by commas; however commas in quoted strings or protected by parentheses do not separate arguments. The number of formal and actual parameters must be the same. Text inside a string or a character constant is not subject to replacement. .PP In both forms the replacement string is rescanned for more defined identifiers. In both forms a long definition may be continued on another line by writing `\e' at the end of the line to be continued. .PP This facility is most valuable for definition of `manifest constants', as in .PR # define TABSIZE 100 .\|.\|. int table[TABSIZE]; .EP A control line of the form .SY \fG# undef \fIidentifier .ES causes the identifier's preprocessor definition to be forgotten. .SH 12.2 File inclusion .LP A compiler control line of the form .SY \fG# include "\fIfilename\|\fG" .ES causes the replacement of that line by the entire contents of the file \fIfilename\fR. .PP The named file is searched for first in the directory of the original source file, and then in a sequence of standard places. Alternatively, a control line of the form .SY # include <\fIfilename> .ES searches only the standard places, and not the directory of the source file. .PP Includes may be nested. .SH 12.3 Conditional compilation .LP A compiler control line of the form .SY \fG# if \fIconstant-expression .ES checks whether the constant expression (see \(sc15) evaluates to non-zero. A control line of the form .SY \fG# ifdef \fIidentifier .ES checks whether the identifier is currently defined in the preprocessor; that is, whether it has been the subject of a .Bd #define control line. A control line of the form .SY \fG# ifndef \fIidentifier .ES checks whether the identifier is currently undefined in the preprocessor. .PP All three forms are followed by an arbitrary number of lines, possibly containing a control line .SY \fG# else .ES and then by a control line .SY \fG# endif .ES If the checked condition is true then any lines between .Bd #else and .Bd #endif are ignored. If the checked condition is false then any lines between the test and an .Bd #else or, lacking an .Bd #else, the .Bd #endif, are ignored. .PP These constructions may be nested. .SH 12.4 Line control .LP For the benefit of other preprocessors which generate C programs, a line of the form .SY \fG# line \fIconstant identifier .ES causes the compiler to believe, for purposes of error diagnostics, that the next line number is given by the constant and the current input file is named by the identifier. If the identifier is absent the remembered file name does not change. .SH 13. Implicit declarations .LP It is not always necessary to specify both the storage class and the type of identifiers in a declaration. Sometimes the storage class is supplied by the context: in external definitions, and in declarations of formal parameters and structure members. In a declaration inside a function, if a storage class but no type is given, the identifier is assumed to be \fGint\fR; if a type but no storage class is indicated, the identifier is assumed to be \fGauto\fR. An exception to the latter rule is made for functions, since \fGauto\fR functions are meaningless (C being incapable of compiling code into the stack). If the type of an identifier is `function returning ...', it is implicitly declared to be \fGextern\fR. .PP In an expression, an identifier followed by \fG(\fR and not currently declared is contextually declared to be `function returning \fGint\fR'. .SH 14. Types revisited .LP This section summarizes the operations which can be performed on objects of certain types. .SH 14.1 Structures and unions .LP There are only two things that can be done with a structure or union: name one of its members (by means of the \fG\|.\|\fR operator); or take its address (by unary \fG&\fR). Other operations, such as assigning from or to it or passing it as a parameter, draw an error message. In the future, it is expected that these operations, but not necessarily others, will be allowed. .PP \(sc7.1 says that in a direct or indirect structure reference (with \fG.\fR or \(mi>) the name on the right must be a member of the structure named or pointed to by the expression on the left. To allow an escape from the typing rules, this restriction is not firmly enforced by the compiler. In fact, any lvalue is allowed before `\fB.\fR', and that lvalue is then assumed to have the form of the structure of which the name on the right is a member. Also, the expression before a `\(mi>' is required only to be a pointer or an integer. If a pointer, it is assumed to point to a structure of which the name on the right is a member. If an integer, it is taken to be the absolute address, in machine storage units, of the appropriate structure. .PP Such constructions are non-portable. .SH 14.2 Functions .LP There are only two things that can be done with a function: call it, or take its address. If the name of a function appears in an expression not in the function-name position of a call, a pointer to the function is generated. Thus, to pass one function to another, one might say .PR int f(\|\|); ... g(\|f\|); .EP Then the definition of \fIg \fRmight read .PR g\|(\|funcp\|) int (\**funcp)\|(\|\|); { .\|.\|. (\**funcp)\|(\|\|); .\|.\|. } .EP Notice that \fIf\fR was declared explicitly in the calling routine since its first appearance was not followed by \fG(\fR\|. .SH 14.3 Arrays, pointers, and subscripting .LP Every time an identifier of array type appears in an expression, it is converted into a pointer to the first member of the array. Because of this conversion, arrays are not lvalues. By definition, the subscript operator \fG[\|]\fR is interpreted in such a way that `E1[E2]' is identical to `\**(\|(\|E1)\|+\|(E2\|)\|)'. Because of the conversion rules which apply to \fG+\fR, if E1 is an array and E2 an integer, then E1[E2] refers to the E2-th member of E1. Therefore, despite its asymmetric appearance, subscripting is a commutative operation. .PP A consistent rule is followed in the case of multi-dimensional arrays. If E is an \fIn\|\fR-dimensional array of rank $i times j times ... times k$, then E appearing in an expression is converted to a pointer to an (\fIn\fR\(mi1)-dimensional array with rank $j times ... times k$. If the \fG\**\fR operator, either explicitly or implicitly as a result of subscripting, is applied to this pointer, the result is the pointed-to (\fIn\fR\(mi1)-dimensional array, which itself is immediately converted into a pointer. .PP For example, consider .PR int x[3][5]; .EP Here \fIx\fR is a 3\(mu5 array of integers. When \fIx\fR appears in an expression, it is converted to a pointer to (the first of three) 5-membered arrays of integers. In the expression `x[\|i\|]', which is equivalent to `\**(x+i)', \fIx\fR is first converted to a pointer as described; then \fIi\fR is converted to the type of \fIx\fR, which involves multiplying \fIi\fR by the length the object to which the pointer points, namely 5 integer objects. The results are added and indirection applied to yield an array (of 5 integers) which in turn is converted to a pointer to the first of the integers. If there is another subscript the same argument applies again; this time the result is an integer. .PP It follows from all this that arrays in C are stored row-wise (last subscript varies fastest) and that the first subscript in the declaration helps determine the amount of storage consumed by an array but plays no other part in subscript calculations. .SH 14.4 Explicit pointer conversions .LP .MC Certain conversions involving pointers are permitted but have implementation-dependent aspects. They are all specified by means of an explicit type-conversion operator, \(sc\(sc7.2 and 8.7. .PP A pointer may be converted to any of the integral types large enough to hold it. Whether an \fGint\fR or \fGlong\fR is required is machine dependent. The mapping function is also machine dependent, but is intended to be unsurprising to those who know the addressing structure of the machine. Details for some particular machines are given below. .PP An object of integral type may be explicitly converted to a pointer. The mapping always carries an integer converted from a pointer back to the same pointer, but is otherwise machine dependent. .PP A pointer to one type may be converted to a pointer of another type. The resulting pointer may cause addressing exceptions upon use if the subject pointer does not refer to an object suitably aligned in storage. It is guaranteed that a pointer to an object of a given size may be converted to a pointer to an object of a smaller size and back again without change. .PP For example, a storage-allocation routine might accept a size (in bytes) of an object to allocate, and return a \fGchar\fR pointer; it might be used in this way: .PR extern char *alloc(); double *dp; dp = (double *) alloc(sizeof(double)); *dp = 22.0 / 7.0; .EP \fGalloc\fR must ensure (in a machine-dependent way) that its return value is suitable for conversion to a pointer to \fGdouble\fR; then the \fIuse\fR of the function is portable. .PP The pointer representation on the \*(pd corresponds to a 16-bit integer and is measured in bytes. \fGchars\fR have no alignment requirements; everything else must have an even address. .PP On the Honeywell 6000, a pointer corresponds to a 36-bit integer; the word part is in the left 18 bits, and the two bits that select the character in a word are just to their right. Thus \fGchar\fR pointers are measured in units of $2 sup 16$ bytes; everything else is measured in units of $2 sup 18$ machine words. \fGdouble\fR quantities and aggregates containing them must lie on an even word address (0 mod $2 sup 19$). .PP The IBM 370 and the \*I \*(I2 are similar. On both, addresses are measured in bytes and occupy a 32-bit integer; elementary objects must be aligned on a boundary equal to their length, so pointers to \fGshort\fR must be 0 mod 2, to \fGint\fR and \fGfloat\fR 0 mod 4, and to \fGdouble\fR 0 mod 8. Aggregates are aligned on the strictest boundary required by any of their constituents. .PP Addressing on the \*I \*(I1 is like the \*(I2, except that a pointer corresponds to a 16-bit integer, and \fGlong\fR objects need only be aligned on a 2-byte boundary. .mc .SH 15. Constant expressions .LP In several places C requires expressions which evaluate to a constant: after .Bd case, as array bounds, and in initializers. In the first two cases, the expression can involve only integer constants, character constants, and .Bd sizeof expressions, possibly connected by the binary operators .SY .R + \(mi \** / % & \(or \*^ << >> == != < > <= >= .ES or by the unary operators .SY \(mi \*~ .ES or by the ternary operator .SY .R ? : .ES Parentheses can be used for grouping, but not for function calls. .PP A bit more latitude is permitted for initializers; besides constant expressions as discussed above, one can also apply the unary \fG&\fR operator to external or static objects, .MC and (under UNIX) .mc to external or static arrays subscripted with a constant expression. The unary \fG&\fR can also be applied implicitly by appearance of unsubscripted arrays and functions. The basic rule is that initializers must evaluate either to a constant or to the address of a previously declared external or static object plus or minus a constant. .if n .ds * * .bp .SH 16. Grammar revisited. .PP This section repeats the grammar of C in notation somewhat different than given before. The description below is adapted directly from a YACC grammar actually used by several compilers; thus it may (aside from possible editing errors) be regarded as authentic. The notation is pure YACC with the exception that the `\(or' separating alternatives for a production is omitted, since alternatives are always on separate lines; the `;' separating productions is omitted since a blank line is left between productions. .PP The lines with `%term' name the terminal symbols, which are either commented upon or should be self-evident. The lines with `%left,' `%right,' and `%binary' indicate whether the listed terminals are left-associative, right-associative, or non-associative, and describe a precedence structure. The precedence (binding strength) increases as one reads down the page. When the construction `%prec \fIx\fR' appears the precedence of the rule is that of the terminal .It x; otherwise the precedence of the rule is that of its leftmost terminal. .TS l1l1l1l1. %term NAME %term STRING %term ICON %term FCON %term PLUS %term MINUS %term MUL %term AND %term QUEST %term COLON %term ANDAND %term OROR %term ASOP /\** old-style =+ etc. \**/ %term RELOP /\** <= >= < > \**/ %term EQUOP /\** == != \**/ %term DIVOP /\** / % \**/ %term OR /\** \(or \**/ %term EXOR /\** \*^ \**/ %term SHIFTOP /\** << >> \**/ %term INCOP /\** ++ \-\- \**/ %term UNOP /\** ! \*~ \**/ %term STROP /\** \fG.\fR \-> \**/ .TE .TS l1l1l1l1. %term TYPE /\** int, char, long, float, double, unsigned, short \**/ %term CLASS /\** extern, register, auto, static, typedef \**/ %term STRUCT /\** struct or union \**/ %term RETURN %term GOTO %term IF %term ELSE %term SWITCH %term BREAK %term CONTINUE %term WHILE %term DO %term FOR %term DEFAULT %term CASE %term SIZEOF %term LP /\** ( \**/ %term RP /\** ) \**/ %term LC /\** { \**/ %term RC /\** } \**/ %term LB /\** [ \**/ %term RB /\** ] \**/ %term CM /\** , \**/ %term SM /\** ; \**/ %term ASSIGN /\** = \**/ .TE .TS l1l1l1l1. %left CM %right ASOP ASSIGN %right QUEST COLON %left OROR %left ANDAND %left OROP %left AND %binary EQUOP %binary RELOP %left SHIFTOP %left PLUS MINUS %left MUL DIVOP %right UNOP %right INCOP SIZEOF %left LB LP STROP .TE .TS l1l1l1l1. program: ext_def_list ext_def_list: ext_def_list external_def /\** empty \**/ external_def: optattrib SM optattrib init_dcl_list SM optattrib fdeclarator function_body function_body: dcl_list compoundstmt dcl_list: dcl_list declaration /\** empty \**/ declaration: specifiers declarator_list SM specifiers SM optattrib: specifiers /\** empty \**/ specifiers: CLASS type type CLASS CLASS type type: TYPE TYPE TYPE struct_dcl struct_dcl: STRUCT NAME LC type_dcl_list RC STRUCT LC type_dcl_list RC STRUCT NAME type_dcl_list: type_declaration type_dcl_list type_declaration type_declaration: type declarator_list SM struct_dcl SM type SM declarator_list: declarator declarator_list CM declarator declarator: fdeclarator nfdeclarator nfdeclarator COLON con_e %prec CM COLON con_e %prec CM nfdeclarator: MUL nfdeclarator nfdeclarator LP RP nfdeclarator LB RB nfdeclarator LB con_e RB NAME LP nfdeclarator RP fdeclarator: MUL fdeclarator fdeclarator LP RP fdeclarator LB RB fdeclarator LB con_e RB LP fdeclarator RP NAME LP name_list RP NAME LP RP name_list: NAME name_list CM NAME init_dcl_list: init_declarator %prec CM init_dcl_list CM init_declarator init_declarator: nfdeclarator nfdeclarator ASSIGN initializer nfdeclarator initializer fdeclarator init_list: initializer %prec CM init_list CM initializer initializer: e %prec CM LC init_list RC LC init_list CM RC compoundstmt: LC dcl_list stmt_list RC stmt_list: stmt_list statement /\** empty \**/ statement: e SM compoundstmt IF LP e RP statement IF LP e RP statement ELSE statement WHILE LP e RP statement DO statement WHILE LP e RP SM FOR LP opt_e SM opt_e SM opt_e RP statement SWITCH LP e RP statement BREAK SM CONTINUE SM RETURN SM RETURN e SM GOTO NAME SM SM label statement label: NAME COLON CASE con_e COLON DEFAULT COLON con_e: e %prec CM opt_e: e /\** empty \**/ elist: e %prec CM elist CM e e: e MUL e e CM e e DIVOP e e PLUS e e MINUS e e SHIFTOP e e RELOP e e EQUOP e e AND e e OROP e e ANDAND e e OROR e e MUL ASSIGN e e DIVOP ASSIGN e e PLUS ASSIGN e e MINUS ASSIGN e e SHIFTOP ASSIGN e e AND ASSIGN e e OROP ASSIGN e e QUEST e COLON e e ASOP e e ASSIGN e term term: term INCOP MUL term AND term MINUS term UNOP term INCOP term SIZEOF term LP type_name RP term %prec STROP SIZEOF LP type_name RP %prec SIZEOF term LB e RB term LP RP term LP elist RP term STROP NAME NAME ICON FCON STRING LP e RP type_name: type abst_decl abst_decl: /\** empty \**/ LP RP LP abst_decl RP LP RP MUL abst_decl abst_decl LB RB abst_decl LB con_e RB LP abst_decl RP .TE .de Bd \\$2\fG\\$1\fR\\$3 .. .de It \\$2\fI\\$1\|\fR\\$3 .. .ds ~ \v'.5'\s14~\s10\v'-.5' .ds ^ \v'.5'\s14^\s10\v'-.5' .ds pd \s8PDP\s10-11 .ds * \fR\v'.2'*\fP\v'-.2' .ds op \s6\d\fIopt\fP\u\s10 .ds I Interdata .ds I1 7/16 .ds I2 7/32 .tr @ .tc .tr \(sc# .tr ~~ .de SY .LP .KS .nf .ft I .. .de ES .KE .LP .. .de PR .DS .ft G .. .de EP .ft R .DE .. .de MC .mc | 1m .. .sp |2.5i .ce 3 .ps 12 .ft G Programming in C _ A Tutorial .ps 10 .sp .ft R Brian W. Kernighan .ft I .sp Bell Laboratories, Murray Hill, N. J. .sp |4.1i .ft R .ps 10 .fi .vs 12p .NH Introduction .PP C is a computer language .MC available on a variety of machines, including the PDP-11, Honeywell 6000, IBM 370, and Interdata 7/16, 7/32 and 8/32. .mc C lets you write your programs clearly and simply _ it has decent control flow facilities so your code can be read straight down the page, without labels or GOTO's; it lets you write code that is compact without being too cryptic; it encourages modularity and good program organization; and it provides good data-structuring facilities. .PP This memorandum is a tutorial to make learning C as painless as possible. The first part concentrates on the central features of C; the second part discusses those parts of the language which are useful (usually for getting more efficient and smaller code) but which are not necessary for the new user. This is .ul not a reference manual. Details and special cases will be skipped ruthlessly, and no attempt will be made to cover every language feature. The order of presentation is hopefully pedagogical instead of logical. Users who would like the full story should consult the .ul C Reference Manual by D. M. Ritchie [1], which should be read for details anyway. Runtime support is described in [2] and [3]; you will have to read one of these to learn how to compile and run a C program. .PP We will assume that you are familiar with the mysteries of creating files, text editing, and the like in the operating system you run on, and that you have programmed in some language before. .NH A Simple C Program .PP .E1 main(~) { printf("hello, world"); } .E2 .PP A C program consists of one or more .ul functions, which are similar to the functions and subroutines of a Fortran program or the procedures of PL/I, and perhaps some external data definitions. .UL main is such a function, and in fact all C programs must have a .UL main\*. Execution of the program begins at the first statement of .UL main\*. .UL main will usually invoke other functions to perform its job, some coming from the same program, and others from libraries. .PP One method of communicating data between functions is by arguments. The parentheses following the function name surround the argument list; here .UL main is a function of no arguments, indicated by (~). The {} enclose the statements of the function. Individual statements end with a semicolon but are otherwise free-format. .PP .UL printf is a library function which will format and print output on the terminal (unless some other destination is specified). In this case it prints .E1 hello, world .E2 A function is invoked by naming it, followed by a list of arguments in parentheses. There is no .UC CALL statement as in Fortran or .UC PL/I. .NH A Working C Program; Variables; Types and Type Declarations .PP Here's a bigger program that adds three integers and prints their sum. .E1 main(~) { int a, b, c, sum; a = 1; b = 2; c = 3; sum = a + b + c; printf("sum is %d", sum); } .E2 .PP Arithmetic and the assignment statements are much the same as in Fortran (except for the semicolons) or .UC PL/I. The format of C programs is quite free. We can put several statements on a line if we want, or we can split a statement among several lines if it seems desirable. The split may be between any of the operators or variables, but .ul not in the middle of a name or operator. As a matter of style, spaces, tabs, and newlines should be used freely to enhance readability. .PP C has four fundamental .ul types of variables: .DS .MC \fGint\fR integer (PDP-11 and Interdata 7/16: 16 bits; H6070: 36 bits; IBM370 and Interdata 7/32, 8/32: 32 bits) \fGchar\fR one byte character (PDP-11, Interdata and IBM370: 8 bits; H6070: 9 bits) .mc \fGfloat\fR single-precision floating point \fGdouble\fR double-precision floating point .DE There are also .ul arrays and .ul structures of these basic types, .ul pointers to them and .ul functions that return them, all of which we will meet shortly. .PP .ul All variables in a C program must be declared, although this can sometimes be done implicitly by context. Declarations must precede executable statements. The declaration .E1 int a, b, c, sum; .E2 declares .UL a, .UL b, .UL c, and .UL sum to be integers. .PP Variable names have one to eight characters, chosen from A-Z, a-z, 0-9, and \(ul, and start with a non-digit. Stylistically, it's much better to use only a single case and give functions and external variables names that are unique in the first six characters. (Function and external variable names are used by various assemblers, some of which are limited in the size and case of identifiers they can handle.) Furthermore, keywords and library functions may only be recognized in one case. .NH Constants .PP We have already seen decimal integer constants in the previous example _ 1, 2, and 3. Since C is often used for system programming and bit-manipulation, octal .MC and hexadecimal .mc numbers are an important part of the language. In C, any number that begins with 0 (zero!) is an octal integer (and hence can't have any 8's or 9's in it). Thus 0777 is an octal constant, with decimal value 511. .MC A number beginning with 0x is a hexadecimal integer: e.g. 0x7f is a hexadecimal constant with decimal value 127. .mc .PP A ``character'' is one byte (an inherently machine-dependent concept). Most often this is expressed as a .ul character constant, which is one character enclosed in single quotes. However, it may be any quantity that fits in a byte, as in .UL flags below: .E1 char quest, newline, flags; quest = '?'; newline = '\\n'; flags = 077; .E2 .PP The sequence `\\n' is C notation for ``newline character'', which, when printed, skips the terminal to the beginning of the next line. Notice that `\\n' represents only a single character. There are several other ``escapes'' like `\\n' for representing hard-to-get or invisible characters, such as `\\t' for tab, `\\b' for backspace, .MC `\f' for formfeed, .mc `\\0' for end of file, and `\\\\' for the backslash itself. .PP .UL float and .UL double constants are discussed in section 26. .NH Simple I/O _ getchar, putchar, printf .PP .E1 main( ) { char c; c = getchar(~); putchar(c); } .E2 .PP .UL getchar and .UL putchar are the basic I/O library functions in C. .UL getchar fetches one character from the standard input (usually the terminal) each time it is called, and returns that character as the value of the function. When it reaches the end of whatever file it is reading, thereafter it returns the character represented by `\\0' (ascii .UC NUL, which has value zero). We will see how to use this very shortly. .PP .UL putchar puts one character out on the standard output (usually the terminal) each time it is called. So the program above reads one character and writes it back out. By itself, this isn't very interesting, but observe that if we put a loop around this, and add a test for end of file, we have a complete program for copying one file to another. .PP .UL printf is a more complicated function for producing formatted output. We will talk about only the simplest use of it. Basically, .UL printf uses its first argument as formatting information, and any successive arguments as variables to be output. Thus .E1 printf ("hello, world\\n"); .E2 is the simplest use _ the string ``hello, world\\n'' is printed out. No formatting information, no variables, so the string is dumped out verbatim. The newline is necessary to put this out on a line by itself. (The construction .E1 "hello, world\\n" .E2 is really an array of .UL chars\*. More about this shortly.) .PP More complicated, if .UL sum is 6, .E1 printf ("sum is %d\\n", sum); .E2 prints .E1 sum is 6 .E2 Within the first argument of .UL printf, the characters ``%d'' signify that the next argument in the argument list is to be printed as a base 10 number. .PP Other useful formatting commands are ``%c'' to print out a single character, ``%s'' to print out an entire string, and ``%o'' to print a number as octal instead of decimal (no leading zero). For example, .E1 n = 511; printf ("What is the value of %d in octal?", n); printf (" %s! %d decimal is %o octal\\n", "Right", n, n); .E2 prints .E1 .fi What is the value of 511 in octal? Right! 511 decimal is 777 octal .E2 Notice that there is no newline at the end of the first output line. Successive calls to .UL printf (and/or .UL putchar, for that matter) simply put out characters. No newlines are printed unless you ask for them. Similarly, on input, characters are read one at a time as you ask for them. Each line is generally terminated by a newline (\\n), but there is otherwise no concept of record. .NH If; relational operators; compound statements .PP The basic conditional-testing statement in C is the .UL if statement: .E1 c = getchar( ); if( c \*= '?' ) printf("why did you type a question mark?\\n"); .E2 The simplest form of .UL if is .E1 if (expression) statement .E2 .PP The condition to be tested is any expression enclosed in parentheses. It is followed by a statement. The expression is evaluated, and if its value is non-zero, the statement is executed. There's an optional .UL else clause, to be described soon. .PP The character sequence `==' is one of the relational operators in C; here is the complete set: .E1 \*= equal to (\*.EQ\*. to Fortraners) != not equal to > greater than < less than >= greater than or equal to <= less than or equal to .E2 .PP The value of .UL ``expression .UL relation .UL expression'' is 1 if the relation is true, and 0 if false. Don't forget that the equality test is `=='; a single `=' causes an assignment, not a test, and invariably leads to disaster. .PP Tests can be combined with the operators .UL `&&' .UC (AND), .UL `\*|' .UC (OR), and .UL `!' .UC (NOT). For example, we can test whether a character is blank or tab or newline with .E1 if( c\*=' ' \*| c\*='\\t' \*| c\*='\\n' ) \*.\*.\*. .E2 C guarantees that .UL `&&' and .UL `\*|' are evaluated left to right _ we shall soon see cases where this matters. .PP One of the nice things about C is that the .UL statement part of an .UL if can be made arbitrarily complicated by enclosing a set of statements in {}. As a simple example, suppose we want to ensure that .UL a is bigger than .UL b, as part of a sort routine. The interchange of .UL a and .UL b takes three statements in C, grouped together by {}: .E1 .ne 5 if (a < b) { t = a; a = b; b = t; } .E2 .PP As a general rule in C, anywhere you can use a simple statement, you can use any compound statement, which is just a number of simple or compound ones enclosed in {}. There is no semicolon after the } of a compound statement, but there .ul is a semicolon after the last non-compound statement inside the {}. .PP The ability to replace single statements by complex ones at will is one feature that makes C much more pleasant to use than Fortran. Logic (like the exchange in the previous example) which would require several GOTO's and labels in Fortran can and should be done in C without any, using compound statements. .NH While Statement; Assignment within an Expression; Null Statement .PP The basic looping mechanism in C is the .UL while statement. Here's a program that copies its input to its output a character at a time. Remember that `\\0' marks the end of file. .E1 main(~) { char c; while( (c=getchar(~)) != '\\0' ) putchar(c); } .E2 The .UL while statement is a loop, whose general form is .E1 while (expression) statement .E2 Its meaning is .E1 (a) evaluate the expression (b) if its value is true (i\*.e\*., not zero) do the statement, and go back to (a) .E2 Because the expression is tested before the statement is executed, the statement part can be executed zero times, which is often desirable. As in the .UL if statement, the expression and the statement can both be arbitrarily complicated, although we haven't seen that yet. Our example gets the character, assigns it to .UL c, and then tests if it's a `\\0''. If it is not a `\\0', the statement part of the .UL while is executed, printing the character. The .UL while then repeats. When the input character is finally a `\\0', the .UL while terminates, and so does .UL main\*. .PP Notice that we used an assignment statement .E1 c = getchar(~) .E2 within an expression. This is a handy notational shortcut which often produces clearer code. (In fact it is often the only way to write the code cleanly. As an exercise, re-write the file-copy without using an assignment inside an expression.) It works because an assignment statement has a value, just as any other expression does. Its value is the value of the right hand side. This also implies that we can use multiple assignments like .E1 x = y = z = 0; .E2 Evaluation goes from right to left. .PP By the way, the extra parentheses in the assignment statement within the conditional were really necessary: if we had said .E1 c = getchar(~) != '\\0' .E2 .UL c would be set to 0 or 1 depending on whether the character fetched was an end of file or not. This is because in the absence of parentheses the assignment operator `=' is evaluated after the relational operator `!='. When in doubt, or even if not, parenthesize. .PP Since .UL putchar(c) returns .UL c as its function value, we could also copy the input to the output by nesting the calls to .UL getchar and .UL putchar: .E1 main(~) { while( putchar(getchar(~)) != '\\0' ) ; } .E2 What statement is being repeated?~ None, or technically, the .ul null statement, because all the work is really done within the test part of the .UL while\*. This version is slightly different from the previous one, because the final `\\0' is copied to the output before we decide to stop. .NH Arithmetic .PP The arithmetic operators are the usual `+', `\(mi', `*', and `/' (truncating integer division if the operands are both .UL int), and the remainder or mod operator `%': .E1 x = a%b; .E2 sets .UL x to the remainder after .UL a is divided by .UL b (i.e., .UL a .UL mod .UL b)\*. The results are machine dependent unless .UL a and .UL b are both positive. .PP In arithmetic, .UL char variables can usually be treated like .UL int variables. Arithmetic on characters is quite legal, and often makes sense: .E1 c = c + 'A' - 'a'; .E2 converts a single lower case ascii character stored in .UL c to upper case, making use of the fact that corresponding ascii letters are a fixed distance apart. The rule governing this arithmetic is that all .UL chars are converted to .UL int before the arithmetic is done. Beware that conversion may involve sign-extension _ if the leftmost bit of a character is 1, the resulting integer might be negative. (This doesn't happen with genuine characters on any current machine.) .PP So to convert a file into lower case: .E1 main( ) { char c; while( (c=getchar( )) != '\\0' ) if( 'A'<=c && c<='Z' ) putchar(c+'a'-'A'); else putchar(c); } .E2 Characters have different sizes on different machines. Further, this code won't work on an IBM machine, because the letters in the ebcdic alphabet are not contiguous. .NH Else Clause; Conditional Expressions .PP We just used an .UL else after an .UL if\*. The most general form of .UL if is .E1 if (expression) statement1 else statement2 .E2 the .UL else part is optional, but often useful. The canonical example sets .UL x to the minimum of .UL a and .UL b: .E1 .ne 4 if (a < b) x = a; else x = b; .E2 Observe that there's a semicolon after .UL x=a\*. .PP C provides an alternate form of conditional which is often more concise. It is called the ``conditional expression'' because it is a conditional which actually has a value and can be used anywhere an expression can. The value of .E1 a127 or <0) into one pile. Since this is presumably an isolated part of the program, good practice dictates making it a separate function. Here is one way: .E1 .ne 7 main(~) { int hist[129]; /\** 128 legal chars + 1 illegal group \**/ \*.\*.\*. count(hist, 128); /\** count the letters into hist \**/ printf( \*.\*.\*. ); /\** comments look like this; use them \**/ \*.\*.\*. /\** anywhere blanks, tabs or newlines could appear \**/ } .SP count(buf, size) int size, buf[ ]; { int i, c; for( i=0; i<=size; i\*+ ) buf[i] = 0; /\** set buf to zero \**/ while( (c=getchar(~)) != '\\0' ) { /\** read til eof \**/ if( c > size \*| c < 0 ) c = size; /\** fix illegal input \**/ buf[c]\*+; } return; } .E2 We have already seen many examples of calling a function, so let us concentrate on how to .ul define one. Since .UL count has two arguments, we need to declare them, as shown, giving their types, and in the case of .UL buf, the fact that it is an array. The declarations of arguments go .ul between the argument list and the opening `{'. There is no need to specify the size of the array .UL buf, for it is defined outside of .UL count\*. .PP The .UL return statement simply says to go back to the calling routine. In fact, we could have omitted it, since a return is implied at the end of a function. .PP What if we wanted .UL count to return a value, say the number of characters read?~ The .UL return statement allows for this too: .E1 int i, c, nchar; nchar = 0; \*.\*.\*. while( (c=getchar(~)) != '\\0' ) { if( c > size \*| c < 0 ) c = size; buf[c]\*+; nchar\*+; } return(nchar); .E2 Any expression can appear within the parentheses. Here is a function to compute the minimum of two integers: .E1 .ne 4 min(a, b) int a, b; { return( a < b ? a : b ); } .E2 .PP .PP To copy a character array, we could write the function .E1 .ne 5 strcopy(s1, s2) /\** copies s1 to s2 \**/ char s1[ ], s2[ ]; { int i; for( i = 0; (s2[i] = s1[i]) != '\\0'; i\*+ ); } .E2 As is often the case, all the work is done by the assignment statement embedded in the test part of the .UL for\*. Again, the declarations of the arguments .UL s1 and .UL s2 omit the sizes, because they don't matter to .UL strcopy\*. (In the section on pointers, we will see a more efficient way to do a string copy.) .PP There is a subtlety in function usage which can trap the unsuspecting Fortran programmer. Simple variables (not arrays) are passed in C by ``call by value'', which means that the called function is given a copy of its arguments, and doesn't know their addresses. This makes it impossible to change the value of one of the actual input arguments. .a .PP There are two ways out of this dilemma. One is to make special arrangements to pass to the function the address of a variable instead of its value. The other is to make the variable a global or external variable, which is known to each function by its name. We will discuss both possibilities in the next few sections. .NH Local and External Variables .PP If we say .E1 f( ) { int x; \*.\*.\*. } g( ) { int x; \*.\*.\*. } .E2 each .UL x is .ul local to its own routine _ the .UL x in .UL f is unrelated to the .UL x in .UL g\*. (Local variables are also called ``automatic''.) Furthermore each local variable in a routine appears only when the function is called, and .ul disappears when the function is exited. Local variables have no memory from one call to the next and must be explicitly initialized upon each entry. (There is a .UL static storage class for making local variables with memory; we won't discuss it.) .PP As opposed to local variables, .ul external variables are defined external to all functions, and are (potentially) available to all functions. External storage .ne 6 always remains in existence. To make variables external we have to .ul define them external to all functions, and, wherever we want to use them, make a .ul declaration. .E1 main(~) { extern int nchar, hist[ ]; \*.\*.\*. count(~); \*.\*.\*. } .SP .ne 7 count(~) { extern int nchar, hist[ ]; int i, c; \*.\*.\*. } .SP int hist[129]; /\** space for histogram \**/ int nchar; /\** character count \**/ .E2 Roughly speaking, any function that wishes to access an external variable must contain an .UL extern declaration for it. The declaration is the same as others, except for the added keyword .UL extern\*. Furthermore, there must somewhere be a .ul definition of the external variables external to all functions. .PP External variables can be initialized; they are set to zero if not explicitly initialized. In its simplest form, initialization is done by putting the value (which must be a constant) after the definition: .E1 int nchar 0; char flag 'f'; .ft R etc\*. .E2 This is discussed further in a later section. .SP .PP This ends our discussion of what might be called the central core of C. You now have enough to write quite substantial C programs, and it would probably be a good idea if you paused long enough to do so. The rest of this tutorial will describe some more ornate constructions, useful but not essential. .SP .SP .NH Pointers .PP A .ul pointer in C is the address of something. It is a rare case indeed when we care what the specific address itself is, but pointers are a quite common way to get at the contents of something. The unary operator `&' is used to produce the address of an object, if it has one. Thus .E1 int a, b; b = &a; .E2 puts the address of .UL a into .UL b\*. We can't do much with it except print it or pass it to some other routine, because we haven't given .UL b the right kind of declaration. But if we declare that .UL b is indeed a .ul pointer to an integer, we're in good shape: .E1 int a, \**b, c; b = &a; c = \**b; .E2 .UL b contains the address of .UL a and .UL `c .UL = .UL \**b' means to use the value in .UL b as an address, i.e., as a pointer. The effect is that we get back the contents of .UL a, albeit rather indirectly. (It's always the case that .UL `\**&x' is the same as .UL x if .UL x has an address.) .PP The most frequent use of pointers in C is for walking efficiently along arrays. In fact, in the implementation of an array, the array name represents the address of the zeroth element of the array, so you can't use it on the left side of an expression. (You can't change the address of something by assigning to it.) If we say .E1 char \**y; char x[100]; .E2 .UL y is of type pointer to character (although it doesn't yet point anywhere). We can make .UL y point to an element of .UL x by either of .E1 y = &x[0]; y = x; .E2 Since .UL x is the address of .UL x[0] this is legal and consistent. .PP Now .UL `\**y' gives .UL x[0]\*. More importantly, .E1 \**(y+1) gives x[1] \**(y+i) gives x[i] .E2 and the sequence .E1 y = &x[0]; y\*+; .E2 leaves .UL y pointing at .UL x[1]\*. .PP Let's use pointers in a function .UL length that computes how long a character array is. Remember that by convention all character arrays are terminated with a `\\0'. (And if they aren't, this program will blow up inevitably.) The old way: .E1 length(s) char s[ ]; { int n; for( n=0; s[n] != '\\0'; ) n\*+; return(n); } .E2 Rewriting with pointers gives .E1 length(s) char \**s; { int n; for( n=0; \**s != '\\0'; s\*+ ) n\*+; return(n); } .E2 You can now see why we have to say what kind of thing .UL s points to _ if we're to increment it with .UL s\*+ we have to increment it by the right amount. .PP The pointer version is more efficient (this is almost always true) but even more compact is .E1 for( n=0; \**s\*+ != '\\0'; n\*+ ); .E2 The .UL `\**s' returns a character; the .UL `\*+' increments the pointer so we'll get the next character next time around. As you can see, as we make things more efficient, we also make them less clear. But .UL `\**s\*+' is an idiom so common that you have to know it. .PP Going a step further, here's our function .UL strcopy that copies a character array .UL s to another .UL t\*. .E1 strcopy(s,t) char \**s, \**t; { while(\**t\*+ = \**s\*+); } .E2 We have omitted the test against `\\0', because `\\0' is identically zero; you will often see the code this way. (You .ul must have a space after the `=': see section 25.) .PP For arguments to a function, and there only, the declarations .E1 char s[ ]; char \**s; .E2 are equivalent _ a pointer to a type, or an array of unspecified size of that type, are the same thing. .PP If this all seems mysterious, copy these forms until they become second nature. You don't often need anything more complicated. .NH Function Arguments .PP Look back at the function .UL strcopy in the previous section. We passed it two string names as arguments, then proceeded to clobber both of them by incrementation. So how come we don't lose the original strings in the function that called .UL strcopy? .PP As we said before, C is a ``call by value'' language: when you make a function call like .UL f(x), the .ul value of .UL x is passed, not its address. So there's no way to .ul alter .UL x from inside .UL f\*. If .UL x is an array .UL (char .UL x[10]) this isn't a problem, because .UL x .ul is an address anyway, and you're not trying to change it, just what it add     resses. This is why .UL strcopy works as it does. And it's convenient not to have to worry about making temporary copies of the input arguments. .PP But what if .UL x is a scalar and you do want to change it? In that case, you have to pass the .ul address of .UL x to .UL f, and then use it as a pointer. Thus for example, to interchange two integers, we must write .E1 flip(x, y) int \**x, \**y; { int temp; temp = \**x; \**x = \**y; \**y = temp; } .E2 and to call .UL flip, we have to pass the addresses of the variables: .E1 flip (&a, &b); .E2 .NH Multiple Levels of Pointers; Program Arguments .PP When a C program is called, the arguments on the command line are made available to the main program as an argument count .UL argc and an array of character strings .UL argv containing the arguments. Manipulating these arguments is one of the most common uses of multiple levels of pointers (``pointer to pointer to ...''). By convention, .UL argc is greater than zero; the first argument (in .UL argv[0]) is the command name itself. .PP Here is a program that simply echoes its arguments. .E1 main(argc, argv) int argc; char \**\**argv; { int i; for( i=1; i < argc; i\*+ ) printf("%s ", argv[i]); putchar('\\n'); } .E2 Step by step: .UL main is called with two arguments, the argument count and the array of arguments. .UL argv is a pointer to an array, whose individual elements are pointers to arrays of characters. The zeroth argument is the name of the command itself, so we start to print with the first argument, until we've printed them all. Each .UL argv[i] is a character array, so we use a .UL `%s' in the .UL printf\*. .PP You will sometimes see the declaration of .UL argv written as .E1 char \**argv[ ]; .E2 which is equivalent. But we can't use .UL char .UL argv[ .UL ][ .UL ], because both dimensions are variable and there would be no way to figure out how big the array is. .PP Here's a bigger example using .UL argc and .UL argv\*. A common convention in C programs is that if the first argument is `\(mi', it indicates a flag of some sort. For example, suppose we want a program to be callable as .E1 prog -abc arg1 arg2 \*.\*.\*. .E2 where the `\(mi' argument is optional; if it is present, it may be followed by any combination of a, b, and c. .E1 main(argc, argv) int argc; char \**\**argv; { \*.\*.\*. aflag = bflag = cflag = 0; if( argc > 1 && argv[1][0] \*= '-' ) { for( i=1; (c=argv[1][i]) != '\\0'; i\*+ ) if( c\*='a' ) aflag\*+; else if( c\*='b' ) bflag\*+; else if( c\*='c' ) cflag\*+; else printf("%c?\\n", c); --argc; \*+argv; } \*.\*.\*. .E2 .PP There are several things worth noticing about this code. First, there is a real need for the left-to-right evaluation that && provides; we don't want to look at .UL argv[1] unless we know it's there. Second, the statements .E1 --argc; \*+argv; .E2 let us march along the argument list by one position, so we can skip over the flag argument as if it had never existed _ the rest of the program is independent of whether or not there was a flag argument. This only works because .UL argv is a pointer which can be incremented. .NH The Switch Statement; Break; Continue .PP The .UL switch statement can be used to replace the multi-way test we used in the last example. When the tests are like this: .E1 if( c \*= 'a' ) \*.\*.\*. else if( c \*= 'b' ) \*.\*.\*. else if( c \*= 'c' ) \*.\*.\*. else \*.\*.\*. .E2 testing a value against a series of .ul constants, the switch statement is often clearer and usually gives better code. Use it like this: .E1 switch( c ) { case 'a': aflag\*+; break; case 'b': bflag\*+; break; case 'c': cflag\*+; break; default: printf("%c?\\n", c); break; } .E2 The .UL case statements label the various actions we want; .UL default gets done if none of the other cases are satisfied. (A .UL default is optional; if it isn't there, and none of the cases match, you just fall out the bottom.) .PP The .UL break statement in this example is new. It is there because the cases are just labels, and after you do one of them, you .ul fall through to the next unless you take some explicit action to escape. This is a mixed blessing. On the positive side, you can have multiple cases on a single statement; we might want to allow both upper and lower case letters in our flag field, so we could say .E1 case 'a': case 'A': \*.\*.\*. .SP case 'b': case 'B': \*.\*.\*. etc\*. .E2 But what if we just want to get out after doing .UL case .UL `a' ? We could get out of a .UL case of the .UL switch with a label and a .UL goto, but this is really ugly. The .UL break statement lets us exit without either .UL goto or label. .E1 switch( c ) { case 'a': aflag\*+; break; case 'b': bflag\*+; break; \*.\*.\*. } /\** the break statements get us here directly \**/ .E2 The .UL break statement also works in .UL for and .UL while statements _ it causes an immediate exit from the loop. .PP The .UL continue statement works .ul only inside .UL for's and .UL while's; it causes the next iteration of the loop to be started. This means it goes to the increment part of the .UL for and the test part of the .UL while\*. We could have used a .UL continue in our example to get on with the next iteration of the .UL for, but it seems clearer to use .UL break instead. .NH Structures .PP The main use of structures is to lump together collections of disparate variable types, so they can conveniently be treated as a unit. For example, if we were writing a compiler or assembler, we might need for each identifier information like its name (a character array), its source line number (an integer), some type information (a character, perhaps), and probably a usage count (another integer). .E1 char id[10]; int line; char type; int usage; .E2 .PP We can make a structure out of this quite easily. We first tell C what the structure will look like, that is, what kinds of things it contains; after that we can actually reserve storage for it, either in the same statement or separately. The simplest thing is to define it and allocate storage all at once: .E1 struct { char id[10]; int line; char type; int usage; } sym; .E2 .PP This defines .UL sym to be a structure with the specified shape; .UL id, .UL line, .UL type and .UL usage are .ul members of the structure. The way we refer to any particular member of the structure is .E1 structure\(hyname \*. member .E2 as in .E1 sym\*.type = 077; if( sym\*.usage \*= 0 ) \*.\*.\*. while( sym\*.id[j\*+] ) \*.\*.\*. .ft R etc\*. .E2 Although the names of structure members never stand alone, they still have to be unique _ there can't be another .UL id or .UL usage in some other structure. .PP So far we haven't gained much. The advantages of structures start to come when we have arrays of structures, or when we want to pass complicated data layouts between functions. Suppose we wanted to make a symbol table for up to 100 identifiers. We could extend our definitions like .E1 char id[100][10]; int line[100]; char type[100]; int usage[100]; .E2 but a structure lets us rearrange this spread-out information so all the data about a single identifer is collected into one lump: .E1 struct { char id[10]; int line; char type; int usage; } sym[100]; .E2 This makes .UL sym an array of structures; each array element has the specified shape. Now we can refer to members as .E1 sym[i]\*.usage\*+; /\** increment usage of i\(hyth identifier \**/ for( j=0; sym[i]\*.id[j\*+] != '\\0'; ) \*.\*.\*. .ft R etc\*. .E2 Thus to print a list of all identifiers that haven't been used, together with their line number, .E1 for( i=0; i= 0 ) sym[index]\*.usage\*+; /\** already there \*.\*.\*. \**/ else install(newname, newline, newtype); \*.\*.\*. } .SP lookup(s) char \**s; { int i; extern struct { char id[10]; int line; char type; int usage; } sym[ ]; .SP for( i=0; i 0 ) return(i); return(-1); } compar(s1,s2) /\** return 1 if s1\*=s2, 0 otherwise \**/ char \**s1, \**s2; { while( \**s1\*+ \*= \**s2 ) if( \**s2\*+ \*= '\\0' ) return(1); return(0); } .E2 The declaration of the structure in .UL lookup isn't needed if the external definition precedes its use in the same source file, as we shall see in a moment. .PP Now what if we want to use pointers? .E1 struct symtag { char id[10]; int line; char type; int usage; } sym[100], \**psym; psym = &sym[0]; /\** or p = sym; \**/ .E2 This makes .UL psym a pointer to our kind of structure (the symbol table), then initializes it to point to the first element of .UL sym\*. .PP Notice that we added something after the word .UL struct: a ``tag'' called .UL symtag\*. This puts a name on our structure definition s !#$%&'()*o we can refer to it later without repeating the definition. It's not necessary but useful. In fact we could have said .E1 struct symtag { \*.\*.\*. structure definition }; .E2 which wouldn't have assigned any storage at all, and then said .E1 struct symtag sym[100]; struct symtag \**psym; .E2 which would define the array and the pointer. This could be condensed further, to .E1 struct symtag sym[100], \**psym; .E2 .PP The way we actually refer to an member of a structure by a pointer is like this: .E1 ptr -> structure\(hymember .E2 The symbol `\(mi>' means we're pointing at a member of a structure; `\(mi>' is only used in that context. .UL ptr is a pointer to the (base of) a structure that contains the structure member. The expression .UL "ptr\(mi>structure\(hymember" refers to the indicated member of the pointed-to structure. Thus we have constructions like: .E1 psym->type = 1; psym->id[0] = 'a'; .E2 and so on. .PP For more complicated pointer expressions, it's wise to use parentheses to make it clear who goes with what. For example, .E1 struct { int x, \**y; } \**p; p->x\*+ increments x \*+p->x so does this! (\*+p)->x increments p before getting x \**p->y\*+ uses y as a pointer, then increments it \**(p->y)\*+ so does this \**(p\*+)->y uses y as a pointer, then increments p .E2 .tr |. The way to remember these is that .UL \(mi>, .UL | (dot), .UL "( )" and .UL "[ ]" bind very tightly. An expression involving one of these is treated as a unit. .tr || .UL p\(mi>x, .UL a[i], .UL y\*.x and .UL f(b) are names exactly as .UL abc is. .PP If .UL p is a pointer to a structure, any arithmetic on .UL p takes into account the acutal size of the structure. For instance, .UL p\*+ increments .UL p by the correct amount to get the next element of the array of structures. But don't assume that the size of a structure is the sum of the sizes of its members _ because of alignments of different sized objects, there may be ``holes'' in a structure. .PP Enough theory. Here is the lookup example, this time with pointers. .E1 struct symtag { char id[10]; int line; char type; int usage; } sym[100]; .SP main( ) { struct symtag \**lookup( ); struct symtag \**psym; \*.\*.\*. if( (psym = lookup(newname)) ) /\** non-zero pointer \**/ psym -> usage\*+; /\** means already there \**/ else install(newname, newline, newtype); \*.\*.\*. } .SP struct symtag \**lookup(s) char \**s; { struct symtag \**p; for( p=sym; p < &sym[nsym]; p\*+ ) if( compar(s, p->id) > 0) return(p); return(0); } .E2 The function .UL compar doesn't change: .UL `p\(mi>id' refers to a string. .PP In .UL main we test the pointer returned by .UL lookup against zero, relying on the fact that a pointer is by definition never zero when it really points at something. The other pointer manipulations are trivial. .PP The only complexity is the set of lines like .E1 struct symtag \**lookup( ); .E2 This brings us to an area that we will treat only hurriedly _ the question of function types. So far, all of our functions have returned integers (or characters, which are much the same). What do we do when the function returns something else, like a pointer to a structure? The rule is that any function that doesn't return an .UL int has to say explicitly what it does return. The type information goes before the function name (which can make the name hard to see). Examples: .E1 char f(a) int a; { \*.\*.\*. } int \**g( ) { \*.\*.\*. } struct symtag \**lookup(s) char \**s; { \*.\*.\*. } .E2 The function .UL f returns a character, .UL g returns a pointer to an integer, and .UL lookup returns a pointer to a structure that looks like .UL symtag\*. And if we're going to use one of these functions, we have to make a declaration where we use it, as we did in .UL main above. .PP Notice th parallelism between the declarations .E1 struct symtag \**lookup( ); struct symtag \**psym; .E2 In effect, this says that .UL lookup(~) and .UL psym are both used the same way _ as a pointer to a strcture _ even though one is a variable and the other is a function. .NH Initialization of Variables .PP An external variable may be initialized at compile time by following its name with an initializing value when it is defined. The initializing value has to be something whose value is known at compile time, like a constant. .E1 int x 0; /\** "0" could be any constant \**/ int a 'a'; char flag 0177; int \**p &y[1]; /\** p now points to y[1] \**/ .E2 An external array can be initialized by following its name with a list of initializations enclosed in braces: .E1 int x[4] {0,1,2,3}; /\** makes x[i] = i \**/ int y[ ] {0,1,2,3}; /\** makes y big enough for 4 values \**/ char \**msg "syntax error\\n"; /\** braces unnecessary here \**/ char \**keyword[ ]{ "if", "else", "for", "while", "break", "continue", 0 }; .E2 This last one is very useful _ it makes .UL keyword an array of pointers to character strings, with a zero at the end so we can identify the last element easily. A simple lookup routine could scan this until it either finds a match or encounters a zero keyword pointer: .E1 lookup(str) /\** search for str in keyword[ ] \**/ char \**str; { int i,j,r; for( i=0; keyword[i] != 0; i\*+) { for( j=0; (r=keyword[i][j]) \*= str[j] && r != '\\0'; j\*+ ); if( r \*= str[j] ) return(i); } return(-1); } .E2 .NH Scope Rules: Who Knows About What .PP A complete C program need not be compiled all at once; the source text of the program may be kept in several files, and previously compiled routines may be loaded from libraries. How do we arrange that data gets passed from one routine to another? We have already seen how to use function arguments and values, so let us talk about external data. Warning: the words .ul declaration and .ul definition are used precisely in this section; don't treat them as the same thing. .PP A major shortcut exists for making .UL extern declarations. If the definition of a variable appears .ul before its use in some function, no .UL extern declaration is needed within the function. Thus, if a file contains .E1 f1( ) { \*.\*.\*. } .SP int foo; .SP f2( ) { \*.\*.\*. foo = 1; \*.\*.\*. } .SP f3( ) { \*.\*.\*. if ( foo ) \*.\*.\*. } .E2 no declaration of .UL foo is needed in either .UL f2 or or .UL f3, because the external definition of .UL foo appears before them. But if .UL f1 wants to use .UL foo, it has to contain the declaration .E1 f1( ) { extern int foo; \*.\*.\*. } .E2 .PP This is true also of any function that exists on another file _ if it wants .UL foo it has to use an .UL extern declaration for it. (If somewhere there is an .UL extern declaration for something, there must also eventually be an external definition of it, or you'll get an ``undefined symbol'' message.) .PP There are some hidden pitfalls in external declarations and definitions if you use multiple source files. To avoid them, first, define and initialize each external variable only once in the entire set of files: .E1 int foo 0; .E2 You can get away with multiple external definitions on .UC UNIX, but not on .UC GCOS, so don't ask for trouble. Multiple initializations are illegal everywhere. Second, at the beginning of any file that contains functions needing a variable whose definition is in some other file, put in an .UL extern declaration, outside of any function: .E1 extern int foo; .SP f1( ) { \*.\*.\*. } etc\*. .E2 .PP The .UL #include compiler control line, to be discussed shortly, lets you make a single copy of the external declarations for a program and then stick them into each of the source files making up the program. .NH #define, #include .PP C provides a very limited macro facility. You can say .E1 #define name something .E2 and thereafter anywhere ``name'' appears as a token, ``something'' will be substituted. This is particularly useful in parametering the sizes of arrays: .E1 #define ARRAYSIZE 100 int arr[ARRAYSIZE]; \*.\*.\*. while( i\*+ < ARRAYSIZE )\*.\*.\*. .E2 (now we can alter the entire program by changing only the .UL define) or in setting up mysterious constants: .E1 #define SET 01 #define INTERRUPT 02 /\** interrupt bit \**/ #define ENABLED 04 \*.\*.\*. if( x & (SET | INTERRUPT | ENABLED) ) \*.\*.\*. .E2 Now we have meaningful words instead of mysterious constants. (The mysterious operators `&' (AND) and `\(or' (OR) will be covered in the next section.) It's an excellent practice to write programs without any literal constants except in .UL #define statements. .PP There are several warnings about .UL #define\*. First, there's no semicolon at the end of a .UL #define; all the text from the name to the end of the line (except for comments) is taken to be the ``something''. When it's put into the text, blanks are placed around it. Good style typically makes the name in the .UL #define upper case _ this makes parameters more visible. Definitions affect things only after they occur, and only within the file in which they occur. .MC Defines can't be nested. .mc .WS .PP The other control word known to C is .UL #include\*. To include one file in your source at compilation time, say .E1 #include "filename" .E2 This is useful for putting a lot of heavily used data definitions and .UL #define statements at the beginning of a file to be compiled. .MC .UL #include can be nested _ an included file may contain another .UL #include to bring in another file. .mc .NH Bit Operators .PP C has several operators for logical bit-operations. For example, .E1 x = x & 0177; .E2 forms the bit-wise .UC AND of .UL x and 0177, effectively retaining only the last seven bits of .UL x\*. Other operators are .E1 .ft R \(or inclusive OR ^ (circumflex) exclusive OR .tr+~ + (tilde) 1's complement .tr++ ! logical NOT << left shift (as in x<<2) >> right shift (arithmetic on PDP\(hy11; logical on H6070, IBM360) .E2 .NH Assignment Operators .PP An unusual feature of C is that the normal binary operators like `+', `\(mi', etc. can be combined with the assignment operator `=' to form new assignment operators. For example, .E1 .MC x -= 10; .E2 uses the assignment operator `\(mi=' to decrement .UL x by 10, and .E1 x &= 0177 .E2 .mc forms the .UC AND of .UL x and 0177. This convention is a useful notational shortcut, particularly if .UL x is a complicated expression. The classic example is summing an array: .E1 for( sum=i=0; i .DE which defines certain macros and variables. The library containing the routines is `/usr/lib/libS.a,' so the command to compile is .DS cc . . . \-lS .DE All names in the include file intended only for internal use begin with an underscore `\_' to reduce the possibility of collision with a user name. The names intended to be visible outside the package are .IP stdin 10 The name of the standard input file .IP stdout 10 The name of the standard output file .IP stderr 10 The name of the standard error file .IP EOF 10 is actually \-1, and is the value returned by the read routines on end-of-file or error. .IP NULL 10 is a notation for the null pointer, returned by pointer-valued functions to indicate an error .IP FILE 10 expands to `struct \_iob' and is a useful shorthand when declaring pointers to streams. .IP BUFSIZ is a number (viz. 512) of the size suitable for an IO buffer supplied by the user. See .it setbuf, below. .IP "getc, getchar, putc, putchar, feof, ferror, fileno" 10 .br are defined as macros. Their actions are described below; they are mentioned here to point out that it is not possible to redeclare them and that they are not actually functions; thus, for example, they may not have breakpoints set on them. .PP The routines in this package, like the current Portable Library, offer the convenience of automatic buffer allocation and output flushing where appropriate. Absent, however, is the facility of changing the default input and output streams by assigning to `cin' and `cout.' The names `stdin,' stdout,' and `stderr' are in effect constants and may not be assigned to. .SH Calls .PP The routines in the library are in nearly one-to-one correspondence with those in the Portable Library. In several cases the name has been changed. This is an attempt to reduce confusion. If the attempt is judged to fail the names may be made identical even though the arguments may be different. The order of this list generally follows the order used in the Portable Library document. .sr "FILE *fopen(filename, type)" .br char *filename, *type; .br .it Fopen opens the file and, if needed, allocates a buffer for it. .it Filename is a character string specifying the name. .it Type is a character string (not a single character).GHIJKLMNPQRSTUV It may be `"r",' `"w",' or `"a"' to indicate intent to read, write, or append. The value returned is a file pointer. If it is null the attempt to open failed. .sr "FILE *freopen(filename, type, ioptr) .br char *filename, *type; .br FILE *ioptr; .br The stream named by .it ioptr is closed, if necessary, and then reopened as if by .it fopen. If the attempt to open fails, NULL is returned, otherwise .it ioptr, which will now refer to the new file. .PP Often the reopened stream is .it stdin or .it stdout. .sr "int getc(ioptr)" returns the next character from the stream named by .it ioptr, which is a pointer to a file such as returned by .it fopen, or the name .it stdin. The integer EOF is returned on end-of-file or when an error occurs. The null character is a legal character. .sr "int fgetc(ioptr)" is identical in function to `getc' but is a genuine function, not a macro. .sr "putc(c, ioptr)" .it Putc writes the character .it c on the output stream named by .it ioptr, which is a value returned from .it fopen or perhaps .it stdout or .it stderr. The character is returned as value, but EOF is returned on error. .sr "fputc(c, ioptr) Fputc is identical in function to `putc' but is a genuine function, not a macro. .sr fclose(ioptr) The file corresponding to .it ioptr is closed after any buffers are emptied. A buffer allocated by the IO system is freed. .it Fclose is automatic on normal termination of the program. .sr fflush(ioptr) Any buffered information on the (output) stream named by .it ioptr is written out. Output files are normally buffered if and only if they are not directed to the terminal, but .it stderr is unbuffered unless .it setbuf is used. .sr exit(errcode) .it Exit terminates the process and returns its argument as status to the parent. This is a special version of the routine which calls .it fflush for each output file. To terminate without flushing, use .it \_exit. .sr feof(ioptr) returns non-zero when end-of-file has occurred on the specified input stream. .sr ferror(ioptr) returns non-zero when an error has occurred while reading or writing the named stream. The error indication lasts until the file has been closed. .sr "getchar( )" is identical to `getc(stdin)'. .sr "putchar(c)" is identical to `putc(c, stdout)'. .sr "char *gets(s)" reads characters up to a new-line from the standard input. The new-line character is replaced by a null character. It is the user's responsibility to make sure that the character array .it s is large enough. .it Gets returns its argument, or null if end-of-file or error occurred. Note that this routine is not compatible with .it fgets; it is included for downward compatibility. .sr "char *fgets(s, n, ioptr)" reads up to .it n characters from the stream .it ioptr into the character pointer .it s. The read terminates with a new-line character. The new-line character is placed in the buffer followed by a null pointer. The first argument, or a null pointer if error or end-of-file occurred, is returned. .sr puts(s) writes the null-terminated string (character array) .it s on the standard output. A new-line is appended. No value is returned. Note that this routine is not compatible with .it fputs; it is included for downward compatibility. .sr "fputs(s, ioptr)" writes the null-terminated string (character array) on the stream .it s. No new-line is appended. No value is returned. .sr "ungetc(c, ioptr)" The argument character .it c is pushed back on the input stream named by .it ioptr. Only one character may be pushed back. .sr "printf(format, a1, . . .)" .sr "fprintf(ioptr, format, a.ce .ul New C Compiler Features 1. Long and short integers In the interests of portability, C integers now come in three flavours: `long', `short', and just plain `int'. A short integer is 16 bits long on both the Interdata X/32 and X/16, as well as on the PDP-11; a long integer is 32 bits long on any machine; an ordinary int is the "natural" size for the host machine: 16 bits on Interdata X/16 and PDP-11, 32 bits on Interdata X/32. The new type keywords can act rather like adjectives in that `short int' means a 16-bit integer and `long float' means the same as `double'. Or they may stand alone, implying integer types. Long constants are written with a terminating `l' or `L'. E.g. "123L" or "0177777777L" or "0X56789abcdL". The latter is a hex constant, which could also have been short; it is marked by starting with "0X". Every fixed decimal constant larger than 32767 is taken to be long, and so are octal or hex constants larger than 0177777 (0Xffff, or 0XFFFF if you like). A warning is given in such a case since this is actually an incompatibility with the older compiler. Where the constant is just used as an initializer or assigned to something it doesn't matter. If it is passed to a subroutine then the routine will not get what it expected. When a short and a long integer are operands of an arithmetic operator, the short is converted to long (with sign extension). This is true also when a short is assigned to a long. When a long is assigned to a short integer it is truncated at the high order end with no notice of possible loss of significant digits. This is true as well when a long is added to a 16-bit pointer (which includes its usage as a subscript). The conversion rules for expressions involving doubles and floats mixed with longs are the same as those for short integers, .ul mutatis mutandis. A point to note is that constant expressions involving longs are not evaluated at compile time, and may not be used where constants are expected. Thus .br long x {5000L*5000L}; .br is illegal; .br long x {5000*5000}; .br is legal but wrong because the high-order part is lost; but both .br long x 25000000L; .br and .br long x 25.e6; .br are correct and have the same meaning because the double constant is converted to long at compile time. 2. Unsigned integers A new fundamental data type with keyword `unsigned,' is available. It may be used alone: .br unsigned u; .br or as an adjective with `int' .br unsigned int u; .br with the same meaning. There are not yet (or possibly ever) unsigned longs, shorts or chars. The meaning of an unsigned variable is that of an integer modulo 2^n, where n is wordsize of the machine. All operators whose operands are unsigned produce results consistent with this interpretation except division and remainder where the divisor is larger than 2^(n-1)-1; then the result is incorrect. The dividend in an unsigned division may however have any value (i.e. up to 2^n-1) with correct results. Right shifts of unsigned quantities are guaranteed to be logical shifts. When an ordinary integer and an unsigned integer are combined then the ordinary integer is mapped into an integer mod 2^n and the result is unsigned. Thus, for example `u = -1' results in assigning 65535 (on a 16-bit machine) or 4294967295 (on a 32-bit machine) to u. This is mathematically reasonable, and also happens to involve no run-time overhead. When an unsigned integer is assigned to a plain integer, an (undiagnosed) overflow occurs when the unsigned integer exceeds 2^(n-1)-1. It is intended that unsigned integers be used in contexts where previously character pointers were used (artificially and nonportably) to represent unsigned integers. 3. Block structure. A sequence of declarations may now appear at the beginning of any compound statement in {}. The variables declared thereby are local to the compound statement. Any declarations of the same name existing before the block was entered are pushed down for the duration of the block. Just as in functions, as before, auto variables disappear and loWXYZ[\]^`abcdefghijklmnopqrstse their values when the block is left; static variables retain their values. Also according to the same rules as for the declarations previously allowed at the start of functions, if no storage class is mentioned in a declaration the default is automatic. Implementation of inner-block declarations is such that there is no run-time cost associated with using them. 4. Initialization (part 1) This compiler properly handles initialization of structures so the construction struct { char name[8]; char type; float val; } x { "abc", 'a', 123.4 }; compiles correctly. In particular it is recognized that the string is supposed to fill an 8-character array, the `a' goes into a character, and that the 123.4 must be rounded and placed in a single-precision cell. Structures of arrays, arrays of structures, and the like all work; a more formal description of what is done follows. ::= ::= | , | { } | { , } An element is an expression or a comma-separated sequence of elements possibly enclosed in braces. In a brace-enclosed sequence, a comma is optional after the last element. This very ambiguous definition is parsed as described below. "Expression" must of course be a constant expression within the previous meaning of the Act. An initializer for a non-structured scalar is an element with exactly one expression in it. An "aggregate" is a structure or an array. If the initializer for an aggregate begins with a left brace, then the succeeding comma-separated sequence of elements initialize the members of the aggregate. It is erroneous for the number of members in the sequence to exceed the number of elements in the aggregate. If the sequence has too few members the aggregate is padded. If the initializer for an aggregate does not begin with a left brace, then the members of the aggregate are initialized with successive elements from the succeeding comma-separated sequence. If the sequence terminates before the aggregate is filled the aggregate is padded. The "top level" initializer is the object which initializes an external object itself, as opposed to one of its members. The top level initializer for an aggregate must begin with a left brace. If the top-level object being initialized is an array and if its size is omitted in the declaration, e.g. "int a[]", then the size is calculated from the number of elements which initialized it. Short of complete assimilation of this description, there are two simple approaches to the initialization of complicated objects. First, observe that it is always legal to initialize any object with a comma-separated sequence of expressions. The members of every structure and array are stored in a specified order, so the expressions which initialize these members may if desired be laid out in a row to successively, and recursively, initialize the members. Alternatively, the sequences of expressions which initialize arrays or structures may uniformly be enclosed in braces. 5. Initialization (part 2) Declarations, whether external, at the head of functions, or in inner blocks may have initializations whose syntax is the same as previous external declarations with initializations. The only restrictions are that automatic structures and arrays may not be initialized (they can't be assigned either); nor, for the moment at least, may external variables when declared inside a function. The declarations and initializations should be thought of as occurring in lexical order so that forward references in initializations are unlikely to work. E.g., { int a a; int b c; int c 5; ... } Here a is initialized by itself (and its value is thus undefined); b is initialized with the old value of c (which is either undefined or any c declared in an outer block). 6. Bit fields A declarator inside a structure may have the form : which specifies that the object declared is stored in a field the number of bits in which is specified by the constant. If several such things are stacked up next to each other then the compiler allocates the fields from right to left, going to the next word when the new field will not fit. The declarator may also have the form : which allocates an unnamed field to simplify accurate modelling of things like hardware formats where there are unused fields. Finally, : 0 means to force the next field to start on a word boundary. The types of bit fields can be only "int" or "char". The only difference between the two is in the alignment and length restrictions: no int field can be longer than 16 bits, nor any char longer than 8 bits. If a char field will not fit into the current character, then it is moved up to the next character boundary. Both int and char fields are taken to be unsigned (non-negative) integers. Bit-field variables are not quite full-class citizens. Although most operators can be applied to them, including assignment operators, they do not have addresses (i.e. there are no bit pointers) so the unary & operator cannot be applied to them. For essentially this reason there are no arrays of bit field variables. There are three twoes in the implementation: addition (=+) applied to fields can result in an overflow into the next field; it is not possible to initialize bit fields. 7. Macro preprocessor The proprocessor handles `define' statements with formal arguments. The line #define macro(a1,...,an) ...a1...an... is recognized by the presence of a left parenthesis following the defined name. When the form macro(b1,...,bn) is recognized in normal C program text, it is replaced by the definition, with the corresponding .ul bi actual argument string substituted for the corresponding .ul ai formal arguments. Both actual and formal arguments are separated by commas not included in parentheses; the formal arguments have the syntax of names. Macro expansions are no longer surrounded by spaces. Lines in which a replacement has taken place are rescanned until no macros remain. The preprocessor has a rudimentary conditional facility. A line of the form #ifdef name is ignored if `name' is defined to the preprocessor (i.e. was the subject of a `define' line). If name is not defined then all lines through a line of the form #endif are ignored. A corresponding form is #ifndef name ... #endif which ignores the intervening lines unless `name' is defined. Under unix the name `unix' is predefined and replaced by itself to aid writers of C programs which are expected to be transported to other machines with C compilers. In connection with this, there is a new option to the cc command: cc -Dname which causes `name' to be defined to the preprocessor (and replaced by itself). This can be used together with conditional preprocessor statements to select variant versions of a program at compile time. The previous two facilities (macros with arguments, conditional compilation) were actually available in the 6th Edition system, but undocumented. New in this release of the cc command is the ability to nest `include' files. Preprocessor include lines may have the new form #include where the angle brackets replace double quotes. In this case, the file name is prepended with a standard prefix, namely `/usr/include'. In is intended that commonly-used include files be placed in this directory; the convention reduces the dependence on system-specific naming conventions. The standard prefix can be replaced by the cc command option `-I': cc -Iotherdirectory 8. Registers A formal argument may be given the storage class `register.' When this occurs the save sequence copies it from the place the caller left it into a fast register; all usual restrictions on its use are the same as for ordinary register variables. Now any variable inside a function may be declared `register;' if the type is unsuitable, or if there are more than three register declarations, then the compiler makes it `auto' instead. The restriction that the & operator may not be applied to a register remains. 9. Mode declarations A declaration of the form typedef_______ type-specifier declarator ;_ makes the name given in the declarator into the equivalent of a keyword specifying the type which the name would have in an ordinary declaration. Thus typedef int *iptr; makes `iptr' usable in declarations of pointers to integers; subsequently the declarations iptr ip; .br int *ip; would mean the same thing. Type names introduced in this way obey the same scope rules as ordinary variables. The facility is new, experimental, and probably buggy. 10. Top-level static The storage class `static' can be specified in top-level declarations. Names declared thereby are global to the rest of the file in which they appear (except as modified by block structure, see 3 above) but are unconnected with names in programs in other files. This may be useful to systems of library routines which want to keep their internal interfaces hidden. 11. Restrictions The compiler is somewhat stickier about some constructions that used to be accepted. One difference is that external declarations made inside functions are remembered to the end of the file, that is even past the end of the function. The most frequent problem that this causes is that implicit declaration of a function as an integer in one routine, and subsequent explicit declaration of it as another type, is not allowed. This turned out to affect several source programs distributed with the system. It is now required that all forward references to labels inside a function be the subject of a `goto.' This has turned out to affect mainly people who pass a label to the routine `setexit.' In fact a routine is supposed to be passed here, and why a label worked I do not know. In general this compiler makes it more difficult to use label variables. Think of this as a contribution to structured programming. The compiler now checks multiple declarations of the same name more carefully for consistency. It used to be possible to declare the same name to be a pointer to different structures; this is caught. So too are declarations of the same array as having different sizes. The exception is that array declarations with empty brackets may be used in conjunction with a declaration with a specified size. Thus int a[]; int a[50]; is acceptable (in either order). An external array all of whose definitions involve empty brackets is diagnosed as `undefined' by the loader; it used to be taken as having 1 element. .TL A Tour through the UNIX C Compiler .AU "MH 2C517 3770 D. M. Ritchie .AI .MH .OK Languages Computing ..AB ..AE .CS a b c d e f .de II .I \\$1 .R .. .de Op .SH \\$1 \fI\\$2 .IP .. .PP .SH The Intermediate Language .PP Communication between the two phases of the compiler proper is carried out by means of a pair of intermediate files. These files are treated as having identical structure, although the second file contains only the code generated for strings. It is convenient to write strings out separately to reduce the need for multiple location counters in a later assembly phase. .PP The intermediate language is not machine-independent; its structure in a number of ways reflects the fact that C was originally a one-pass compiler chopped in two to reduce the maximum memory requirement. In fact, only the latest version of the compiler has a complete intermediate language at all. Until recently, the first phase of the compiler generated assembly code for those constructions it could deal with, and passed expression parse trees, in absolute binary form, to the second phase for code generation. Now, at least, all inter-phase information is passed in a describable form, and there are no absolute pointers involved, so the coupling between the phases is not so strong. .PP The areas in which the machine (and system) dependencies are most noticeable are .IP 1. Storage allocation for automatic variables and arguments has already been performed, and nodes for such variables refer to them by offset from a display pointer. Type conversion (for example, from integer to pointer) has already occurred using the assumption of byte addressing and 2-byte words. .IP 2. Data representations suitable to the PDP-11 are assumed; in particular, floating point constants are passed as four words in the machine representation. .PP As it happens, each intermediate file is represented as a sequence of binary numbers without any explicit demarcations. It consists of a sequence of conceptual lines, each headed by an operator, and possibly containing various operands. The operators are small numbers; to assist in recognizing failure in synchronization, the high-order byte of each operator word is always the octal number 376. Operands are either 16-bit binary numbers or strings of characters representing names. Each name is terminated by a null character. There is no alignment requirement for numerical operands and so there is no padding after a name string. .PP The binary representation was chosen to avoid the necessity of converting to and from character form and to minimize the size of the files. It would be very easy to make each operator-operand `line' in the file be a genuine, printable line, with the numbers in octal or decimal; this in fact was the representation originally used. .PP The operators fall naturally into two classes: those which represent part of an expression, and all others. Expressions are transmitted in a reverse-Polish notation; as they are being read, a tree is built which is isomorphic to the tree constructed in the first phase. Expressions are passed as a whole, with no non-expression operators intervening. The reader maintains a stack; each leaf of the expression tree (name, constant) is pushed on the stack; each unary operator replaces the top of the stack by a node whose operand is the old top-of-stack; each binary operator replaces the top pair on the stack with a single entry. When the expression is complete there is exactly one item on the stack. Following each expression is a special operator which passes the unique previous expression to the `optimizer' described below and then to the code generator. .PP Here is the list of operators not themselves part of expressions. .LP .Op EOF marks the end of an input file. .Op BDATA "flag data ..." specifies a sequence of bytes to be assembled as static data. It is followed by pairs of words; the first member of the pair is non-zero to indicate that the data continue; a zero flag is not followed by data and terminates the operator. The data bytes occupy the low-order part of a word. .Op WDATA "flag data ..." specifies a sequence of words to be assembled as static data; it is identical to the BDATA operator except that entire words, not just bytes, are passed. .vwxyz{|}Op PROG means that subsequent information is to be compiled as program text. .Op DATA means that subsequent information is to be compiled as static data. .Op BSS means that subsequent information is to be compiled as unitialized static data. .Op SYMDEF name means that the symbol .I name .R is an external name defined in the current program. It is produced for each external data or function definition. .Op CSPACE "name size" indicates that the name refers to a data area whose size is the specified number of bytes. It is produced for external data definitions without explicit initialization. .Op SSPACE size indicates that .I size .R bytes should be set aside for data storage. It is used to pad out short initializations of external data and to reserve space for static (internal) data. It will be preceded by an appropriate label. .Op EVEN is produced after each external data definition whose size is not an integral number of words. It is not produced after strings except when they initialize a character array. .Op NLABEL name is produced just before a BDATA or WDATA initializing external data, and serves as a label for the data. .Op RLABEL name is produced just before each function definition, and labels its entry point. .Op SNAME "name number" is produced at the start of each function for each static variable or label declared therein. Subsequent uses of the variable will be in terms of the given number. The code generator uses this only to produce a debugging symbol table. .Op ANAME "name number" Likewise, each automatic variable's name and stack offset is specified by this operator. Arguments count as automatics. .Op RNAME "name number" Each register variable is similarly named, with its register number. .Op SAVE number produces a register-save sequence at the start of each function, just after its label (RLABEL). .Op SETREG number is used to indicate the number of registers used for register variables. It actually gives the register number of the lowest free register; it is redundant because the RNAME operators could be counted instead. .Op PROFIL is produced before the save sequence for functions when the profile option is turned on. It produces code to count the number of times the function is called. .Op SWIT "deflab line label value ..." is produced for switches. When control flows into it, the value being switched on is in the register forced by RFORCE (below). The switch statement occurred on the indicated line of the source, and the label number of the default location is .I deflab. .R Then the operator is followed by a sequence of label-number and value pairs; the list is terminated by a 0 label. .Op LABEL number generates an internal label. It is referred to elsewhere using the given number. .Op BRANCH number indicates an unconditional transfer to the internal label number given. .Op RETRN produces the return sequence for a function. It occurs only once, at the end of each function. .Op EXPR line causes the expression just preceding to be compiled. The argument is the line number in the source where the expression occurred. .Op NAME "class type name" .Op NAME "class type number" indicates a name occurring in an expression. The first form is used when the name is external; the second when the name is automatic, static, or a register. Then the number indicates the stack offset, the label number, or the register number as appropriate. Class and type encoding is described elsewhere. .Op CON "type value" transmits an integer constant. This and the next two operators occur as part of expressions. .Op FCON "type 4-word-value" transmits a floating constant as four words in PDP-11 notation. .Op SFCON "type value" transmits a floating-point constant whose value is correctly represented by its high-order word in PDP-11 notation. .Op NULL indicates a null argument list of a function call in an expression; call is a binary operator whose second operand is the argument list. .Op CBRANCH "label cond" produces a conditional branch. It is an expression operator, and will be followed by an EXPR. The branch to the label number takes place if the expression's truth value is the same as that of .I cond. .R That is, if .I cond=1 .R and the expression evaluates to true, the branch is taken. .Op binary-operator type There are binary operators corresponding to each such source-language operator; the type of the result of each is passed as well. Some perhaps-unexpected ones are: COMMA, which is a right-associative operator designed to simplify right-to-left evaluation of function arguments; prefix and postfix ++ and \-\-, whose second operand is the increment amount, as a CON; QUEST and COLON, to express the conditional expression as `a?(b:c)'; and a sequence of special operators for expressing relations between pointers, in case pointer comparison is different from integer comparison (e.g. unsigned). .Op unary-operator type There are also numerous unary operators. These include ITOF, FTOI, FTOL, LTOF, ITOL, LTOI which convert among floating, long, and integer; JUMP which branches indirectly through a label expression; INIT, which compiles the value of a constant expression used as an initializer; RFORCE, which is used before a return sequence or a switch to place a value in an agreed-upon register. .SH Expression Optimization .PP Each expression tree, as it is read in, is subjected to a fairly comprehensive analysis. This is performed by the .II optim routine and a number of subroutines; the major things done are .IP 1. Modifications and simplifications of the tree so its value may be computed more efficiently and conveniently by the code generator. .RT .IP 2. Marking each interior node with an estimate of the number of registers required to evaluate it. This register count is needed to guide the code generation algorithm. .PP One thing that is definitely not done is discovery or exploitation of common subexpressions, nor is this done anywhere in the compiler. .PP The basic organization is simple: a depth-first scan of the tree. .II Optim does nothing for leaf nodes (except for automatics; see below), and calls .II unoptim to handle unary operators. For binary operators, it calls itself to process the operands, then treats each operator separately. One important case is commutative and associative operators, which are handled by .II acommute. .PP Here is a brief catalog of the transformations carried out by by .II optim itself. It is not intended to be complete. Some of the transformations are machine-dependent, although they may well be useful on machines other than the PDP-11. .IP 1. As indicated in the discussion of .II unoptim below, the optimizer can create a node type corresponding to the location addressed by a register plus a constant offset. Since this is precisely the implementation of automatic variables and arguments, where the register is fixed by convention, such variables are changed to the new form to simplify later processing. .RT .IP 2. Associative and commutative operators are processed by the special routine .II acommute. .RT .IP 3. After processing by .II acommute, the bitwise & operator is turned into a new .II andn operator; `a & b' becomes `a .II andn ~b'. This is done because the PDP-11 provides no .II and operator, but only .II andn. A similar transformation takes place for `=&'. .RT .IP 4. Relationals are turned around so the more complicated expression is on the left. (So that `2 > f(x)' becomes `f(x) < 2'). This improves code generation since the algorithm prefers to have the right operand require fewer registers than the left. .RT .IP 5. An expression minus a constant is turned into the expression plus the negative constant, and the .II acommute routine is called to take advantage of the properties of addition. .RT .IP 6. Operators with constant operands are evaluated. .RT .IP 7. Right shifts (unless by 1) are turned into left shifts with a negated right operand, since the PDP-11 lacks a general right-shift operator. .RT .IP 8. A number of special cases are simplified, such as division or multiplication by 1, and shifts by 0. .LP The .II unoptim routine performs the same sort of processing for unary operators. .IP 1. `*&x' and `&*x' are simplified to `x'. .RT .IP 2. If .II r is a register and .II c is a constant or the address of a static or external variable, the expressions `*(r+c)' and `*r' are turned into a special kind of name node which expresses the name itself and the offset. This simplifies subsequent processing because such constructions can appear as the the address of a PDP-11 instruction. .RT .IP 3. When the unary `&' operator is applied to a name node of the special kind just discussed, it is reworked to make the addition explicit again; this is done because the PDP-11 has no `load address' instruction. .RT .IP 4. Constructions like `*r++' and `*\-\-r' where .II r is a register are discovered and marked as being implementable using the PDP-11 auto-increment and -decrement modes. .RT .IP 5. If `!' is applied to a relational, the `!' is discarded and the sense of the relational is reversed. .RT .IP 6. Special cases involving reflexive use of negation and complementation are discovered. .RT .IP 7. Operations applying to constants are evaluated. .PP The .II acommute routine, called for associative and commutative operators, discovers clusters of the same operator at the top levels of the current tree, and arranges them in a list: for `a+((b+c)+(d+f))' the list would be`a,b,c,d,e,f'. After each subtree is optimized, the list is sorted in decreasing difficulty of computation; as mentioned above, the code generation algorithm works best when left operands are the difficult ones. The `degree of difficulty' computed is actually finer than the mere number of registers required; a constant is considered simpler than the address of a static or external, which is simpler than reference to a variable. This makes it easy to fold all the constants together, and also to merge together the sum of a constant and the address of a static or external (since in such nodes there is space for an `offset' value). There are also special cases, like multiplication by 1 and addition of 0. .II A special routine is invoked to handle sums of products. .II Distrib is based on the fact that it is better to compute `c1*c2*x + c1*y' as `c1*(c2*x + y)' and makes the divisibility tests required to assure the correctness of the transformation. This transformation is rarely possible with code directly written by the user, but it invariably occurs as a result of the implementation of multi-dimensional arrays. .PP Finally, .II acommute reconstructs a tree from the list of expressions which result. .SH Code Generation .PP The grand plan for code-generation is independent of any particular machine; it depends largely on a set of tables. But this fact does not necessarily make it very easy to modify the compiler to produce code for other machines, both because there is a good deal of machine-dependent structure in the tables, and because in any event such tables are non-trivial to prepare. .PP The arguments to the basic code generation routine .II rcexpr are a pointer to a tree representing an expression, the name of a code-generation table, and the number of a register in which the value of the expression should be placed. .II Rcexpr returns the number of the register in which the value actually ended up; its caller may need to produce a .II mov instruction if the value really needs to be in the given register. There are four code generation tables. .PP .II Regtab is the basic one, which actually does the job described above: namely, compile code which places the value represented by the expression tree in a register. .PP .II Cctab is used when the value of the expression is not actually needed, but instead the value of the condition codes resulting from evaluation of the expression. This table is used, for example, to evaluate the expression after .II if. It is clearly silly to calculate the value (0 or 1) of the expression `a==b' in the context `if (a==b) ... ' .PP The .II sptab table is used when the value of an expression is to be pushed on the stack, for example when it is an actual argument. For example in the function call `f(a)' it is a bad idea to load .II a into a register which is then pushed on the stack, when there is a single instruction which does the job. .PP The .II efftab table is used when an expression is to be evaluated for its side effects, not its value. This occurs mostly for expressions which are statements, which have no value. Thus the code for the statement `a = b' need produce only the approoriate .II mov instruction, and need not leave the value of .II b in a register, while in the expression `a + (b = c)' the value of `b = c' will appear in a register. .PP All of the tables besides .II regtab are rather small, and handle only a relatively few special cases. If one of these subsidiary tables does not contain an entry applicable to the given expression tree, .II rcexpr uses .II regtab to put the value of the expression into a register and then fixes things up; nothing need be done when the table was .II efftab, but a .II tst instruction is produced when the table called for was .II cctab, and a .II mov instruction, pushing the register on the stack, when the table was .II sptab. .PP The .II rcexpr routine itself picks off some special cases, then calls .II cexpr to do the real work. .II Cexpr tries to find an entry applicable to the given tree in the given table, and returns \-1 if no such entry is found, letting .II rcexpr try again with a different table. A successful match yields a string containing both literal characters which are written out and pseudo-operations, or macros, which are expanded. Before studying the contents of these strings we will consider how table entries are matched against trees. .PP Recall that most non-leaf nodes in an expression tree contain the name of the operator, the type of the value represented, and pointers to the subtrees (operands). They also contain an estimate of the number of registers required to evaluate the expression, placed there by the expression-optimizer routines. The register counts are used to guide the code generation process, which is based on the Sethi-Ullman algorithm. .PP The main code generation tables consist of entries each containing an operator number and a pointer to a subtable for the corresponding operator. A subtable consists of a sequence of entries, each with a key describing certain properties of the operands of the operator involved; associated with the key is a code string. Once the subtable corresponding to the operator is found, the subtable is searched linearly until a key is found such that the properties demanded by the key are compatible with the operands of the tree node. A successful match returns the code string; an unsuccessful search, either for the operator in the main table or a compatble key in the subtable, returns a failure indication. .PP The tables are all contained in a file which must be processed to obtain an assembly language program. Thus they are written in a special-purpose language. To provided definiteness to the following discussion, here is an example of a subtable entry. .DS %n,aw F add A2,R .DE The `%' indicates the key; the information following (up to a blank line) specifies the code string. Very briefly, this entry is in the subtable for `+' of .II regtab; the key specifies that the left operand is any integer, character, or pointer expression, and the right operand is any word quantity which is directly addressible (e.g. a variable or constant). The code string calls for the generation of the code to compile the left (first) operand into the current register (`F') and then to produce an `add' instruction which adds the second operand (`A2') to the register (`R'). All of the notation will be explained below. .PP Only three features of the operands are used in deciding whether a match has occurred. They are: .IP 1. Is the type of the operand compatible with that demanded? .RT .IP 2. Is the `degree of difficulty' (in a sense described below) compatible? .RT .IP 3. The table may demand that the operand have a `*' (indirection operator) as its highest operator. .PP As suggested above, the key for a subtable entry is indicated by a `%,' and a comma-separated pair of specifications for the operands. (The second specification is ignored for unary operators). A specification indicates a type requirement by including one of the following letters. If no type letter is present, any integer, character, or pointer operand will satisfy the requirement (not float, double, or long). .IP b A byte (character) operand is required. .RT .IP w A word (integer or pointer) operand is required. .RT .IP f A float or double operand is required. .RT .IP d A double operand is required. .RT .IP l A long (32-bit integer) operand is required. .PP Before discussing the `degree of difficulty' specification, the algorithm has to be explained more completely. .II Rcexpr (and .II cexpr) are called with a register number in which to place their result. Registers 0, 1, ... are used during evaluation of expressions; the maximum register which can be used in this way depends on the number of register variables, but in any event only registers 0 through 4 are available since r5 is used as a stack frame header and r6 (sp) and r7 (pc) have special hardware properties. The code generation routines assume that when called with register .II n as argument, they may use .II n+1, \&... (up to the first register variable) as temporaries. Consider the expression `X+Y', where both X and Y are expressions. As a first approximation, there are three ways of compiling code to put this expression in register .II n. .IP 1. If Y is an addressible cell, (recursively) put X into register .II n and add Y to it. .RT .IP 2. If Y is an expression that can be calculated in .II k registers, where .II k smaller than the number of registers available, compile X into register .II n, Y into register .II n+1, and add register .II n+1 to .II n. .RT .IP 3. Otherwise, compile Y into register .II n, save the result in a temporary (actually, on the stack) compile X into register .II n, then add in the temporary. .PP The distinction between cases 2 and 3 therefore depends on whether the right operand can be compiled in fewer than .II k registers, where .II k is the number of free registers left after registers 0 through .II n are taken: 0 through .II n\-1 are presumed to contain already computed temporary results; .II n will, in case 2, contain the value of the left operand while the right is being evaluated. .PP These considerations should make clear the specification codes for the degree of difficulty, bearing in mind that a number of special cases are also present: .IP z is satisfied when the operand is zero, so that special code can be produced for expressions like `x = 0'. .RT .IP 1 is satisfied when the operand is the constant 1, to optimize cases like left and right shift by 1, which can be done efficiently on the PDP-11. .RT .IP c is satisfied when the operand is a positive (16-bit) constant; this takes care of some special cases in long arithmetic. .RT .IP a is satisfied when the operand is addressible; this occurs not only for variables and constants, but also for some more complicated constructions, such as indirection through a simple variable, `*p++' where .II p is a register variable (because of the PDP-11's auto-increment address mode), and `*(p+c)' where .II p is a register and .II c is a constant. Precisely, the requirement is that the operand refers to a cell whose address can be written as a source or destination of a PDP-11 instruction. .RT .IP e is satisfied by an operand whose value can be generated in a register using no more than .II k registers, where .II k is the number of registers left (not counting the current register). The `e' stands for `easy.' .RT .IP n is satisfied by any operand. The `n' stands for `anything.' .PP These degrees of difficulty are considered to lie in a linear ordering and any operand which satisfies an earlier-mentioned requirement will satisfy a later one. Since the subtables are searched linearly, if a `1' specification is included, almost certainly a `z' must be written first to prevent expressions containing the constant 0 to be compiled as if the 0 were 1. .PP Finally, a key specification may contain a `*' which requires the operand to have an indirection as its leading operator. Examples below should clarify the utility of this specification. .PP Now let us consider the contents of the code string associated with each subtable entry. Conventionally, lower-case letters in this string represent literal information which is copied directly to the output. Upper-case letters generally introduce specific macro-operations, some of which may be followed by modifying information. The code strings in the tables are written with tabs and new-lines used freely to suggest instructions which will be generated; the table-compiling program compresses tabs (using the 0200 bit of the next character) and throws away some of the new-lines. For example the macro `F' is ordinarily written on a line by itself; but since its expansion will end with a new-line, the new-line after `F' itself is dispensable. This is all to reduce the size of the stored tables. .PP The first set of macro-operations is concerned with compiling subtrees. Recall that this is done by the .II cexpr routine. In the following discussion the `current register' is generally the argument register to .II cexpr; that is, the place where the result is desired. The `next register' is numbered one higher than the current register. (This explanation isn't fully true because of complications, described below, involving operations which require even-odd register pairs.) .IP F causes a recursive call to the .II rcexpr routine to compile code which places the value of the first (left) operand of the operator in the current register. .RT .IP F1 generates code which places the value of the first operand in the next register. It is incorrectly used if there might be no next register; that is, if the degree of difficulty of the first operand is not `easy;' if not, another register might not be available. .RT .IP FS generates code which pushes the value of the first operand on the stack, by calling .II rcexpr specifying .II sptab as the table. .LP Analogously, .IP "S, S1, SS" compile the second (right) operand into the current register, the next register, or onto the stack. .LP To deal with registers, there are .IP R which expands into the name of the current register. .RT .IP R1 which expands into the name of the next register. .RT .IP R+ which expands into the the name of the current register plus 1. It was suggested above that this is the same as the next register, except for complications; here is one of them. Long integer variables have 32 bits and require 2 registers; in such cases the next register is the current register plus 2. The code would like to talk about both halves of the long quantity, so R refers to the register with the high-order part and R+ to the low-order part. .RT .IP R\- This is another complication, involving division and mod. These operations involve a pair of registers of which the odd-numbered contains the left operand. .II Cexpr arranges that the current register is odd; the R\- notation allows the code to refer to the next lower, even-numbered register. .LP To refer to addressible quantities, there are the notations: .IP A1 causes generation of the address specified by the first operand. For this to be legal, the operand must be addressible; its key must contain an `a' or a more restrictive specification. .RT .IP A2 correspondingly generates the address of the second operand providing it has one. .PP We now have enough mechanism to show a complete, if suboptimal, table for the + operator on word or byte operands. .DS %n,z F .sp 1 %n,1 F inc R .sp 1 %n,aw F add A2,R .sp 1 %n,e F S1 add R1,R .sp 1 %n,n SS F add (sp)+,R .DE The first two sequences handle some special cases. Actually it turns out that handling a right operand of 0 is unnecessary since the expression-optimizer throws out adds of 0. Adding 1 by using the `increment' instruction is done next, and then the case where the right operand is addressible. It must be a word quantity, since the PDP-11 lacks an `add byte' instruction. Finally the cases where the right operand either can, or cannot, be done in the available registers are treated. .PP The next macro-instructions are conveniently introduced by noticing that the above table is suitable for subtraction as well as addition, since no use is made of the commutativity of addition. All that is needed is substitution of `sub' for `add' and `dec' for 'inc.' Considerable saving of space is achieved by factoring out several similar operations. .IP I is replaced by a string from another table indexed by the operator in the node being expanded. This secondary table actually contains two strings per operator. .RT .IP I\(fm is replaced by the second string in the side table entry for the current operator. .PP Thus, given that the entries for `+' and `\-' in the side table (which is called .II instab) are `add' and `inc,' `sub' and `dec' respectively, the middle of of the above addition table can be written .DS %n,1 F I' R %n,aw F I A2,R .DE and it will be suitable for subtraction, and several other operators, as well. .PP Next, there is the question of character and floating-point operations. .IP B1 generates the letter `b' if the first operand is a character, `f' if it is float or double, and nothing otherwise. It is used in a context like `movB1' which generates a `mov', `movb', or `movf' instruction according to the type of the operand. .RT .IP B2 is just like B1 but applies to the second operand. .RT .IP BE generates `b' if either operand is a character and null otherwise. .RT .IP BF generates `f' if the type of the operator node itself is float or double, otherwise null. .PP For example, there is an entry in .II efftab for the `=' operator .DS %a,aw %ab,a IBE A2,A1 .DE Note first that two key specifications can be applied to the same code string. Next, observe that when a word is assigned to a byte or to a word, or a word is assigned to a byte, a single instruction, a .II mov or .II movb as appropriate, does the job. However, when a byte is assigned to a word, it must pass through a register to implement the sign-extension rules: .DS %a,n S IB1 R,A1 .DE .PP Next, there is the question of handling indirection properly. Consider the expression `X + *Y', where X and Y are expressions, Assuming that Y is more complicated than just a variable, but on the other hand qualifies as `easy' in the context, the expression would be compiled by placing the value of X in a register, that of *Y in the next register, and adding the registers. It is easy to see that a better job can be done by compiling X, then Y (into the next register), and producing the instruction symbolized by `add (R1),R'. This scheme avoids generating the instruction `mov (R1),R1' required actually to place the value of *Y in a register. A related situation occurs with the expression `X + *(p+6)', which exemplifies a construction frequent in structure and array references. The addition table shown above would produce .DS [put X in register R] mov p,R1 add $6,R1 mov (R1),R1 add R1,R .DE when the best code is .DS [put X in R] mov p,R1 add 6(R1),R .DE As we said above, a key specification for a code table entry may require an operand to have an indirection as its highest operator. To make use of the requirement, the following macros are provided. .IP F* the first operand must have the form *X. If in particular it has the form *(Y + c), for some constant .II c, then code is produced which places the value of Y in the current register. Otherwise, code is produced which loads X into the current register. .RT .IP F1* resembles F* except that the next register is loaded. .RT .IP S* resembles F* except that the second operand is loaded. .RT .IP S1* resembles S* except that the next register is loaded. .RT .IP FS* The first operand must have the form `*X'. Push the value of X on the stack. .RT .IP SS* resembles FS* except that it applies to the second operand. .LP To capture the constant that may have been skipped over in the above macros, there are .IP #1 The first operand must have the form *X; if in particular it has the form *(Y + c) for .II c a constant, then the constant is written out, otherwise a null string. .RT .IP #2 is the same as #1 except that the second operand is used. .LP Now we can improve the addition table above. Just before the `%n,e' entry, put .DS %n,ew* F S1* add #2(R1),R .DE and just before the `%n,n' put .DS %n,nw* SS* F add *(sp)+,R .DE When using the stacking macros there is no place to use the constant as an index word, so that particular special case doesn't occur. .PP The constant mentioned above can actually be more general than a number. Any quantity acceptable to the assembler as an expression will do, in particular the address of a static cell, perhaps with a numeric offset. If .II x is an external character array, the expression `x[i+5] = 0' will generate the code .DS mov i,r0 clrb x+5(r0) .DE via the table entry (in the `=' part of .II efftab) .DS %e*,z F I'B1 #1(R) .DE Some machine operations place restrictions on the registers used. The divide instruction, used to implement the divide and mod operations, requires the dividend to be placed in the odd member of an even-odd pair; other peculiarities of multiplication make it simplest to put the multiplicand in an odd-numbered register. There is no theory which optimally accounts for this kind of requirement. .II Cexpr handles it by checking for a multiply, divide, or mod operation; in these cases, its argument register number is incremented by one or two so that it is odd, and if the operation was divide or mod, so that it is a member of a free even-odd pair. The routine which determines the number of registers required estimates, conservatively, that at least two registers are required for a multiplication and three for the other peculiar operators. After the expression is compiled, the register where the result actually ended up is returned. (Divide and mod are actually the same operation except for the location of the result). .PP These operations are the ones which cause results to end up in unexpected places, and this possibility adds a further level of complexity. The simplest way of handling the problem is always to move the result to the place where the caller expected it, but this will produce unnecessary register moves in many simple cases; `a = b*c' would generate .DS mov b,r1 mul c,r1 mov r1,r0 mov r0,a .DE The next thought is used the passed-back information as to where the result landed to change the notion of the current register. While compiling the `=' operation above, which comes from a table entry like .DS %a,e S mov R,A1 .DE it is sufficient to redefine the meaning of `R' after processing the `S' which does the multiply. This technique is in fact used; the tables are written in such a way that correct code is produced. The trouble is that the technique cannot be used in general, because it invalidates the count of the number of registers required for an expression. Consider just `a*b + X' where X is some expression. The algorithm assumes that the value of a*b, once computed, requires just one register. If there are three registers available, and X requires two registers to compute, then this expression will match a key specifying `%n,e'. If a*b is computed and left in register 1, then there are, contrary to expectations, no longer two registers available to compute X, but only one, and bad code will be produced. To guard against this possibility, .II cexpr checks the result returned by recursive calls which implement F, S and their relatives. If the result is not in the expected register, then the number of registers required by the other operand is checked; if it can be done using those registers which remain even after making unavailable the unexpectedly-occupied register, then the notions of the `next register' and possibly the `current register' are redefined. Otherwise a register-copy instruction is produced. A register-copy is also always produced when the current operator is one of those which have odd-even requirements. .PP Finally, there are a few loose-end macro operations and facts about the tables. The operators: .IP V is used for long operations. It is written with an address like a machine instruction; it expands into `adc' (add carry) if the operation is an additive operator, `sbc' (subtract carry) if the operation is a subtractive operator, and disappears, along with the rest of the line, otherwise. Its purpose is to allow common treatment of logical operations, which have no carries, and additive and subtractive operations, which generate carries. .RT .IP T generates a `tst' instruction if the first operand of the tree does not set the condition codes correctly. It is used with divide and mod operations, which require a sign-extended 32-bit operand. The code table for the operations contains an `sxt' (sign-extend) instruction to generate the high-order part of the dividend. .RT .IP H is analogous to the `F' and `S' macros, except that it calls for the generation of code for the current tree (not one of its operands) using .II regtab. It is used in .II cctab for all the operators which, when executed normally, set the condition codes properly according to the result. It prevents a `tst' instruction from being generated for constructions like `if (a+b) ...' since after calculation of the value of `a+b' a conditional branch can be written immediately. .PP All of the discussion above is in terms of operators with operands. Leaves of the expression tree (variables and constants), however, are peculiar in that they have no operands. In order to regularize the matching process, .II cexpr examines its operand to determine if it is a leaf; if so, it creates a special `load' operator whose operand is the leaf, and substitutes it for the argument tree; this allows the table entry for the created operator to use the `A1' notation to load the leaf into a register. .PP Purely to save space in the tables, pieces of subtables can be labelled and referred to later. It turns out, for example, that rather large portions of the the .II efftab table for the `=' and `=+' operators are identical. Thus `=' has an entry .DS %[move3:] %a,aw %ab,a IBE A2,A1 .DE while part of the `=+' table is .DS %aw,aw % [move3] .DE Labels are written as `%[ ... : ]', before the key specifications; references are written with `% [ ... ]' after the key. Peculiarities in the implementation make it necessary that labels appear before references to them. .PP The example illustrates the utility of allowing separate keys to point to the same code string. The assignment code works properly if either the right operand is a word, or the left operand is a byte; but since there is no `add byte' instruction the addition code has to be restricted to word operands. .SH Delaying and reordering .PP Intertwined with the code generation routines are two other, interrelated processes. The first, implemented by a routine called .II delay, is based on the observation that naive code generation for the expression `a = b++' would produce .DS mov b,r0 inc b mov r0,a .DE The point is that the table for postfix ++ has to preserve the value of .II b before incrementing it; the general way to do this is to preserve its value in a register. A cleverer scheme would generate .DS mov b,a inc b .DE .II Delay is called for each expression input to .II rcexpr, and it searches for postfix ++ and \-\- operators. If one is found applied to a variable, the tree is patched to bypass the operator and compiled as it stands; then the increment or decrement itself is done. The effect is as if `a = b; b++' had been written. In this example, of course, the user himself could have done the same job, but more complicated examples are easily constructed, for example `switch (x++)'. An essential restriction is that the condition codes not be required. It would be incorrect to compile `if (a++) ...' as .DS tst a inc a beq ... .DE because the `inc' destroys the required setting of the condition codes. .PP Reordering is a similar sort of optimization. Many cases which it detects are useful mainly with register variables. If .II r is a register variable, the expression `r = x+y' is best compiled as .DS mov x,r add y,r .DE but the codes tables would produce .DS mov x,r0 add y,r0 mov r0,r .DE which is in fact preferred if .II r is not a register. (If .II r is not a register, the two sequences are the same size, but the second is slightly faster.) The scheme is to compile the expression as if it had been written `r = x; r =+ y'. The .II reorder routine is called with a pointer to each tree that .II rcexpr is about to compile; if it has the right characteristics, the `r = x' tree is constructed and passed recursively to .II rcexpr; then the original tree is modified to read `r =+ y' and the calling instance of .II rcexpr compiles that instead. Of course the whole business is itself recursive so that more extended forms of the same phenomenon are handled, like `r = x + y | z'. .PP Care does have to be taken to avoid `optimizing' an expression like `r = x + r' into `r = x; r =+ r'. It is required that the right operand of the expression on the right of the `=' be a ', distinct from the register variable. .PP The second case that .II reorder handles is expressions of the form `r = X' used as a subexpression. Again, the code out of the tables for `x = r = y' would be .DS mov y,r0 mov r0,r mov r0,x .DE whereas if .II r were a register it would be better to produce .DS mov y,r mov r,x .DE When .II reorder discovers that a register variable is being assigned to in a subexpression, it calls .II rcexpr recursively to compile the subexpression, then fiddles the tree passed to it so that the register variable itself appears as the operand instead of the whole subexpression. Here care has to be taken to avoid an infinite regress, with .II rcexpr and .II reorder calling each other forever to handle assignments to registers. .PP A third set of cases treated by .II reorder comes up when any name, not necessarily a register, occurs as a left operand of an assignment operator other than `=' or as an operand of prefix `++' or `\-\-'. Unless condition-code tests are involved, when a subexpression like `(a =+ b)' is seen, the assignment is performed and the argument tree modified so that .II a is its operand; effectively `x + (y =+ z)' is compiled as `y =+ z; x + y'. Similarly, prefix increment and decrement are pulled out and performed first, then the remainder of the expression. .PP Throughout code generation, the expression optimizer is called whenever .II delay or .II reorder change the expression tree. This allows some special cases to be found that otherwise would not be seen. This directory contains nroff input for the UNIX Programmer's Manual (Green Book) and some of the Documents for Use with the UNIX System (Blue Book). Only the documentation which is different for Interdata UNIX is here; for original UNIX documentation see the Bell Labs distribution tape. 20/.-,+*)('&%$#"!      2ba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543212~}|{zyxwvutsrqponmlkjihgfedc222*)('&%$#"!      2\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+2~}|{zyxwvutsrqponmlkjihgfedcba`_^]222$#"!      2VUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%2~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXW222     2PONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"! 2~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQ222     2JIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"! 2|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLK2~}22     2DCBA@?>=<;:9876543210/.-,+*)('&%$#"! 2vutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFE2~}|{zyxw22    2>=<;:9876543210/.-,+*)('&%$#"!  2ponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?2~}|{zyxwvutsrq222876543210/.-,+*)('&%$#"!      2jihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:92~}|{zyxwvutsrqponmlk222210/.-,+*)('&%$#"!      2dcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:98765432~}|{zyxwvutsrqponmlkjihgfe222,+*)('&%$#"!      2^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-2~}|{zyxwvutsrqponmlkjihgfedcba`_222&%$#"!      2XWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('2~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZY222      2RQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!2~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTS222     2LKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"! 2~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONM222     2FEDCBA@?>=<;:9876543210/.-,+*)('&%$#"! 2xwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHG2~}|{zy22     2?>=<;:9876543210/.-,+*)('&%$#"! 'xXP PA@,PA@@Xp(Ї$#PA@&" $PA@#6PA@A@HP@t$ B<'t$ PX@tP$PA@l&tP@tX@\0 @h'CX,@ P@xA@P@!7@P@x$PPA@X@X(C $P@xX-B0RX-XcB0X(#(X P@CXt!5$P@CB$PA@$PX PA@X CX PA@PA2X-B02@&@$P$PA@$P$PA@ &P@pX('P@tX@x#8X@xPAA@ACюp(p(Ї@P@@ 0P@@P@|@P@$@$@X@|A 9@ DP@@ P@@B0Z@B0,A@X@B0 B0@&@@C X@|&P@|CCRX@|&P@|X@|&P@|$CC@LP@&Y 3X8@A@.PPAC08@@!8XP#'XB0&YL!9@&@'@|PXPA#8@&@X X6C2'tXX@ HPXX@ 4PPA&tC\X &D!AC>X@ DP@ &&#8D!Al"D &&#2" ю p,p(ЇX(X,X0C &&D!A " #юp(p(ЇAbAA~!3AA8X@X CX X&P$ &X &P &C)B0.XC >$ &X'P &CN$ & C0 &C4$ &C(CXC0X !3A4XCAP@ B0x$ &C$ &$ &$PA^!8A$ @ C0d&$Q CNAh]B0XXCb$ &&C@P@4&Y 3XC2$@A\ю p@p(ЇX(C0>X@$#4$CD &&#2" X@P@C,X,Y@(!4$CX,XPAz$P@X@$C0P@|PPACx B0>Ӽ  B0PPA\#7P@|$CB&B0$C.PPA,#7P@|$C&B0$#юp(p,Ї X,X0 &Cl &&"<$Cr&B0$C^ C0$CNP@$CB't$P P&PA2&t#6 C$C't$P P&PA&t#6 CV$C&P@ C>&P@ C,&#2"CX & !2"&CB't @#5$P#$P P&PAn&t#3C #'Y@C0PPA#4$C0B $C$AC' ' X@TCnю p,p(ЇX(X,!4$C.ӽ&'C0 & !5X0C" X0#3$#$#юp(p(Ї't$ PX@HPX@DPA@ @&tP@H$P@DX@X@H#3A 0PANюp(p(ЇX($P@l C0 P&A" $ PA юp(p(ЇX@X(X@hC0$Q@lX@lHB$P@l\ &$ & !4>#B0 <- &$ &&CH C: C02\ & 0 & 0 &$Q@l#& #6 `B4@ P@'t  P@ P$PA@"&t#P@юp(C@"p@ h$p@ h$XX]P@X@X#X@ZP@P@%X!$P@%XP@XP@!P@%XP@P@!P@%#!P@%$XP@XP@!P@%XP@XP@X!P@%XP@XP@X!$P@%XP@XP@P@%XP@!$P@%!X'PP@%XP@XP@ X!P@%&" P@(` &P &P&$P@u@u`#юp(p(ЇuD( &&#2" X(X$(uD && && &&&X(ʰX$( && && &&'X PPA'X dP## eded # | HHpt$HɬP t #H t#` pg #`D(`#80G4D" 8.8# `H+X`p*,H T h \\u tt0L% pL0 |Xe,||p( XP@+XP@++!$P@,$%X!$P@,$%XP@+XP@++!P@,$%XP@+XP@++!P@,$%XP@+XP@+X+!P@,$%XP@+XP@+X+!$P@,$%XP@+X'XX+!$P@,$%XP@,XP@,,!$P@,$%XP@,, !$P@,$%XP@,XP@,X,!P@,$%/dev/tapx/dev/mt001234567cdfimortuvwxx ,<\pTape open error Bad usage mode uid gid tapa size date time name End Out of core Pathname too long - %s File ignored Directory checksum /tpboot/usr/mdec/tbootTape read error Tape write error Tape seek error %c %s %s -- Cannot open file Directory overflow %s not found Can't open %s %s -- Phase error Tape overflow Tape overflow %4d entries %4d used %4d free %4d last %s%4d%4d%5d%9d %2d/%2d/%2d %2d:%2d %s %s -- create error %s -- write error ((M:/ESTEDTDay Mon 00 00:00:00 1900 SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec0123456789ABCDEFCDEFLOSXcdeflosx r !! r !! ^% >dhww%tpmxC@$ тЁB  CH~#3@xx }0|@zЂ,PЁPЁ$Ȱ PB'"Ȁ?A4$AC0ɀ-!7PЁ" ҋ&C$A|AC0f氁$HC0HKE!4'"# ʰЃ BCA>$PbP^A#3&" Xŀ!9$X P& :x&icAĐ`&iJ`F`栃JtЃ6?\AhC0ȰX PK'""栃8PxPyPŝ] XĀŀA!ŀZ!#ƀ A ŀ ?$Px&QPX] Xj>&M`xa`!&h-B=C BPMBBpG@P=C MBBp > ? < ; 8G60% #-B =C BP`Hp% )r`'ެeެd)n}$<ެ[ 8ެX@ެW5ެVQA'ެS tE}߾ ```pp` P`p@p```pPp< syrx~vtqw}ߍ|*[agm\bߍ[ kZ`fl! 0X^djY_e`#nI0{Lޱ7=,2ޱ?+1ޱ9F~#$ ޱ%'l# ޱ-Eްް $Ӹ ";C߽ޮ[ެޮ  կ@ްp #sj[agްP [TZ`fUޮ_eްJ]cRX^dSY!fJQWޭ OPV\bVVI$)y;H HD-&n .ެjެiެgެf8$uv7yR$uH|v|v#$/9P9M:9B39;9/-؛w aCw ( nuC-C}/p/$* [{|!Y0z,qwޱ udjpvekCiޱ{Sޱv U[JPV\K;n} =C28>D3G317߽Bޯ6H-߼!'ߺH,9 $tYX$t-xC wtYdYa#D*reD#D KNcOg- z .rZ ⺞ gddddJd@g!Otzffh|vvv&p$*:cio@]jnF\bhA$gmekZ`fl[ad CIOUDJ-39? ,26  R"#@=    c=tbj0  I#-Z!)oRn>;<~~J9?EKI=Dx4%>xj42';8:}|Yf mRX^쏟L8]i!EV  <9⼃$'OLp<y;- k }T |"p{Q$5/xp-r/=RX' I%2.d)D2 $h 40 vE& $o$5 R "s)%;lt 4d u dn}Q oxX ix c$/ e g m s b h n tn|\ f Y _ ` f l r a Sn|>Y Q W ] L R X ^ Mn{ \ Kn{ ~ U [ J P V e O E] T Z I 5 c F 5 ; A G H N 1^D $$v V   >K = $0* |, |     q q!!Խ RԿJNoM+.s~|~%g~"V~iH~ 8>-39?@~&2*,wb;xH V &!`a%f[t"D t"v x a g m \ b h~ l ['% fU ` Zcq e kHg* _u d~YY D J~W C~V^ L R~SK @ F~R 3~Mq 6 < +a * 0~w 5~i &  ~g  %   ~f  $  ~e0 ~d3 ~`Ax ~\7. ~V`h m~O t~Fv d~C C I O P V \~@ =~? H N~>B $w+ ( k  $7lV $1{r $xw ~ku yw- ~f z z1 z F V ٻY =  7 "!v } n}b  ~"+ V {9 |m |a  |ZJ U d$7G7> G3 7& ) &" h )`   ,G : x J  ђ+@ o0 w^  = ڹC  } فq |3 { t" $7|  y  z AQ J%c uAL/ g mA_L a- $xG ~l ~k ~ $y( ~  ~ k ~ m ~ ~ &,. ~ ~}Q ~| x ~ s y o v | q w } r~  n ] c i o p~  VN O MC L{ Kx Jg Jbm I P$...3m62as1boot0c/chicago.cmds-cref)etc(fort'liba&libc%lpd$lpd_melb#ratfor snostdiotroffwgongyacc)READ_ME..3.`makem6.hm61.cm62.cm63.cm64.cm65.cm66.cm67.cinstall..2.as.has1.cas4.cas5.cas6.cas0.cas3.cas7.cREAD_MEas2.cmakeinstallas8.c..1.boot0.s_uboot.s^mdl.s]mkboot.c\uboot-40.s[READ_MEZmakeYinstallXtpboot.s..0.cc.cREAD_MEcpp.ccvoptcvopt.cc1.hc0.hc10.cc11.cc1t.ctablesc02.cc00.cc01.cc03.cc04.cc05.c-c13.c,make+c12.c*install../.tp.hddt1.cddt2.cddt3.cem1.cem2.ctp1.ctp2.ctp3.cREAD_MEmakeinstallmc.c....chmod.cnm.c cp.c dsw.c exit.c kill.c ln.cmv.cnice.cod.cpasswd.crm.csleep.ctee.cesync.cdtime.cctty.cbcal.cafind.c`ld.c_ps.c^READ_ME]rmdir.c\size.c[stty.cZnohup.cYtr.cXpwd.cWprof.cVsort.c..-.,index+src*tabecmn.hecons.hmcons.hccmn.hREAD_MEmakeinstall-..,.ind0.cind1.cind2.c-..+.upost.ccrpost.cdr.cacts.cput.c-..*.atableetablectablemtab.c..&.hsrc.agiobuf.hfREAD_MEmakeinstall#..".lib.rrat.h...doprnt.sfltpr.sffltpr.smalloc.c...JcrossIdatemacHesc.tblGm0Fm0aEm1Dm2Cm3Bm4Am5@mac?reg.tbl>table1=table2 0 && *argv[1] == '-') { argv++; while (*++*argv) switch (**argv) { case 'n': nflg++; continue; case 'c': cflg++; continue; case 'g': gflg++; continue; case 'u': uflg++; continue; ca[i] != p2->name[i]) { if(p1->name[i] > p2->name[i]) a = 1; else a = -1; goto out; } out: return(a*rflg); } printo(v) { register i, n; /*** printf("%c", v<0?'1':'0'); for(i=0; i<5; i++) { printf("%c", ((v>>12)&7)+'0'); v =<<3; } ***/ n = v; if (hflg) for (i=16; i>= 0; i =- 4) putchar("0123456789abcdef"[(n>>i)&15]); else for(i=18; i>=0; i =- 3) putchar(((n>>i)&7) + '0'); } /* * dsw: delete files interactivly * author: ross nealon (uow) */ char c; char cc; char buf[40]; main(argc, argv) char *argv[ ]; { register fd, i; if (argc == 2) if (chdir(argv[1]) < 0) { printf("dsw: can't chdir\n"); exit(1); } fd = open(".", 0); if (fd < 0) { printf("dsw: can't open directory\n"); exit(1); } /* * skip entries for . and .. */ read(fd, buf, 32); for (;;) { i = read(fd, buf, 16); if (!i) { printf("dsw: end of directory\n"); exit(0)ric arg\n"); exit(1); } n = n * 10 + c; } return(n); } 2\n",22); exit(); } /* is there anything to do? */ argp3 = argp[1]; argp4 = argp[2]; if(stat(argp[1], stbuf) < 0){ write(1,"Source file non-existent\n",25); exit(); } /* yes, there is a source. check whether file or directory */ if((stbuf[0].imode & 060000) == 040000){ /* The source is a directory, so we do lots of checking and messing around so as not to get into trouble. This patch of code contains administrative policies rather than system restrictions. */ if((stbuf[0].imode & setmode(0)) ...cvo.cdcopy.cdfi.cal.cexport.cxlib.ccvtask.cimport.clog.cREAD_MEtc.cpress.cmakeattach.cbeep.cbs.ccv.ctm.cinstallrkdump.cse 'r': rflg = -1; continue; case 'p': pflg ++; continue; case 'h': /***/ hflg++; /***/ continue; /***/ default: continue; } argc--; } if (argc==0) fi = open("a.out", 0); else fi = open(*++argv, 0); if(fi < 0) { printf("cannot open input\n"); exit(); } read(fi, buf, sizeof buf); /***/ if(buf[0]!=0407 && buf[0]!=0410 && buf[0]!=0411) { printf("bad format\n"); exit(); } seek(fi, buf[1], 1); /* text */ seek(fi, buf[2], 1); /* data */ if(buf[7] != /* * cp oldfile newfile */ main(argc,argv) char **argv; { static int buf[256]; int fold, fnew, n; register char *p1, *p2, *bp; int mode; if(argc != 3) { write(1, "Usage: cp oldfile newfile\n", 26); exit(1); } if((fold = open(argv[1], 0)) < 0) { write(1, "Cannot open old file.\n", 22); exit(1); } fstat(fold, buf); mode = buf[2]; /* is target a directory? */ if (stat(argv[2], buf+50)>=0 && (buf[52]&060000)==040000) { p1 = argv[1]; p2 = argv[2]; bp = buf+100; while(*bp++ = *p2++; } if (!buf[0] && !buf[1]) continue; retry: printf("%s - ", &buf[2]); cc = c = getchar(); while (cc != '\n') cc = getchar(); switch (c) { case 'y': case 'Y': unlink(&buf[2]); break; case '\n': break; case 'x': case 'X': exit(0); default: goto retry; } } exit(1); } # /* * ln target [ new name ] */ struct ibuf { int dev; /***/ int inum; int iflags; char inl; char iuid; char igid; /***/ char isize0; /***/ int isize; int iaddr[8]; char *ictime[2]; char *imtime[2]; int fill; }; #define DIR 040000 #define FMT 060000 main(argc, argv) char **argv; { static struct ibuf statb; register char *np; if (argc<2) { write(1, "Usage: ln target [ newname ]\n", 29); exit(1); } if (argc==2) { np = argv[1]; while(*np++); while (*--np!='/' && np>argv[1]); == 0) { write(1,"No permission in source directory\n",34); exit(); } if(stat(argp[2], stbuf) >= 0){ write(1,"Directory target exists.\n",25); exit(); } argp1 = argp[1]; argp2 = argp[2]; while(*argp1 == *argp2){ argp1++; if(*argp2++ == 0){ write(1,"???\n",4); exit(); } } while(*argp1)if(*argp1++ == '/'){ write(1,"Directory rename only\n",22); exit(); } while(*argp2)if(*argp2++ == '/'){ write(1,"Directory rename only\n",22); exit(); } if(*--argp1 == '.'){ write(1,"val...dexterny3.cy4.cy5.cy1.cy2.cREAD_MEmain.cyyparse.cyyaccpt.cyyerror.cyyinit.cy0.cinstallmake1) { seek(fi, buf[1], 1); seek(fi, buf[2], 1); /* reloc */ } n = ldiv(0, buf[4], nlsize); /***/ if(n == 0) { printf("no name list\n"); exit(); } nlp = sbrk(nlsize*n); /***/ read(fi, nlp, n*nlsize); /***/ if (pflg==0) qsort(nlp, n, nlsize, compare); /***/ fout = dup(1); close(1); for(i=0; ityp&040)==0) goto out; if(cflg) { if(nlp->name[0] != '_') goto out; for(j=0; j<7; j++) nlp->name[j] = nlp->name[j+1]; nlp->name[7] = '\0'; } j); bp[-1] = '/'; p2 = bp; while(*bp = *p1++) if(*bp++ == '/') bp = p2; argv[2] = buf+100; } if (stat(argv[2], buf+50) >= 0) { if (buf[0]==buf[50] && buf[1]==buf[51]) { write(1, "Copying file to itself.\n", 24); exit(1); } } if ((fnew = creat(argv[2], mode)) < 0) { write(1, "Can't create new file.\n", 23); exit(1); } while(n = read(fold, buf, 512)) { if(n < 0) { write(1, "Read error\n", 11); exit(1); } else if(write(fnew, buf, n) != n){ write(1, "Write error.\n/* exit -- end runcom */ main() { seek(0, 0, 2); } np++; argv[2] = np; } stat(argv[1], &statb); if ((statb.iflags&FMT) == DIR) { write(1, "No directory link\n", 18); exit(1); } if (link(argv[1], argv[2])<0) { write(1, "Can't link\n", 11); exit(1); } exit(0); } ues of B will give rise to dom!\n",37); exit(); } argp2 = argp5 = strbuf; argp1 = argp[1]; while(*argp1) if((*argp2++ = *argp1++) == '/') argp5 = argp2; *argp5 = '.'; argp5[1] = 0; if(stat(strbuf,&stbuf[2]) < 0) { write(1,"Whoops\n",7); exit(); } if((stbuf[2].imode & setmode(2)) == 0) { write(1,"No permission in parent\n",24); exit(); } }else{ /* the source is a file. */ setuid(getuid()); if(stat(argp4, &stbuf[2]) >= 0){ if((stbuf[2].imode & 060000) == 040000){ argp2 = strmain(argc, argv) char **argv; { register i, m; register char *c; int count; if(argc < 3) { printf("arg count\n"); exit(1); } c = argv[1]; m = 0; for(m=0; *c; c++) { if(*c < '0' || *c > '7') { printf("bad mode\n"); exit(1); } m = (m<<3) | *c - '0'; } for(i=2; ityp&037; if(j > 4) j = 1; if(j==0 && nlp->val) j = 5; if(uflg && j!=0) goto out; if(!uflg) { if(j==0) printf(" "); else printo(nlp->val); printf("%c ", (nlp->typ&040? "UATDBC":"uatdbc")[j]); } printf("%.8s\n", nlp); out: nlp++; } flush(); } compare(p1, p2) struct nl *p1, *p2; { register a, i; a = 0; if(nflg) { if(p1->val > p2->val) { a = 1; goto out; } if(p1->val < p2->val) { a = -1; goto out; } } for(i=0; i<8; i++) if(p1->name", 13); exit(1); } } exit(0); } /* * kill [-signo] processid [...] */ main(argc, argv) char **argv; { register char *p; register signo, pid; signo = 9; while (--argc > 0) { if (*(p = *++argv) == '-') { signo = getnum(++p); if (signo <= 0 || signo > 13) { printf("Illegal signal\n"); exit(1); } continue; } pid = getnum(p); if (kill(pid, signo) < 0) printf("%s not found\n", *argv); } } getnum(s) char *s; { register n, c; n = 0; while (c = *s++) { if ((c =- '0') < 0 || c > 9) { printf("Non-nume/* mv [-d] file1 file2 unlink file2 link file1 file2 unlink file1 */ int stbuf[42]; struct sbuf { int dev; int inum; int imode; char nlink; char uid; char gid; char siz0; char *siz1; int addr[8]; int adate[2]; int mdate[2]; }; char strbuf[70]; main(argc,argv) int argc; char *argv[]; { char **argp; char *argp1, *argp2, *argp3, *argp4, *argp5; char *p, *p1, *p2; char place[100]; int i; int status; int b; argp = argv; /* check for correct number of arguments */ if(argc != 3){ write(1,"Usage: mv name1 namebuf; while(*argp2++ = *argp4++); argp2[-1] = '/'; argp4 = argp[1]; argp1 = argp[1]; while(*argp4) if(*argp4++ == '/') argp1 = argp4; while(*argp2++ = *argp1++); argp4 = strbuf; } if(stat(argp4, &stbuf[2]) >= 0){ if((stbuf[0]==stbuf[2]) && (stbuf[1]==stbuf[3])){ write(1,"Files are identical.\n",21); exit(); } b = setmode(2); if((stbuf[2].imode & b) == 0) { printf("%s: %o mode ", argp4, stbuf[2].imode & 07777); i = b = getchar(); while(b != '\n' && b != '\0') b = getchar(); if(i != 'y') exit(); } if(unlink(argp4) < 0){ write(1,"Cannot remove target file.\n",27); exit(); } } } } if(link(argp3, argp4) < 0){ i = fork(); if(i == -1){ write(1,"Try again.\n",11); exit(); } if(i){ while(wait(&status) != i); }else{ p = place; p1 = p; while(*p++ = *argp3++); p2 = p; while(*p++ = *argp4++); execl("/bin/cp","cp", p1, p2, 0); write(1, "no cp\n", 6); exit(1); } if((status & 0377) != 0){ wriint word[16]; char gbuf[512]; int fi; int convt; int base 010; int basem 01000; int max; int gidx; int gcnt; int eof; int addr[2]; int from[2]; int key; int flag; int nword 8; main(argc, argv) char **argv; { extern fout; /***/ int f, k, w, i, a[2]; char *p; fout = dup(1); /***/ argv++; if(argc > 1) { p = *argv; if(*p == '-') { while((i = *p++) != '\0') { switch(i) { case 'o': convt =| 001; f = 6; break; case 'd': convt =| 002; f = 5; break; ca; break; case 020: pre(5); /***/ putch(n>>8); putchar(' '); /***/ putch(n); break; case 040: pre(7); putn(n&0377, 8, 3); putchar(' '); putn((n>>8)&0377, 8, 3); break; } } getw() { int b1, b2; b1 = getc(); if(b1 == -1) { eof = 1; return(0); } b2 = getc(); if(b2 == -1) b2 = 0; return(b2|(b1<<8)); /*** note: bytes reversed for pdp-11 ***/ } getc() { if(gidx >= gcnt) { gcnt = read(fi, gbuf, 512); if(gcnt <= 0) return(-1); gidx = 0; } if(++addr[1] >= basem) {ahi", "shi", "srhl", "slhl", "srha", "slha", "stm", "lm", "stb", "lb", "clb", "al", "wb", "rb", "wh", "rh", "wd", "rd", nil, "ss", "oc", nil, "ts", "svc", "sint", "scp", nil, nil, "la", "tlat", nil, nil, "rrl", "rll", "srl", "sll", "sra", "sla", nil, nil, nil, "ti", "ni", "cli", "oi", "xi", "li", "ci", "ai", "si", nil, nil, nil, nil }; getop(n) { return(mnem[n>>8]); /*** pdp-11 deletions *** switch(n&0170000) { case 0000000: switch(n 0030000: return("bit"); case 0040000: return("bic"); case 0050000: return("bis"); case 0060000: return("add"); case 0070000: switch(n&0177000) { case 0070000: return("mul"); case 0071000: return("div"); case 0072000: return("ash"); case 0073000: return("ashc"); case 0074000: return("xor"); } break; case 0100000: switch(n&0177400) { case 0100000: return("bpl"); case 0100400: return("bmi"); case 0101000: return("bhi"); case 010140te(1,"?\n", 2); exit(); } if(status != 0) exit(); } if(unlink(argp3) < 0){ write(1,"Cannot unlink source file.\n",27); exit(); } } struct { char byte[]; }; putchar(c) { write(1, &c.byte[sizeof c - 1], 1); /***/ } getchar() { char c; if(read(0, &c, 1) != 1) return(0); return(c); } setmode(l) { if((getuid()&0377) == stbuf[l].uid) return(0200); else if((getgid()&0377) == stbuf[l].gid) return(020); else return(02); } se 'a': convt =| 004; f = 4; break; case 'h': convt =| 010; f = 4; break; case 'c': convt =| 020; f = 5; break; case 'b': convt =| 040; f = 7; break; } if(f > max) max = f; } argc--; argv++; } } if(!convt) { max = 6; convt = 1; } if(argc > 1) if(**argv != '+') { fi = open(*argv, 0); if(fi < 0) { printf("cannot open %s\n", *argv); goto done; } argv++; argc--; } if(argc > 1) offset(*arg addr[0]++; addr[1] = 0; } return(gbuf[gidx++]&0377); } putch(c) { c =& 0377; if(c>037 && c<0177 && c!='\\') { putchar(' '); putchar(c); return; } putchar('\\'); switch(c) { case '\0': putchar('0'); break; case '\n': putchar('n'); break; case '\\': putchar('\\'); break; case '\t': putchar('t'); break; default: putchar('?'); } } putn(n, b, c) { if(!c) return; putn(ldiv(0,n,b),b,c-1); if((n=lrem(0,n,b)) > 9) putchar(n-10+'a'); else putchar(n+'0'); } pre(n)*/ char nil[] ""; char *mnem[] { nil, "balr", "btcr", "bfcr", "nr", "clr", "or", "xr", "lr", "cr", "ar", "sr", "mhr", "dhr", nil, nil, "srls", "slls", "chvr", nil, nil, nil, nil, nil, "lpsr", nil, nil, nil, "mr", "dr", nil, nil, "btbs", "btfs", "bfbs", "bffs", "lis", "lcs", "ais", "sis", "ler", "cer", "aer", "ser", "mer", "der", "fxr", "flr", nil, nil, nil, nil, "exhr", nil, nil, nil, nil, nil, nil, nil, nil, nil, ni&0177000) { case 0004000: return("jsr"); case 0077000: return("sob"); } switch(n&0177400) { case 0000400: return("br"); case 0001000: return("bne"); case 0001400: return("beq"); case 0002000: return("bge"); case 0002400: return("blt"); case 0003000: return("bgt"); case 0003400: return("ble"); } switch(n&0177700) { case 0000100: return("jmp"); case 0000300: return("swab"); case 0005000: return("clr"); case 0005100: retur0: return("blos"); case 0102000: return("bvc"); case 0102400: return("bvs"); case 0103000: return("bhis"); case 0103400: return("blo"); case 0104000: return("emt"); case 0104400: return("sys"); } switch(n&0177700) { case 0105000: return("clrb"); case 0105100: return("comb"); case 0105200: return("incb"); case 0105300: return("decb"); case 0105400: return("negb"); case 0105500: return("adcb"); case 0105600: return("sbcb"); /* nice */ int nicarg 4; char *args[100]; char string[1000]; /***/ main(argc, argv) int argc; char *argv[]; { int i; register char **argp, *strp, *p; if(argc > 1 && argv[1][0] == '-') { nicarg = atoi(&argv[1][1]); argc--; argv++; } if(argc < 2) { printf("usage: nice [ -n ] command\n"); exit(1); } argc--; argv++; argp = args; strp = string; for (i=0; i<9; i++) *strp++ = "/usr/bin/"[i]; for(i=0; i 0) if(p[-2] == 'b') { i--; b++; p--; } if(i > 0) if(p[-2] == '.') { i--; base = 10; basem = 1000; } a[0] = 0; for(j=0; i-j>3; j++) { d = s[j]; if(d>='0' && d<='9') a[0] = a[0]*base + d-'0'; } a[1] = 0; for(; i-j>0; j++) { d = s[j]; if(d>='0' && d<='9') a[1] = a[1]*base + d-'0'; } if(b) { i = a[0]*baseml, nil, "sth", "bal", "btc", "bfc", "nh", "clh", "oh", "xh", "lh", "ch", "ah", "sh", "mh", "dh", nil, nil, "st", "am", nil, nil, "n", "cl", "o", "x", "l", "c", "a", "s", "m", "d", "cr12", "cr16", "ste", "ahm", nil, nil, "atl", "abl", "rtl", "rbl", "le", "ce", "ae", "se", "me", "de", nil, nil, nil, "stme", "lme", "lhl", "tbt", "sbt", "rbt", "cbt", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, niln("com"); case 0005200: return("inc"); case 0005300: return("dec"); case 0005400: return("neg"); case 0005500: return("adc"); case 0005600: return("sbc"); case 0005700: return("tst"); case 0006000: return("ror"); case 0006100: return("rol"); case 0006200: return("asr"); case 0006300: return("asl"); case 0006400: return("mark"); case 0006500: return("mfpi"); case 0006600: return("mtpi"); case 0006700: return("sxt"); } swi case 0105700: return("tstb"); case 0106000: return("rorb"); case 0106100: return("rolb"); case 0106200: return("asrb"); case 0106300: return("aslb"); case 0106500: return("mfpd"); case 0106600: return("mfpd"); } break; case 0110000: return("movb"); case 0120000: return("cmpb"); case 0130000: return("bitb"); case 0140000: return("bicb"); case 0150000: return("bisb"); case 0160000: return("sub"); case 0170000: switch(n&01777000) { c nice(nicarg); execv(string+9, args); execv(string+4, args); execv(string, args); printf("%s not found\n", string+9); exit(1); } 4); putn(a[1], base, 3); putchar(' '); } line(a, w, n) int w[]; { int i, f, c; f = 1; for(c=1; c; c=+c) { if((c&convt) == 0) continue; if(f) { puta(a); f = 0; } else for(i=0; i<8; i++) putchar(' '); for(i=0; i= basem) { a[1] =- basem; a[0]++; } } } i = 0; while(a[0] > addr[0]+1) { addr[1] =+ 512; while(addr[1] >= basem) { addr[1] =- basem; addr[0]++; } i++; } seek(fi, i, 3); while(a[0]!=addr[0] || a[1]!=addr[1]) if(getc() == -1) break; } putop(n) { char *p; int i, c; p = getop(n); for(i=0; (c = *p++) != '\0'; i++) putchar(c); for(; i<4; i++) putchar(' '); } /* INTERDATA opcode mnemonics , nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "srls", "slls", "stbr", "lbr", "exbr", "epsr", "wbr", "rbr", "whr", "rhr", "wdr", "rdr", nil, "ssr", "ocr", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "bxh", "bxle", "lpsw", "thi", "nhi", "clhi", "ohi", "xhi", "lhi", "chi", "tch(n&0177740) { case 0000240: return("flag"); } switch(n&0177770) { case 0000200: return("rts"); case 0000230: return("spl"); } switch(n&0177777) { case 0000000: return("halt"); case 0000001: return("wait"); case 0000002: return("rti"); case 0000003: return("bpt"); case 0000004: return("iot"); case 0000005: return("rset"); case 0000006: return("rtt"); } break; case 0010000: return("mov "); case 0020000: return("cmp"); casease 0:0; } break; } *** end of pdp-11 deletions ***/ } # /* * enter a password in the password file * this program should be suid with owner * with an owner with write permission on/etc/passwd */ char *tfile { "/tmp/ptmp" }; char *pfile { "/etc/passwd" }; int tbuf[131]; /***/ int pbuf[131]; /***/ char *uname; /*** user name ***/ char *upass; /*** new password ***/ int echoflg; /*** turn off echo while prompting ***/ main(argc, argv) char **argv; { register u, c; register char *p; if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e') { echoflg+y out and back */ for(;;) { c = getc(pbuf); if(c < 0) { fflush(tbuf); close(pbuf[0]); close(tbuf[0]); tbuf[0] = open(tfile, 0); if(tbuf[0] < 0) { write(2, "Urk\n", 4); goto out; } pbuf[0] = creat(pfile, 0644); if(pbuf[0] < 0) { write(2, "Cannot create /etc/passwd\n", 26); goto out; } while((c = read(tbuf[0], tbuf+1, 512)) > 0) write(pbuf[0], tbuf+1, c); unlink(tfile); exit(0); } putc(c, tbuf); } ill: write(2, "Password file illformed\n", main(argc, argv) char *argv[]; { char *arg; int fflg, rflg; fflg = 0; rflg = 0; while(--argc > 0) { arg = *++argv; if(arg[0] == '-') { if(arg[1] == 'f') { fflg++; continue; } if(arg[1] == 'r') { rflg++; continue; } } rm(arg, fflg, rflg); } } struct stbuf { int dev; int inum; int mode; char nlink; char uid; char gid; char siz0; char siz1; int addr[8]; int adate[2]; int mdate[2]; }; rm(arg, fflg, rflg) char arg[]; { char *p; int buf[20]; int i, b; int open[9] { 1 }; int n 1; int t 0; char in[512]; char out[512]; main(argc,argv) char **argv; { int register r,w,p; struct { int x1[2], type, x2[15]; } buf; fstat(1,&buf); t = (buf.type&060000)==020000; while(argc-->1) { open[n++] = creat(argv[1],0666); if(stat(argv[1],&buf)>=0) if((buf.type&060000)==020000) t++; argv++; } r = w = 0; for(;;) { for(p=0;p<512;) { if(r>=w) { if(t>0&&p>0) break; w = read(0,in,512); r = 0; if(w<=0) { stash(p); return; } execv(command+9, args); execv(command+4, args); execv(command, args); printf("%s not found\n", command+9); exit(1); } signal(2, 1); while(wait(0) != pid); time(tafter); signal(2,0); times(&tbuf); i = tafter[1] - tbefore[1]; if (i < 0) i = ~i + 1; putchar('\n'); ptime("Real", i * 100); ptime("Cpu ", tbuf.usertime[1]); ptime("Sys ", tbuf.systime[1]); } ptime(label, clicks) char *label; { register t; t = clicks; printf("%s", label); pdec(' ', t/(3600*100)); t =% 3600*100; pdec(("%s\n", dayw); cal(m, y, string, 24); for(i=0; i<6*24; i=+24) pstr(string+i, 24); exit(); /* * print out complete year */ xlong: y = number(argv[1]); if(y<1 || y>9999) goto badarg; printf("\n\n\n"); printf(" %d\n", y); printf("\n"); for(i=0; i<12; i=+3) { for(j=0; j<6*72; j++) string[j] = '\0'; printf(" %s", smon[i]); printf(" %s", smon[i+1]); printf(" %s\n", smon[i+2]); printf("%s %s %s\n", dayw, dayw, dayw); cal(i+1, y, string, 72); cal(i+2, y, string+2+; argc--; argv++; } if (argc == 1) getpass(); else if(argc != 3) { write(2, "Usage: passwd [user password]\n", 30); goto bex; } else { uname = argv[1]; upass = argv[2]; } signal(1, 1); signal(2, 1); signal(3, 1); if(stat(tfile, tbuf+20) >= 0) { write(2, "Temporary file busy -- try again\n", 33); goto bex; } tbuf[0] = creat(tfile, 0600); if(tbuf[0] < 0) { write(2, "Cannot create temporary file\n", 29); goto bex; } pbuf[0] = open(pfile, 0); if(pbuf[0] < 0) { write(2, 24); out: unlink(tfile); bex: exit(1); } /* * Prompt for current user's password */ char npass[128]; struct { char name[8]; char tty; char junk[15]; } utbuf; #define ECHO 010 getpass() { register char *p; register fd, ttysave, tty; int ttybuf[3]; /* First find out who it is */ if ((tty = ttyn(0)) == 'x' || (fd = open("/etc/utmp", 0)) < 0) return(1); while (read(fd, &utbuf, sizeof(utbuf)) == sizeof(utbuf)) if (utbuf.tty == tty) { close(fd); uname = utbuf.name; for (p = unam if(stat(arg, buf)) { printf("%s: non existant\n", arg); return; } if((buf->mode & 060000) == 040000) { if(rflg) { i = fork(); if(i == -1) { printf("%s: try again\n", arg); return; } if(i) { while(wait() != i); return; } if(chdir(arg)) { printf("%s: cannot chdir\n", arg); exit(); } p = 0; execl("/etc/glob", "glob", "rm", "-r", fflg? "-f": "*", fflg? "*": p, 0); printf("%s: no glob\n", arg); exit(); } printf("%s: directory\n", arg); } out[p++] = in[r++]; } stash(p); } } stash(p) { int k; int i; int d; d = t ? 10 : p; for(i=0; i'9') return(0); n = n*10 + c-'0'; } return(n); } pstr(str, n) char *str; { register i; register char *s; s = str; i = n; while(i--) if(*s++ == '\0') s[-1] = ' '; i = n+1; while(i--) if(*--s != ' ') break; s[1] = '\"Cannot open /etc/passwd\n", 24); goto out; } goto l1; /* * skip to beginning of next line */ skip: while(c != '\n') { if(c < 0) goto ill; c = getc(pbuf); putc(c, tbuf); } /* * compare user names */ l1: c = getc(pbuf); putc(c, tbuf); if(c < 0) { write(2, "User name not found in password file\n", 37); goto out; } p = uname; while(c != ':') { if(*p++ != c) goto skip; c = getc(pbuf); putc(c, tbuf); } if(*p) goto skip; /* * skip old password */ do { c = getc(pbe; p < &uname[8] && *p != ' '; p++) ; *p = '\0'; /* Prompt for new password (noecho if echoflg set) */ if (echoflg) { gtty(0, &ttybuf); ttysave = ttybuf[2]; ttybuf[2] = ttysave & ~ECHO; stty(0, &ttybuf); } write(0, "New Password: ", 14); read(0, npass, sizeof npass); upass = npass; for (p = npass; p < &npass[sizeof npass -1] && *p != '\n'; p++) ; *p = '\0'; if (echoflg) { ttybuf[2] = ttysave; stty(0, &ttybuf); write(0, "\n", 1); } return; } if(!fflg) { if((getuid()&0377) == buf->uid) b = 0200; else b = 2; if((buf->mode & b) == 0 && ttyn(0) != 'x') { printf("%s: %o mode ", arg, buf->mode); i = b = getchar(); i = b; while(b != '\n' && b != '\0') b = getchar(); if(i != 'y') return; } } if(unlink(arg)) printf("%s: not removed\n", arg); } putchar(c) { char ch; /***/ ch = c; /***/ write(1, &ch, 1); /***/ } getchar() { char c; if(read(0, &c, 1) != 1) return(0); return(c); } main() { sync(); } /* * tty -- print tty number */ char ttyname[] { "ttyx\n" }; main() { register c; if ((c = ttyn(0)) == 'x') write(1, "Not a tty\n", 10); else { ttyname[3] = c; write(1, ttyname, 5); } } 0'; printf("%s\n", str); } char mon[] { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; cal(m, y, p, w) char *p; { register d, i; register char *s; s = p; d = jan1(y); mon[2] = 29; mon[9] = 30; switch((jan1(y+1)+7-d)%7) { /* * non-leap year */ case 1: mon[2] = 28; break; /* * 1752 */ default: mon[9] = 19; break; /* * leap year */ case 2: ; } for(i=1; i= '0' && c <= '9') u = u*10 + c-'0'; if(c < 0) goto ill; } while(c != ':'); c = getuid() & 0377; if(c != 0 &&c != u) { write(2, "Permission denied\n", 18); goto out; } /* * copreturn(0); } close(fd); return(1); } main(argc, argv) char **argv; { int c, n; char *s; n = 0; if(argc < 2) { printf("arg count\n"); exit(); } s = argv[1]; while(c = *s++) { if(c<'0' || c>'9') { printf("bad character\n"); exit(); } n = n*10 + c - '0'; } sleep(n); } /* * time command */ char command[128]; int args[64]; struct { int parenttime[2]; int usertime[2]; int systime[2]; } tbuf; main(argc, argv) char **argv; { int tbefore[2], tafter[2]; register i, pid, c; register char *p; extern fout; fout = 2; if (argc <= 1) exit(1); for (i=0; i<9; i++) command[i] = "/usr/bin/"[i]; for (p = *++argv; c = *p; p++) if (i < 127) command[i++] = c; for (i=0; --argc; i++) if (i < 63) args[i] = *argv++; time(tbefore); if ((pid = fork()) == 0) { char dayw[] { " S M Tu W Th F S" }; char *smon[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; char string[432]; main(argc, argv) char *argv[]; { register y, i, j; int m; if(argc < 2) { printf("usage: cal [month] year\n"); exit(); } if(argc == 2) goto xlong; /* * print out just month */ m = number(argv[1]); if(m<1 || m>12) goto badarg; y = number(argv[2]); if(y<1 || y>9999) goto badarg; printf(" %s %d\n", smon[m-1], y); printf=+ 11; mon[m] =+ 11; } if(i > 9) *s = i/10+'0'; s++; *s++ = i%10+'0'; s++; if(++d == 7) { d = 0; s = p+w; p = s; } } } /* * return day of the week * of jan 1 of given year */ jan1(yr) { register y, d; /* * normal gregorian calendar * one extra day per four years */ y = yr; d = 4+y+(y+3)/4; /* * julian calendar * regular gregorian * less three days per 400 */ if(y > 1800) { d =- (y-1701)/100; d =+ (y-1601)/400; } /* * great calendar changeover instant */ if(y > 1752) d =+ 3; return(d%7); } the arguments */ printf("Odd usage\n"); exit(9); } if(apt,p->s)); /***/ } user(p) struct { int f, u, s; } *p; { return(scomp(statb.iuid,p->u,p->s)); } group(p) struct { int f, u; } *p; { return(p->u == statb.igid); } links(p) struct { int f, link, s; } *p; { return(scomp(statb.inl,p->link,p->s)); } size(p) struct { int f, sz, s; } *p; { register int i; i = statb.isize0 << 23; /***/ i = i | (statb.isize>>9); /***/ return(scomp(i,p->sz,p->s)); } perm(p) struct { int f, per, s; } *p; { int i; i = (p->s=='-') ? p! c) goto RET; sp = str; while((*sp = getchar()) != ':') sp++; *sp = '\0'; i = atoi(str); break; } } } RET: close(fin); fin = 0; return(i); } compstr(s1,s2) char s1[], s2[]; { /* compare strings: */ register char *c1, *c2; c1 = s1; c2 = s2; while(*c1 == *c2) if(*c1++ == '\0') return(0); /* s1 == s2 */ else c2++; return(*c1 > *c2 ? 1 : -1); } int descend(name,goal,func,arg, dentry) int (*func)(); char *name, goal; register struct dentry *dentry; { int dir /* opench(s, p) /* string match as in glob */ char *s, *p; { if (*s=='.' && *p!='.') return(0); return(amatch(s, p)); } amatch(s, p) char *s, *p; { register int cc, scc,k; int c, lc; scc = *s; lc = 077777; switch (c = *p) { case '[': k = 0; while (cc = *++p) { switch (cc) { case ']': if (k) return(amatch(++s, ++p)); else return(0); case '-': k =| lc <= scc & scc <= (cc=p[1]); } if (scc==(lc=cc)) k++; } return(0); case '?': caseq: if(scc) return(amatch(# /* find -- find files in a pathname. Use of find is documented in /usr/man/man1/find.1 . In addition, find has a secret first arg "+" which causes each file name to be printed along with a period if the predicates succeed. */ int randlast; char *pathname; int verbose; struct anode { int (*F)(); struct anode *L, *R; } node[100]; int nn; /* number of nodes */ char *fname, *path; int now[2]; int ap, ac; char **av; struct ibuf { int idev; int inum; int iflags; char inl; char iuid; char igid; /* parse -a */ int and(); int p1; char *na; p1 = e2(); if(compstr(na=nxtarg(),"-a")==0) { randlast--; return(mk(&and,p1,e1())); } else if(*na!=0) --ap; return(p1); } struct anode *e2() { /* parse not (!) */ int not(); char *na; if(randlast) { printf("operand follows operand.\n"); exit(9); } randlast++; if(compstr(na=nxtarg(),"!")==0) return(mk(¬,e3(),0)); else if(*na!=0) --ap; return(e3()); } struct anode *e3() { /* parse parens and predicates */ int exeq(), ok(), glob(), mti     ->per : 03777; /* '-' means only arg bits */ return((statb.iflags & i & 017777) == p->per); } type(p)struct { int f, per, s; } *p; { return((statb.iflags&060000)==p->per); } exeq(p) struct { int f, com; } *p; { return(doex(p->com)); } ok(p) struct { int f, com; } *p; { char c; int yes; yes = 0; printf("%s ... %s ...? ",av[p->com],path); if((c=getchar())=='y') yes = 1; while(c!='\n') c = getchar(); if(yes) return(doex(p->com)); return(0); } /* support functions */ scomp(a,b,s) char s; { /* funny directory*/, offset /* in directory */; int dsize, top; register int i, j, k; char aname[128]; if(stat(name,&statb)<0) { printf("--bad status %s\n",name); return(0); } /* if((statb.iflags&060000)!=040000){ /*not a directory*/ /* if(goal=='f'||goal=='b') /* search goal for files */ /* (*func)(arg,name); return(1); }else if(goal=='d' || goal=='b') /* search goal is directories */ /* (*func)(arg,name); */ (*func)(arg,name); if((statb.iflags&060000)!=040000) return(1); /*** *** A++s, ++p)); return(0); case '*': return(umatch(s, ++p)); case 0: return(!scc); } if (c==scc) goto caseq; return(0); } umatch(s, p) char *s, *p; { if(*p==0) return(1); while(*s) if (amatch(s++,p)) return(1); return(0); } char isize0; char *isize; int iaddr[8]; int iatime[2]; int imtime[2]; } statb; /*** *** Buffers for directory blocks. *** *** Originally dentry[] was an array local to the descend() function. *** Since Interdata unix has no automatic stack growth, the buffers *** were moved out of the function and allocated explicitly. ***/ struct dentry { short dinode; /***/ char dname[14]; }; #define NDENTRY 32 /* no. of entries per block */ #define SDBUF (NDENTRY*sizeof(struct dentry)) struct dentry *me(), atime(), user(), group(), size(), perm(), links(), print(), type(); int p1, i; char *a, *b, s; a = nxtarg(); if(compstr(a,"(")==0) { randlast--; p1 = exp(); a = nxtarg(); if(compstr(a,")")!=0) goto err; return(p1); } else if(compstr(a,"-print")==0) { return(mk(&print,0,0)); } b = nxtarg(); s = *b; if(s=='+') b++; if(compstr(a,"-name")==0) return(mk(&glob,b,0)); else if(compstr(a,"-mtime")==0) return(mk(&mtime,atoi(b),s)); else if(compstr(a,"-atime")==0) return(mk(&at node[nn].L = l; node[nn].R = r; return(&(node[nn++])); } nxtarg() { /* get next arg from command line */ if(ap>=ac) return(""); return(av[ap++]); } find(exlist,fullname) /* execute predicat list with current file */ struct anode *exlist; char *fullname; { register int i; path = fullname; if(verbose) printf("%s",path); for(i=0;fullname[i];++i) if(fullname[i]=='/') fname = &fullname[i+1]; i = (*exlist->F)(exlist); if(verbose) if(i) printf(".\n"); else printf("\n"); } /* execution time functsigned compare */ if(s == '+') return(a > b); if(s == '-') return(a < (b * -1)); return(a == b); } doex(com) { int ccode; int np, i, c; char *nargv[50], *ncom, *na; ccode = np = 0; while (na=av[com++]) { if(compstr(na,";")==0) break; if(compstr(na,"{}")==0) nargv[np++] = path; else nargv[np++] = na; } nargv[np] = 0; if (np==0) return(9); if(fork()) /*parent*/ wait(&ccode); else { /*child*/ execv(nargv[0], nargv, np); i = 0; ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; whllocate directory buffer space ***/ if (dentry >= maxdentry) { if (brk(maxdentry+NDENTRY) < 0) { printf("-- out of core\n"); return(0); } maxdentry += NDENTRY; } top = statb.isize; for(offset=0 ; offset < top ; offset =+ SDBUF) { /* each block */ dsize= SDBUF<(top-offset) ? SDBUF : (top-offset); if((dir=open(name,0))<0) { printf("--cannot open %s\n",name); return(0); } if(offset) seek(dir,offset,0); if(read(dir,dentry,dsize)<0) { printf("--cannot read %s\n",name); re# /* * link editor */ #define SIGINT 2 #define ARCMAGIC 0177545 /*** new archive format magic word ***/ #define OLDARCMAGIC 0177555 /*** old archive format magic word ***/ #define FMAGIC 0407 #define NMAGIC 0410 #define IMAGIC 0411 #define EXTERN 040 #define UNDEF 00 #define ABS 01 #define TEXT 02 #define DATA 03 #define BSS 04 #define COMM 05 /* internal use only */ #define RABS 00 #define RTEXT 02 #define RDATA 04 #define RBSS 06 #define REXT 010 #define RHI 01 /*** high-order halfword ***/ #definedbuf = &end; /* first block allocated */ struct dentry *maxdentry = &end; /* end of last block allocated */ struct anode *exp(), *e1(), *e2(), *e3(), *mk(); main(argc,argv) char *argv[]; { struct anode *exlist; int find(); time(&now); ac = argc; av = argv; ap = 2; pathname = argv[1]; if(compstr(argv[1],"+")==0) { verbose++; ap++; pathname = argv[2]; } else verbose = 0; argv[argc] = 0; if(argc<3) { printf("Insufficient args\n"); exit(9); } if(!(exlist = exp())) { /* parse and compileime,atoi(b),s)); else if(compstr(a,"-user")==0) { if((i=getunum(b)) == -1) { printf("Cannot find user \"%s\"\n",b); exit(9); } return(mk(&user,i,s)); } else if(compstr(a,"-group")==0) return(mk(&group,atoi(b),s)); else if(compstr(a,"-size")==0) return(mk(&size,atoi(b),s)); else if(compstr(a,"-links")==0) return(mk(&links,atoi(b),s)); else if(compstr(a,"-perm")==0) { for(i=0; *b ; ++b) { if(*b=='-') continue; i =<< 3; i = i + (*b - '0'); } return(mk(&perm,i,s)); } elsions */ and(p) struct anode *p; { return(((*p->L->F)(p->L)) && ((*p->R->F)(p->R))?1:0); } or(p) struct anode *p; { return(((*p->L->F)(p->L)) || ((*p->R->F)(p->R))?1:0); } not(p) struct anode *p; { return( !((*p->L->F)(p->L))); } glob(p) struct { int f; char *pat; } *p; { return(gmatch(fname,p->pat)); } print() { printf("%s\n",path); return(1); } mtime(p) struct { int f, t, s; } *p; { return(scomp((now[1]-statb.imtime[1])/86400,p->t,p->s)); /***/ } atime(p) struct { int f, t, s; } *p; { return(scile(c=nargv[0][i]) { ncom[9+i++] = c; } ncom[9+i] = '\0'; execv(ncom+4, nargv, np); execv(ncom, nargv, np); exit(9); } return(ccode ? 0:1); } extern fin; /***/ getunum(s) char *s; { /* find username in /etc/passwd &return num. */ int i; char str[20], *sp, c; i = -1; fin = open("/etc/passwd",0); while(c = getchar()) { if(c=='\n') { sp = str; while((*sp = getchar()) != ':') if(! *sp++) goto RET; *sp = '\0'; if(compstr(str,s)==0) { while((c=getchar()) != ':') if(turn(0); } close(dir); for(i = 0; i < (dsize>>4); ++i) { /* each dir. entry */ if (dentry[i].dinode == 0 || compstr(dentry[i].dname,".")==0 || compstr(dentry[i].dname,"..")==0) continue; if (dentry[i].dinode == -1) break; for(j=0;aname[j]=name[j];++j); if(aname[j-1]!='/') aname[j++] = '/'; for(k=0; (aname[j++]=dentry[i].dname[k]) && k<13; ++k); aname[j] = '\0'; if(descend(aname,goal,func,arg, dentry+NDENTRY)==0) printf("--%s\n",name); } } return(1); } gmat RELFLG 01 #define NROUT 256 #define NSYM 701 /*** was 501 ***/ #define NSYMPR 500 #define RONLY 0400 char premeof[] "Premature EOF"; struct page { int nuser; int bno; int nibuf; short buff[256]; /***/ } page[2]; struct { int nuser; int bno; } fpage; struct stream { short *ptr; /***/ int bno; int nibuf; int size; struct page *pno; }; struct stream text; struct stream reloc; struct archdr { /*** new archive header format ***/ char aname[14]; char auid, agid; long atime; long asize; int amode; } archdr; struct filhdr { int fmagic; int tsize; int dsize; int bsize; int ssize; int entry; int pad; int relflg; } filhdr; struct liblist { int off; int bno; }; struct liblist liblist[NROUT]; struct liblist *libp { liblist }; struct symbol { char sname[8]; int stype; /***/ int svalue; }; struct symbol cursym; struct symbol symtab[NSYM]; struct symbol *hshtab[NSYM+2]; struct symbol *symp { symtab }; struct symbol **local[NSYMPR]; struct symbol *petext; struct symbol *pedata; st continue; /*** *** Change default output file ***/ case 'o': if (++c >= argc) error(1, "No output filename"); ofname = *p++; continue; } load1arg(ap); close(infil); } middle(); setupout(); p = argv+1; libp = liblist; for (c=1; cstype != EXTERN+UNDEF) continue; if (cursym.stype == EXTERN+UNDEF) { if (cursym.svalue > sp->svalue) sp->svalue = cursym.svalue; continue; } if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT) continue; ndef++; sp->stype = cursym.stype; sp->svalue = cursym.svalue; } if (libflg==0 || ndef) { tsize =+16)<<16; /***/ /*** note: the above was originally *** (tsize+0177777) & ~0177777; ***It was changed because of an Interdata assembler bug. ***/ if (iflag) dorigin = 0; corigin = dorigin + dsize; borigin = corigin + csize; nund = 0; for (sp=symtab; spstype) { case EXTERN+UNDEF: errlev =| 01; if (arflag==0 && sp->svalue==0) { if (nund==0) printf("Undefined:\n"); nund++; printf("%.8s\n", sp->sname); } continue; case EXTERN+ABS: default: contior (lp = libp; lp->bno != -1; lp++) { dseek(&text, lp->bno, lp->off, sizeof archdr); mget(&archdr, sizeof archdr); mkfsym(archdr.aname); load2(lp->bno, lp->off + (sizeof archdr) / 2); } libp = ++lp; } load2(bno, off) { register struct symbol *sp; register int *lp, symno; readhdr(bno, off); ctrel = torigin; cdrel =+ dorigin; cbrel =+ borigin; /* * Reread the symbol table, recording the numbering * of symbols for fixing external references. */ lp = local; symno = -1; off =+ (sizeof filt = get(&text); } else if (--text.nibuf < 0) { text.nibuf++; text.size++; t = get(&text); } else t = *text.ptr++ & 0xffff; /***/ if (--reloc.size <= 0) { if (reloc.size < 0) error(1, "Relocation error"); reloc.size++; r = get(&reloc); } else if (--reloc.nibuf < 0) { reloc.nibuf++; reloc.size++; r = get(&reloc); } else r = *reloc.ptr++ & 0xffff; /***/ if (r&01) { /* * Fullword address value: * second relocation bits halfword means * 0 - 24-bit aruct symbol *pend; int xflag; /* discard local symbols */ int Xflag; /* discard locals starting with 'L' */ int rflag; /* preserve relocation bits, don't define common */ int arflag; /* original copy of rflag */ int sflag; /* discard all symbols */ int nflag; /* pure procedure */ int dflag; /* define common even with rflag */ int iflag; /* I/D space separated */ int infil; char *filname; int tsize; int dsize; int bsize; int ssize; int nsym; int torigin; int dorigin; int borigin; int ctrel; int r char *cp; register noff, nbno; cp = acp; if (getfile(cp)==0) { load1(0, 0, 0); return; } nbno = 0; noff = 2; /***/ for (;;) { dseek(&text, nbno, noff, sizeof archdr); if (text.size <= 0) { libp->bno = -1; libp++; return; } mget(&archdr, sizeof archdr); if (load1(1, nbno, noff + (sizeof archdr) / 2)) { libp->bno = nbno; libp->off = noff; libp++; } noff =+ (archdr.asize + sizeof archdr)>>1; nbno =+ (noff >> 8) & 0377; noff =& 0377; } } load1(libflg, bno, of (filhdr.tsize+03) & ~03; /***/ dsize =+ (filhdr.dsize+03) & ~03; /***/ bsize =+ filhdr.bsize; ssize =+ nloc; return(1); } /* * No symbols defined by this library member. * Rip out the hash table entries and reset the symbol table. */ symp = ssymp; while (cp > local) **--cp = 0; return(0); } middle() { register struct symbol *sp; register t, csize; int nund, corigin; petext = *slookup("etext"); /***/ pedata = *slookup("edata"); /***/ pend = *slookup("end"); /***/ /* * If there arenue; case EXTERN+TEXT: sp->svalue =+ torigin; continue; case EXTERN+DATA: sp->svalue =+ dorigin; continue; case EXTERN+BSS: sp->svalue =+ borigin; continue; case EXTERN+COMM: sp->stype = EXTERN+BSS; sp->svalue =+ corigin; continue; } if (sflag || xflag) ssize = 0; bsize =+ csize; nsym = ssize / (sizeof cursym); } setupout() { register char *p; register pid; /***/ if (ofname) { /***/ if ((toutb[0] = creat(ofname, 0666)) < 0) /***/ error(1, "Can't create -o file"); /***/hdr)/2; dseek(&text, bno, off+filhdr.tsize+filhdr.dsize, filhdr.ssize); while (text.size > 0) { symno++; mget(&cursym, sizeof cursym); symreloc(); if ((cursym.stype&EXTERN) == 0) { if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L')) mput(soutb, &cursym, sizeof cursym); continue; } if ((sp = *lookup()) == 0) error(1, "internal error: symbol not found"); if (cursym.stype == EXTERN+UNDEF) { if (lp >= &local[NSYMPR]) error(1, "Local symbol overflow"); *lp++ = symno; *lpddress * nonzero - 32-bit address */ if ((r1 = get(&reloc)) == 0) h = t & 0xff00; t = (t<<16) | get(&text); } switch (r & 016) { case RTEXT: t =+ ctrel; break; case RDATA: t =+ cdrel; break; case RBSS: t =+ cbrel; break; case REXT: sp = lookloc(lp, r); if (sp->stype==EXTERN+UNDEF) { r = (r&01) + ((nsym+(sp-symtab))<<4) + REXT; break; } t =+ sp->svalue; r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1); break; } /*** bit 0 used to mean cdrel; int cbrel; int errlev; int delarg 4; char tfname[] "/tmp/lxyyyyy"; char *ofname; /***/ int toutb[131]; /***/ int doutb[131]; /***/ int troutb[131]; /***/ int droutb[131]; /***/ int soutb[131]; /***/ struct symbol **lookup(); struct symbol **slookup(); main(argc, argv) char **argv; { extern int delexit(); register c; register char *ap, **p; struct symbol **hp; if ((signal(SIGINT, 1) & 01) == 0) signal(SIGINT, delexit); if (argc == 1) exit(4); p = argv + 1; for (c = 1; cDJ9?EK:@ any undefined symbols, save the relocation bits. */ if (rflag==0) for (sp=symtab; spstype==EXTERN+UNDEF && sp->svalue==0 && sp!=pend && sp!=pedata && sp!=petext) { rflag++; dflag = 0; nflag = 0; iflag = 0; sflag = 0; break; } /* * Assign common locations. */ csize = 0; if (dflag || rflag==0) { for (sp=symtab; spstype==EXTERN+UNDEF && (t=sp->svalue)!=0) { t = (t+1) & ~01; sp->svalue = csize; sp->stype = EXTERN+COMM; } else if ((toutb[0] = creat("l.out", 0666)) < 0) error(1, "Can't create l.out"); pid = getpid(); for (p = &tfname[12]; p > &tfname[7];) { *--p = (pid&07) + '0'; pid =>> 3; } tcreat(doutb, 'a'); if (sflag==0 || xflag==0) tcreat(soutb, 'b'); if (rflag) { tcreat(troutb, 'c'); tcreat(droutb, 'd'); } filhdr.fmagic = FMAGIC; if (nflag) filhdr.fmagic = NMAGIC; if (iflag) filhdr.fmagic = IMAGIC; filhdr.tsize = tsize; filhdr.dsize = dsize; filhdr.bsize = bsize; filhdr.ssize = sflag++ = sp; continue; } if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) { printf("%.8s: ", cursym.sname); error(0, "Multiply defined"); } } dseek(&text, bno, off, filhdr.tsize); dseek(&reloc, bno, off+(filhdr.tsize+filhdr.dsize)/2, filhdr.tsize); load2td(lp, ctrel, toutb, troutb); if (filhdr.tsize&03) { /***/ putw(0, toutb); /***/ putw(0, troutb); /***/ } /***/ dseek(&text, bno, off+(filhdr.tsize/2), filhdr.dsize); dseek(&reloc, bno, off+filhdr.tsize+(filhdr.dsize/2), 'pc-relative address' if (r&01) t =- creloc; ***/ if (r&01) { putw(r1? t>>16 : ((t>>16)&0xff)|h, b1); if (rflag) putw(r, b2); r = r1; t =& 0xffff; } putw(t, b1); if (rflag) putw(r, b2); } } finishout() { register n; register short *p; /***/ if (nflag||iflag) { n = torigin; while (n&0377) { /***/ n =+ 2; putw(0, toutb); if (rflag) putw(0, troutb); } } copy(doutb, 'a'); if (rflag) { copy(troutb, 'c'); copy(droutb, 'd'); } if (sflag==0) { if) { filname = 0; ap = *p++; if (*ap == '-') switch (ap[1]) { case 'u': if (++c >= argc) error(1, "Bad 'use'"); if (*(hp = slookup(*p++)) == 0) { *hp = symp; enter(); } continue; case 'l': break; case 'x': xflag++; continue; case 'X': Xflag++; continue; case 'r': rflag++; arflag++; continue; case 's': sflag++; xflag++; continue; case 'n': nflag++; continue; case 'd': dflag++; continue; case 'i': iflag++; f) { register struct symbol *sp, **hp, ***cp; struct symbol *ssymp; int ndef, nloc; readhdr(bno, off); ctrel = tsize; cdrel =+ dsize; cbrel =+ bsize; ndef = 0; nloc = sizeof cursym; cp = local; ssymp = symp; if ((filhdr.relflg&RELFLG)==1) { error(0, "No relocation bits"); return(0); } off =+ (sizeof filhdr)/2 + filhdr.tsize + filhdr.dsize; dseek(&text, bno, off, filhdr.ssize); while (text.size > 0) { mget(&cursym, sizeof cursym); if ((cursym.stype&EXTERN)==0) { if (Xflag==0 || cu csize =+ t; } if (petext && petext->stype==EXTERN+UNDEF) { petext->stype = EXTERN+TEXT; petext->svalue = tsize; } if (pedata && pedata->stype==EXTERN+UNDEF) { pedata->stype = EXTERN+DATA; pedata->svalue = dsize; } if (pend && pend->stype==EXTERN+UNDEF) { pend->stype = EXTERN+BSS; pend->svalue = bsize; } } /* * Now set symbols to their final value */ if (nflag || iflag) tsize = (tsize + 0377) & ~0377; /***/ dorigin = tsize; if (nflag) dorigin = ((tsize+0177777)>>? 0: (ssize + (sizeof cursym)*(symp-symtab)); filhdr.entry = 0; filhdr.pad = 0; filhdr.relflg = (rflag==0); mput(toutb, &filhdr, sizeof filhdr); return; } tcreat(buf, letter) int *buf; { tfname[6] = letter; if ((buf[0] = creat(tfname, RONLY)) < 0) error(1, "Can't create temp"); } load2arg(acp) char *acp; { register char *cp; register struct liblist *lp; cp = acp; if (getfile(cp) == 0) { while (*cp) cp++; while (cp >= acp && *--cp != '/'); mkfsym(++cp); load2(0, 0); return; } ffilhdr.dsize); load2td(lp, cdrel, doutb, droutb); if (filhdr.dsize&03) { /***/ putw(0, doutb); /***/ putw(0, droutb); /***/ } /***/ torigin =+ (filhdr.tsize+03) & ~03; /***/ dorigin =+ (filhdr.dsize+03) & ~03; /***/ borigin =+ filhdr.bsize; } load2td(lp, creloc, b1, b2) int *lp; { register r, t; register struct symbol *sp; register r1, h; for (;;) { /* * The pickup code is copied from "get" for speed. */ if (--text.size <= 0) { if (text.size < 0) break; text.size++; (xflag==0) copy(soutb, 'b'); for (p=symtab; p < symp;) putw(*p++, toutb); } fflush(toutb); close(toutb[0]); /***/ if (!ofname) { unlink("a.out"); link("l.out", "a.out"); } delarg = errlev; delexit(); } delexit() { register c; unlink("l.out"); for (c = 'a'; c <= 'd'; c++) { tfname[6] = c; unlink(tfname); } if (delarg==0) /***/ chmod(ofname? ofname: "a.out", 0777); exit(delarg); } copy(buf, c) int *buf; { register f, n; register short *p; /***/ fflush(buf); close(buf[0]); tfname[6] = c; f = open(tfname, 0); while ((n = read(f, doutb, 512)>>1) > 0) { p = doutb; do putw(*p++, toutb); while (--n); } close(f); } mkfsym(s) char *s; { if (sflag || xflag) return; cp8c(s, cursym.sname); cursym.stype = 037; cursym.svalue = torigin; mput(soutb, &cursym, sizeof cursym); } mget(aloc, an) short *aloc; /***/ { register n; register short *p, *loc; /***/ n = an; n =>> 1; loc = aloc; if ((text.nibuf =- n) >= 0) { if ((text.size =- n) > 0) { p = text.plib/libXXXXXXXXXXX"; /***/ cpp = &cp[8]; /***/ for (app = &acp[2]; c = *app; app++) /***/ if (cpp < &cp[17]) /***/ *cpp++ = c; /***/ if (app == &acp[2]) /***/ *cpp++ = 'a'; /***/ cpp[0] = '.'; cpp[1] = 'a'; cpp[2] = '\0'; } filname = cp; if ((infil = open(cp, 0)) < 0) error(1, "cannot open"); page[0].bno = page[1].bno = -1; page[0].nuser = page[1].nuser = 0; text.pno = reloc.pno = &fpage; fpage.nuser = 2; dseek(&text, 0, 0, 4); /***/ if (text.size <= 0) error(1, premeof); get(&texttch"); } readhdr(bno, off) { register st, sd; dseek(&text, bno, off, sizeof filhdr); mget(&filhdr, sizeof filhdr); if (filhdr.fmagic != FMAGIC) /***/ error(1, filhdr.fmagic == OLDARCMAGIC? "Old format archive": /***/ "Bad format"); st = (filhdr.tsize+01) & ~01; filhdr.tsize = st; cdrel = -st; sd = (filhdr.dsize+01) & ~01; cbrel = - (st+sd); filhdr.bsize = (filhdr.bsize+01) & ~01; } cp8c(from, to) char *from, *to; { register char *f, *t, *te; f = from; t = to; te = t+8; while ((*t++ = * { ap = argv[1]; while (*ap) switch (*ap++) { case 'a': aflg++; break; case 't': tflg++; break; case 'x': xflg++; break; case 'l': lflg++; break; case 'k': kflg++; break; } } if(chdir("/dev") < 0) { printf("cannot change to /dev\n"); done(); } setup(&nl[0], "_proc"); setup(&nl[1], "_swapdev"); nlist(argc>2? argv[2]:"/unix", nl); if (nl[0].type==0) { printf("No namelist\n"); return; } coref = "/dev/mem"; if(kflg) coref = "/usr/sys/core";dir_n[14]; } *p; register i, c; int f; char dbuf[512]; int sbuf[20]; f = open("/dev", 0); if(f <0) { printf("cannot open /dev\n"); done(); } /*** swap = -1; ***/ swap = open("/dev/swap", 0); if (swap < 0) { printf("Can't find /dev/swap\n"); done(); } c = 0; loop: i = read(f, dbuf, 512); if(i <= 0) { close(f); /*** if(swap < 0) { printf("no swap device\n"); done(); } ***/ ndev = c; return; } while(i < 512) dbuf[i++] = 0; for(p= dbuf; p < dbuf+512; p++) { if((p--1) { cp = ip+1; if (*cp==0) cp++; nbad = 0; for (cp1 = cp; cp1 < &stbuf[128]; cp1++) { /***/ c = *cp1; if (c==0) *cp1 = ' '; else if (c < ' ' || c > 0176) { if (++nbad >= 5) { *cp1++ = ' '; break; } *cp1 = '?'; } } while (*--cp1==' ') *cp1 = 0; printf(lflg?" %.16s":" %.64s", cp); return(1); } } return(0); } done() { fflush(obuf); exit(); } putchar(c) { putc(c, obuf); } /*** dummy nlist to patch in address of proc **tr; do *loc++ = *p++; while (--n); text.ptr = p; return; } else text.size =+ n; } text.nibuf =+ n; do { *loc++ = get(&text); } while (--n); } mput(buf, aloc, an) short *aloc; /***/ { register short *loc; /***/ register n; loc = aloc; n = an>>1; do { putw(*loc++, buf); /***/ } while (--n); } dseek(asp, ab, o, s) { register struct stream *sp; register struct page *p; register b; int n; sp = asp; b = ab + (o>>8); o =& 0377; --sp->pno->nuser; if ((p = &page[0])); /***/ return(get(&text) == ARCMAGIC); } struct symbol **lookup() { int i; register struct symbol **hp; register char *cp, *cp1; i = 0; for (cp=cursym.sname; cp < &cursym.sname[8];) i = (i<<1) + *cp++; for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) { cp1 = (*hp)->sname; for (cp=cursym.sname; cp < &cursym.sname[8];) if (*cp++ != *cp1++) goto no; break; no: if (++hp >= &hshtab[NSYM+2]) hp = hshtab; } return(hp); } struct symbol **slookup(s) char *s; { cp8c(s, cursym.sf++) && tdir_ino[0] | p->dir_ino[1]) == 0) /***/ continue; if(p->dir_n[0] == 't' && p->dir_n[1] == 't' && p->dir_n[2] == 'y' && p->dir_n[4] == 0 && p->dir_n[3] != 0) { if(stat(p->dir_n, sbuf) < 0) continue; devc[c] = p->dir_n[3]; devl[c] = sbuf->iaddr[0]; c++; continue; } /*** if(swap >= 0) continue; if(stat(p->dir_n, sbuf) < 0) continue; if((sbuf->iflags & 060000) != 060000) continue; if(sbuf->iaddr[0] == nl[1].value) swap = open(p->dir_n, 0); ***/ */ nlist(fd, np) struct namelist *np; { np[0].type = 1; } ->bno!=b && (p = &page[1])->bno!=b) if (p->nuser==0 || (p = &page[0])->nuser==0) { if (page[0].nuser==0 && page[1].nuser==0) if (page[0].bno < page[1].bno) p = &page[0]; p->bno = b; seek(infil, b, 3); if ((n = read(infil, p->buff, 512)>>1) < 0) n = 0; p->nibuf = n; } else error(1, "No pages"); ++p->nuser; sp->bno = b; sp->pno = p; sp->ptr = p->buff + o; if (s != -1) sp->size = (s>>1); if ((sp->nibuf = p->nibuf-o) <= 0) sp->size = 0; } get(asp) struct stream *aspname); cursym.stype = EXTERN+UNDEF; cursym.svalue = 0; return(lookup()); } enter() { register struct symbol *sp; if ((sp=symp) >= &symtab[NSYM]) error(1, "Symbol table overflow"); cp8c(cursym.sname, sp->sname); sp->stype = cursym.stype; sp->svalue = cursym.svalue; symp++; return(sp); } symreloc() { switch (cursym.stype) { case TEXT: case EXTERN+TEXT: cursym.svalue =+ ctrel; return; case DATA: case EXTERN+DATA: cursym.svalue =+ cdrel; return; case BSS: case EXTERN+BSS: cur# /*** *** Temporary vversion without nlist() *** - Location x'400' in /dev/mem is used to locate the proc table *** in memory. *** - Also, "/dev/swap" must be an alias of the swap device. ***/ /* * ps - process status * examine and print certain things about processes */ #include "/usr/sys/param.h" #include "/usr/sys/proc.h" #include "/usr/sys/tty.h" #include "/usr/sys/user.h" struct namelist { char name[8]; int type; char *value; } nl[3]; struct proc proc[NPROC]; struct tty tty;ontinue; if (proc[i].p_ttyp==0) { if (xflg==0) continue; c = '?'; } else { for(c=0; cnibuf < 0) { dseek(sp, sp->bno+1, 0, -1); --sp->nibuf; } if (--sp->size <= 0) { if (sp->size < 0) error(1, premeof); ++fpage.nuser; --sp->pno->nuser; sp->pno = &fpage; } return(*sp->ptr++ & 0xffff); /***/ } getfile(acp) char *acp; { register char *cp; /***/ register char *cpp, *app; register c; cp = acp; archdr.aname[0] = '\0'; if (cp[0]=='-' && cp[1]=='l') { /*** *** Allow multi-character lib names ***/ /***/ cp = "/sym.svalue =+ cbrel; return; case EXTERN+UNDEF: return; } if (cursym.stype&EXTERN) cursym.stype = EXTERN+ABS; } error(n, s) char *s; { if (filname) { printf("%s", filname); if (archdr.aname[0]) printf("(%.8s)", archdr.aname); printf(": "); } printf("%s\n", s); if (n) delexit(); errlev = 2; } lookloc(alp, r) { register int *clp, *lp; register sn; lp = alp; sn = (r>>4) & 07777; for (clp=local; clp1) else printf(" "); if (lflg) { printf("%3o %c%4d", proc[i].p_flag, "0SWRIZT"[proc[i].p_stat], puid); } printf("%6d", proc[i].p_pid); /***/ if (lflg) { printf("%4d%6x%4d", proc[i].p_pri, proc[i].p_addr, (proc[i].p_size+3)>>2); /***/ if (proc[i].p_wchan) printf("%6x", proc[i].p_wchan); else /***/ printf(" "); } if (proc[i].p_stat==5) printf(" "); else prcom(i); printf("\n"); } done(); } getdev() { register struct { char dir_ino[2]; char } goto loop; } setup(p, s) char *p, *s; { while (*p++ = *s++); } prcom(i) { int baddr, laddr, mf; register int *ip; register char *cp, *cp1; int c, nbad; baddr = 0; if (proc[i].p_flag&SLOAD) { baddr = proc[i].p_addr; /***/ mf = mem; } else { baddr = proc[i].p_addr<<1; /***/ mf = swap; } baddr =+ proc[i].p_size - 2; /***/ baddr =<< 8; /***/ seek(mf, baddr, 0); /***/ if (read(mf, stbuf, 512) != 512) return(0); for (ip = &stbuf[128]; ip > &stbuf[0];) { /***/ if (*--ip == /* * rmdir dirname [dirname...] */ int uid; int gid; struct { int dev; int inode; int modes; char nlinks; char uid; char gid; char size0; int size; int addr[8]; int actime[2]; int modtime[2]; } statbuff; main(argc, argv) char **argv; { if (argc<2) { printf("Usage: rmdir dirname [dirname...]\n"); exit(1); } gid = getgid() & 0377; uid = getuid() & 0377; while (--argc) rmdir(*++argv); } rmdir(pathname) char *pathname; { char buff[100]; char dirbuff[16]; register char *p, *q, *pdir; register fd, m; /* * Copy filename to buffer -- leave p pointing at last char */ q = pathname; for (p=buff; *p = *q++; p++) if (p >= &buff[sizeof buff - 4]) { printf("%.64s... : name too long\n", pathname); return; } /* * Check for write permission in parent directory */ pdir = parent(pathname); if (stat(pdir, &statbuff) < 0) { printf("Can't find %s\n", pdir); return; } if (uid) { m = statbuff.modes; if (uid == statbuff.uid) m =>> 6; else if (gid == statbuff.gi/* size -- determine object size */ main(argc, argv) char **argv; { int buf[010], f, ac, sum; ac = argc; if (ac==1) { *argv = "a.out"; ac++; --argv; } while(--ac) { ++argv; if((f=open(*argv, 0))<0) { printf("%s not found\n", *argv); continue; } read(f, buf, sizeof buf); if(buf[0]!=0411 && buf[0]!=0410 && buf[0]!=0407) { printf("Bad format: %s\n", *argv); close(f); continue; } if (argc>2) printf("%s: ", *argv); printf("%l+%l+%l=", buf[1],buf[2],buf[3]); sum dd", ODDP, 0, "-odd", 0, ODDP, "raw", RAW, 0, "-raw", 0, RAW, "cooked", 0, RAW, "-nl", CRMOD, 0, "nl", 0, CRMOD, "echo", ECHO, 0, "-echo", 0, ECHO, "LCASE", LCASE, 0, "lcase", LCASE, 0, "-LCASE", 0, LCASE, "-lcase", 0, LCASE, "-tabs", XTABS, 0, "tabs", 0, XTABS, "hup", HUPCL, 0, "-hup", 0, HUPCL, "cr0", CR0, CR3, "cr1", CR1, CR3, "cr2", CR2, CR3, "cr3", CR3, CR3, "tab0", TAB0, TAB3, "tab1", TAB1, TAB3, "tab2", TAB2, TAB3, "tab3", TAB3,speed("speed ", mode[0].lobyte); printf("erase = '%c'; kill = '%c'\n", mode[1].lobyte, mode[1].hibyte); m = mode[2]; if(m & 0200) printf("even "); if(m & 0100) printf("odd "); if(m & 040) printf("raw "); if(m & 020) printf("-nl "); if (m & 010) printf("echo "); if(m & 04) printf("lcase "); if(m & 02) printf("-tabs "); if(m & 01) printf("hup "); delay(m>>8, "nl"); delay(m>>10, "tab"); delay(m>>12, "cr"); delay((m>>14)&1, "ff"); delay((m>>15)&1, "bs"); printf("\n"); } delay(m, s) char *s; { int dflag 0; int sflag 0; int cflag 0; int save 0; char code[256]; char squeez[256]; char vect[256]; struct string { int last, max, rep; char *p; } string1, string2; int inbuf[259]; main(argc,argv) char **argv; { int i, j; int c, d; char *compl; extern fout; string1.last = string2.last = 0; string1.max = string2.max = 0; string1.rep = string2.rep = 0; string1.p = string2.p = ""; if(--argc>0) { argv++; if(*argv[0]=='-'&&argv[0][1]!=0) { while(*++argv[0]) switch(*argv[0]) { case 'c'default: error: write(1,"Bad string\n",11); exit(); } } return(nextc(s)); } nextc(s) struct string *s; { int c, i, n; c = *s->p++; if(c=='\\') { i = n = 0; while(i<3 && (c = *s->p)>='0' && c<='7') { n = n*8 + c - '0'; i++; s->p++; } if(i>0) c = n; else c = *s->p++; } if(c==0) *--s->p = 0; return(c&0377); } d) m =>> 3; if ((m & 02) == 0) { printf("No write permission in %s\n", pdir); return; } } /* * make sure it's empty first */ if ((fd = open(pathname, 0)) < 0) { printf("%s: can't open\n", pathname); return; } while ( (m = read(fd, dirbuff, sizeof dirbuff)) == sizeof dirbuff ) if ( (dirbuff[0] | dirbuff[1]) && !dotname(&dirbuff[2]) ) { printf("%s: not empty\n", pathname); close(fd); return; } close(fd); if (m != 0) { perror(pathname); return; } /* * remove st= buf[1]+buf[2]+buf[3]; printf("%l (%x)\n", sum, sum); close(f); } } TAB3, "nl0", NL0, NL3, "nl1", NL1, NL3, "nl2", NL2, NL3, "nl3", NL3, NL3, "ff0", FF0, FF1, "ff1", FF1, FF1, "bs0", BS0, BS1, "bs1", BS1, BS1, "33", CR1, ALL, "tty33", CR1, ALL, "37", FF1+CR2+TAB1+NL1, ALL, "tty37", FF1+CR2+TAB1+NL1, ALL, "05", NL2, ALL, "vt05", NL2, ALL, "tn", CR1, ALL, "tn300", CR1, ALL, "ti", CR2, ALL, "ti700", CR2, ALL, "tek", FF1, ALL, 0, }; char *arg; int mode[3]; struct { char pad0, pad1, hibyte, lobyte; }; /***/ main(ar if(m =& 3) printf("%s%d ", s, m); } int speed[] { 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,0,0 }; prspeed(c, s) { printf("%s%d baud\n", c, speed[s]); } putchar(c) { write(2, &c.lobyte, 1); } : cflag++; continue; case 'd': dflag++; continue; case 's': sflag++; continue; } argc--; argv++; } } if(argc>0) string1.p = argv[0]; if(argc>1) string2.p = argv[1]; for(i=0; i<256; i++) code[i] = vect[i] = 0; if(cflag) { while(c = next(&string1)) vect[c&0377] = 1; j = 0; for(i=1; i<256; i++) if(vect[i]==0) vect[j++] = i; vect[j] = 0; compl = vect; } for(i=0; i<256; i++) squeez[i] = 0; for(;;){ if(cflag) c = *compl++; else c = char dot[] "."; char dotdot[] ".."; char root[] "/"; char name[512]; int file, off -1; struct statb {int devn, inum, i[18];}x; struct entry { int jnum; char name[16];}y; main() { int n; loop0: stat(dot, &x); if((file = open(dotdot,0)) < 0) prname(); loop1: if((n = read(file,&y.name[-2],16)) < 16) prname(); if(y.jnum != x.inum)goto loop1; close(file); if(y.jnum == 1) ckroot(); cat(); chdir(dotdot); goto loop0; } ckroot() { int i, n; if((n = stat(y.name,&x)) < 0) prname(); i = x.devn; if((n =andard entries . and .. */ p[0] = '/'; p[1] = '.'; p[2] = '\0'; if (unlink(buff) < 0) { perror(buff); return; } p[2] = '.'; p[3] = '\0'; if (unlink(buff) < 0) { perror(buff); return; } /* * now remove the directory itself */ if (unlink(pathname) < 0) perror(pathname); } /* * Check for standard names '.' or '..' */ dotname(name) char *name; { register char *p; p = name; return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0'))); } /* * Given a filename# /* * set teletype modes */ /* * tty flags */ #define HUPCL 01 #define XTABS 02 #define LCASE 04 #define ECHO 010 #define CRMOD 020 #define RAW 040 #define ODDP 0100 #define EVENP 0200 #define ANYP 0300 /* * Delay algorithms */ #define CR0 0 #define CR1 010000 #define CR2 020000 #define CR3 030000 #define NL0 0 #define NL1 000400 #define NL2 001000 #define NL3 001400 #define TAB0 0 #define TAB1 002000 #define TAB2 004000 #define TAB3 006000 #define FF0 0 #define FF1 040000 #define BS0 0 #define BS1gc, argv) char *argv[]; { extern int errno; int i; gtty(1, mode); if(argc == 1) { prmodes(); exit(0); } while(--argc > 0) { arg = *++argv; if (eq("ek")) { mode[1].hibyte = '@'; mode[1].lobyte = '#'; /***/ } if (eq("erase")) { /***/ if (--argc > 0) /***/ mode[1].lobyte = **++argv; } if (eq("kill")) { /***/ if (--argc > 0) /***/ mode[1].hibyte = **++argv; } for(i=0; speeds[i].string; i++) if(eq(speeds[i].string)) mode[0] = speeds[i].speed; for(i=0; modes[i].st/* nohup */ char *args[100]; char string[1000]; main(argc, argv) int argc; char *argv[]; { int i; char **argp, *strp, *p; if(argc < 2) { printf("arg count\n"); exit(); } argc--; argv++; argp = args; strp = string; for (i=0; i<9; i++) *strp++ = "/usr/bin/"[i]; for(i=0; i=0 ) { if(c == 0) continue; if(c = code[c&0377]&0377) if(!sflag || c!=save || !squeez[c&0377]) putchar(save = c); } flush(); } next(s) struct string *s; { int a, chdir(root)) < 0) prname(); if((file = open(root,0)) < 0) prname(); loop: if((n = read(file,&y.name[-2],16)) < 16) prname(); if(y.jnum == 0) goto loop; if((n = stat(y.name,&x)) < 0) prname(); if(x.devn != i) goto loop; x.i[0] =& 060000; if(x.i[0] != 040000) goto loop; if(y.name[0]=='.')if(((y.name[1]=='.') && (y.name[2]==0)) || (y.name[1] == 0)) goto pr; cat(); pr: write(1,root,1); prname(); } prname() { if(off<0)off=0; name[off] = '\n'; write(1,name,off+1); exit(); } cat() { int i, j; , construct the name of its parent directory */ parent(fname) char *fname; { static char pbuff[100]; register char *f, *p, *slash; register c; /* * Copy filename to buffer, remembering position of last '/' */ slash = 0; f = fname; for (p = pbuff; c = *f++; p++) { if (c == '/') slash = p; *p = c; } /* * no slash found - parent is "." * otherwise - parent is "xxx/." */ if (slash == 0) return("."); slash[1] = '.'; slash[2] = '\0'; return(pbuff); } 0100000 #define ALL 0177400 struct { char *string; int speed; } speeds[] { "0", (0<<8)|0, "50", (1<<8)|1, "75", (2<<8)|2, "110", (3<<8)|3, "134", (4<<8)|4, "134.5",(4<<8)|4, "150", (5<<8)|5, "200", (6<<8)|6, "300", (7<<8)|7, "600", (8<<8)|8, "1200", (9<<8)|9, "1800", (10<<8)|10, "2400", (11<<8)|11, "4800", (12<<8)|12, "9600", (13<<8)|13, "exta", (14<<8)|14, "extb", (15<<8)|15, 0, }; struct { char *string; int set; int reset; } modes[] { "even", EVENP, 0, "-even", 0, EVENP, "oring; i++) if(eq(modes[i].string)) { mode[2] =& ~modes[i].reset; mode[2] =| modes[i].set; } if(arg) printf("unknown mode: %s\n", arg); } stty(1,mode); } eq(string) char *string; { int i; if(!arg) return(0); i = 0; loop: if(arg[i] != string[i]) return(0); if(arg[i++] != '\0') goto loop; arg = 0; return(1); } prmodes() { register m; if(mode[0].lobyte != mode[0].hibyte) { prspeed("input speed ", mode[0].lobyte); prspeed("output speed ", mode[0].hibyte); } else prn", string+9); } b, c, n; int base; if(--s->rep > 0) return(s->last); if(s->last < s->max) return(++s->last); if(*s->p=='[') { nextc(s); s->last = a = nextc(s); s->max = 0; switch(nextc(s)) { case '-': b = nextc(s); if(bp++!=']') goto error; s->max = b; return(a); case '*': base = (*s->p=='0')?8:10; n = 0; while((c = *s->p)>='0' && c<'0'+base) { n = base*n + c - '0'; s->p++; } if(*s->p++!=']') goto error; if(n==0) n = 1000; s->rep = n; return(a); i = -1; while(y.name[++i] != 0); if((off+i+2) > 511) prname(); for(j=off+1; j>=0; --j) name[j+i+1] = name[j]; off=i+off+1; name[i] = root[0]; for(--i; i>=0; --i) name[i] = y.name[i]; } /* * Print execution profile */ struct nl { char name[8]; int value; float time; /***/ long ncall; }; struct nl nl[600]; struct fnl { char fname[8]; int flag; int fvalue; }; struct cnt { int cvalue; /***/ long cncall; } cbuf[200]; struct inode { int idev; int inum; int flags; char nlink; char uid; char gid; char size0; int size; int ptr[8]; int ctime[2]; int mtime[2]; int fill; }; int ibuf[131]; /***/ int obuf[131]; /***/ int buf[17]; int i; int j; int highpc; int lowpc; inc(ibuf); if ((buf->flag | aflg) != 042) continue; /***/ buf->fvalue = (buf->fvalue>>1); npe->value = buf->fvalue; for (i=0; i<8; i++) npe->name[i] = buf->fname[i]; npe++; nname++; } if (nname == 0) { printf("No symbols: %s\n", namfil); done(); } /***/ npe->value = 0x7fffffff; npe++; for (cp = cbuf; cp < &cbuf[ncount]; cp++) for (np = nl; np < npe; np++) /***/ if ((off = cp->cvalue-(np->value<<1))>0 && off<32) { /***/ np->ncall = cp->cncall; break; } /***/ qsort(hntziou{pv|k; if(xy > 2047.) xy = 2047.; if(xy < -2048.) xy = -2048.; ixy = xy; vtch(ixy.b1); vtch(ixy.b2); } done() { fflush(obuf); exit(); } initf(f) { ibuf[0] = f; ibuf[1] = 0; ibuf[2] = 0; ibuf[3] = 0; } }; int nfields; int error 1; main(argc, argv) char **argv; { register a, i; char *arg; register int *p; int *q; for(a=0; a<128; a++) nofold[a] = a; nodict[127] = 1; copyproto(); eargv = argv; while (--argc > 0) { if(**++argv == '-') for(arg = *argv;;) { switch(*++arg) { case '\0': if (arg[-1] == '-') eargv[eargc++] = "-"; break; case 'm': mflg++; continue; case 'o': if(--argc > 0) outfil = *++argv; continue; default: field(++*argv,1); != '\n') { if(c >= 0) continue; cp--; close(ibuf[0]); if(i< eargc) { if((f = setfil(i++)) == 0) ibuf[0] = 0; else if(fopen(f, ibuf) < 0) cant(f); } else break; } if(c < 0) { done++; lp--; break; } } qsort(lspace, lp-lspace, sizeof(*lspace), cmp); /***/ if(done == 0 || nfiles!= eargc) newfile(); else oldfile(); while(lp > lspace) { cp = *--lp; do putc(*cp, obuf); while(*cp++ != '\n'); } fflush(obuf); close(ot ccnt; int pcl; int pch; int bufs; int nname; double time; double totime; double maxtime; double scale; double lastx; double lasty; struct nl *np; struct nl *npe; int aflg; int vflg; int lflg; int symoff; int symsiz; int vf; int etext; int ncount; main(argc, argv) char **argv; { /***/ register off; char *namfil; int timcmp(), valcmp(); int nf, pf, overlap; /***/ double fnc, lastsx; struct cnt *cp; obuf[0] = 1; argv++; namfil = "a.out"; while (argc>1) { if (**argv == '-') { if (*++*argv ==nl, nname, sizeof (struct nl), &valcmp); scale = (highpc-lowpc)/(bufs+0.0); initf(pf); for (i=0; (j = getc(ibuf)) != -1; i++) { ccnt.fname[0] = j; ccnt.fname[1] = getc(ibuf); /***/ ccnt.fname[2] = getc(ibuf); /***/ ccnt.fname[3] = getc(ibuf); if (ccnt == 0) continue; time = ccnt; if (ccnt<0) time =+ 65536.; totime =+ time; if(time > maxtime) maxtime = time; pcl = lowpc + scale*i - 1; pch = lowpc + scale*(i+1) - 1; for (j=0; jvalue < lowpc) continue; if(np->value >= highpc) continue; time = np->time/totime; lasty = 2048. - (np->value - lowpc)*scale; vtch(3); point(0., lasty); point(50., lasty); vtch(3); point(lastx-50., lasty); point(lastx, lasty); vtch(9); point(lastx+10., lasty+60.); vtch(1); vtch(3); for(j=0; j<8; j++) if(np->name[j] != '_') vtch(n#define L 512 #define N 7 #define C 20 #define MEM (16*2048) #define NF 10 int ibuf[3+512/sizeof(int)]; /***/ int obuf[3+512/sizeof(int)]; /***/ char *file; char *filep; int nfiles; int nlines; int ntext; int *lspace; char *tspace; int cmp(); int term(); int mflg; char *outfil; char tabchar; int eargc; char **eargv; char *setfil(); char fold[128] { 0000,0001,0002,0003,0004,0005,0006,0007, 0010,0011,0012,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0024,0025,0026,0027, 0030,0031,0032,0033,0034,0035, break; } break; } else if (**argv == '+') { if(++nfields>=NF) { mess("Too many keys\n"); exit(1); } copyproto(); field(++*argv,0); } else eargv[eargc++] = *argv; } q = &fields[0]; for(a=1; a<=nfields; a++) { p = &fields[a]; for(i=0; i<5; i++) /*sensitive to sizeof(proto)*/ if(p[i] != proto[i]) goto next; for(i=0; i<5; i++) p[i] = q[i]; next: ; } if(eargc == 0) eargv[eargc++] = "-"; a = MEM; i = lspace = sbrk(0); while(brk(a) == -1) a =- 512; qw}lrx~my 'l') lflg++; if (**argv == 'a') aflg = 040; if(**argv == 'v') vflg++; } else namfil = *argv; argc--; argv++; } if ((nf = open(namfil, 0)) < 0) { printf("Can't find %s\n", namfil); done(); } /***/ read(nf, buf, 32); if (buf[0] != 0407 && buf[0] != 0410 && buf[0] != 0411) { /* a.out magic */ printf("Bad format: %s\n", namfil); done(); } symsiz = buf[4]; symoff = buf[1] + buf[2]; if (buf[7] != 1) symoff =<< 1; /***/ seek(nf, symoff+32, 0); if ((pf = open("mon.reak; if (pcl >= nl[j+1].value) continue; overlap=(min(pch,nl[j+1].value)-max(pcl,nl[j].value)); nl[j].time =+ overlap*time/scale; } } if (totime==0.0) { printf("No time accumulated\n"); done(); } if(!vflg) goto print; /*** vf = open("/dev/vt0", 1); if(vf < 0) { printf("Cannot open vt\n"); done(); } obuf[0] = vf; vtch(1); vtch(1); vtch(3); point(-2048., -2048.); point(-2048., 2048.); vtch(3); point(0., -2048.); point(0., 2048.); for(j=0; j<9; j++) { vtch(3); poip->name[j]); vtch(0); lastx =+ 500.; if(lastx > 2000.) lastx = 50.; } done(); ***/ print: printf(" name %%time #call ms/call\n"); if (!lflg) /***/ qsort(nl, nname, sizeof (struct nl), &timcmp); for (np = nl; nptime/totime; printf("%8.8s%6.1f", np->name, 100*time); /***/ fnc = np->ncall; if (fnc != 0.0) { /***/ printf("%6d", np->ncall); printf(" %7.2f\n", np->time/(fnc*.06)); } else printf("\n"); } done(); } min(a, b) { if (a= 0) break; } if(*filep == 'z') { if(file[1] != 't') { file = "/tmp/stmXaa"; goto loop; } mess("Cannot locate temp\n"); exit(1); } } close(a); filebuf[0]); } while(done == 0); } struct merg { char l[L]; int b[3+512/sizeof(int)]; /***/ }; merge(a, b) { register struct merg *p; register char *cp; register i; struct { int *ip;}; int f; int j; p = lspace; j = 0; for(i=a; ib[0] = dup(0); else if(fopen(f, p->b) < 0) cant(f); ibuf[j] = p; if(!rline(p)) j++; p++; } i = j; qsort(ibuf, i, sizeof(*ibuf), cmp); /***/ if(i > 0) for(;;) { cp = ibuf[i-1]; do putc(*cp, obuf); while(out", 0)) < 0) { printf("No mon.out\n"); done(); } fstat(pf, buf); /***/ read(pf, &lowpc, sizeof lowpc); /***/ read(pf, &highpc, sizeof highpc); /***/ read(pf, &ncount, sizeof ncount); /***/ bufs = buf->size/(sizeof *buf) - (2*ncount+3); /***/ read(pf, cbuf, ncount*sizeof *cbuf); /***/ lowpc = (lowpc>>1); /***/ highpc = (highpc>>1); npe = nl; initf(nf); /***/ for (nname = 0; symsiz > 0; symsiz =- sizeof (struct fnl)) { /***/ for(i=0; ifname[i] = getnt(-2048., 2048. - j*512.); point(0., 2048. - j*512.); } lastx = 0.; lasty = 2048.; scale = 4096./(i+2); seek(pf, 3*sizeof(*buf) + ncount*sizeof(*cbuf), 0); initf(pf); lastsx = 0.0; while((j = getc(ibuf)) != -1) { ccnt.fname[0] = j; ccnt.fname[1] = getc(ibuf); time = ccnt; if(ccnt < 0) time =+ 65536.; vtch(3); point(lastsx, lasty); lastsx =- 2000.*time/totime; point(lastsx, lasty-scale); if (ccnt!=0 || lastx!=0.0) { vtch(3); point(lastx, lasty); lastx = -time*2000./maa); return(b); } max(a, b) { if (a>b) return(a); return(b); } valcmp(p1, p2) struct nl *p1, *p2; { return(p1->value - p2->value); } timcmp(p1, p2) struct nl *p1, *p2; { float d; /*** d = p2->time - p1->time; ***/ d = p2->time; d =- p1->time; if (d > 0.0) return(1); if (d < 0.0) return(-1); return(0); } vtch(c) int c; { putchar(c&0377); } point(x, y) float x, y; { point1(x); point1(y); } putchar(c) { putc(c, obuf); } point1(xy) float xy; { int ixy; struct { char b1; char b2;}7 }; char nofold[128]; char dict[128] { 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 }; char nodict[128] { 1 }; struct field { char *code; char *ignore; int nflg; int rflg; int bflg; char *m[2]; char *n[2]; } fields[NF]; int proto[9] { &fold, &nodict, 0, 1, 0, 0,-1, 0,0 p++; if ((signal(2, 1) & 01) == 0) signal(2, term); nfiles = eargc; if(!mflg) { ibuf[0] = -1; sort(); close(0); } for(a = mflg?0:eargc; a+N < nfiles; a=+N) { newfile(); merge(a, a+N); } if(a != nfiles) { oldfile(); merge(a, nfiles); } error = 0; term(); } sort() { register char *cp; register *lp, c; int done; int i; int f; done = 0; i = 0; do { cp = tspace; lp = lspace; while(lp < lspace+nlines && cp < tspace+ntext) { *lp++ = cp; while((*cp++ = c = getc(ibuf))*cp++ != '\n'); if(rline(ibuf[i-1])) { i--; if(i == 0) break; } cp = &ibuf[i]; while (--cp.ip > ibuf && cmp(cp.ip, cp.ip-1) < 0) { p = *cp.ip; *cp.ip = *(cp.ip-1); *(cp.ip-1) = p; } } p = lspace; for(i=a; ib[0]); p++; if(i >= eargc) close(creat(setfil(i))); } fflush(obuf); close(obuf[0]); } rline(mp) struct merg *mp; { register char *cp; register *bp, c; bp = mp->b; cp = mp->l; do { c = getc(bp); if(c < 0) return(1); *cp++ = c; } while(c != '\n'); return(0); } newfile() { if(fcreat(setfil(nfiles), obuf) < 0) { mess("Can't create temp\n"); term(); } nfiles++; } char * setfil(i) { if(i < eargc) if(eargv[i][0] == '-' && eargv[i][1] == '\0') return(0); else return(eargv[i]); i =- eargc; filep[0] = i/26 + 'a'; filep[1] = i%26 + 'a'; return(file); } oldfile() { if(outfil) { if(fcreat(outfil, obuf) < 0) { mess("Can't create output\n"); term(); } } else obuf[0] = 1; } cant(f) { mess("Can't opefp->ignore; loop: while(*pa<0 || ignore[*pa]) pa++; while(*pb<0 || ignore[*pb]) pb++; if(pa>=la || *pa=='\n') if(pbrflg); else continue; if(pb>=lb || *pb=='\n') return(-fp->rflg); if((sa = code[*pb++]-code[*pa++]) == 0) goto loop; return(sa*fp->rflg); } pa = *i; pb = *j; while(*pa != '\n') { if(*pa == *pb) { pa++; pb++; continue; } if(*pb == '\n') return(-1); return(*pb - *pa); } return(*pb != '\n'); } skip(pp, fp, j)Ucat.cTcmp.cSdate.cRcrypt.cQwho.cPnewgrp.cOsplit.cNdd.cMbanner.c_oldLlogin.cKls.cJmail.cImesg.cHmkdir.cGsh.cFdf.cEarcv.cDcol.cCecho.cBed.cAgoto.c@if.c?grep.c>ar.c=opr.c_old= 3) gdadd(1); while(--t) gdadd(dmsize[t-1]); gdadd(d-1); gmdadd(24, h); gmdadd(60, m); gmdadd(60, 0); return(0); bad: return(1); } gdadd(n) { register char *t; t = timbuf[1]+n; if(t < timbuf[1]) timbuf[0]++; timbuf[1] = t; } gmdadd(m, n) { register int t1; timbuf[0] = timbuf[0] * m; t1 = timbuf[1]; while(--m) gdadd(t1); gdadd(n); } gpair() { register int c, d; register char *cp; cp = cbp; nt i,j; int precious; int crypt; int cage[27]; xxx = 0; /* copy input key and pad with clever junk */ jp = key; *jp++ = 004; *jp++ = 034; if(ncooky > 1){ while (*jp++ = *cookyp[1]++); jp--; } ip = key; while (jp < key+128) { *jp = jp[-1] ^ *ip++; jp++; } /* manufacture six wheels of various length */ setup(wheel1,26); setup(wheel2,25); setup(wheel3,23); setup(wheel4,21); setup(wheel5,19); setup(wheel6,17); /* set up the cage bars from the key area */ jp = key; i = 27; n "); mess(f); mess("\n"); term(); } term() { register i; if(nfiles == eargc) nfiles++; for(i=eargc; i0; k<=nfields; k++) { fp = &fields[k]; pa = *i; pb = *j; if(k) { la = skip(pa, fp, 1); pa = skip(pa, fp, 0); lb = skip(pb, fp, 1); struct field *fp; char *pp; { register i; register char *p; p = pp; if( (i=fp->m[j]) < 0) return(-1); while(i-- > 0) { if(tabchar != 0) { while(*p != tabchar) if(*p != '\n') p++; else goto ret; p++; } else { while(blank(*p)) p++; while(!blank(*p)) if(*p != '\n') p++; else goto ret; } } if(fp->bflg) while(blank(*p)) p++; i = fp->n[j]; while(i-- > 0) { if(*p != '\n') p++; else goto ret; } ret: return(p); } digit(c) { return(c <= '9 /* cat [file...] */ int fin[131]; int fout[131] { 1 }; char *dash { "-" }; main(argc, argv) char **argv; { register c, count; register char *file, **filep; if (argc == 1) { filep = ‐ count = 1; } else { filep = argv + 1; count = argc - 1; } while (count--) { if (*(file = *filep++) == '-') fin[0] = dup(0); else if ((fin[0] = open(file, 0)) < 0) continue; while ((c = getc(fin)) >= 0) putc(c, fout); close(fin[0]); } flush(fout); } int timbuf[2]; extern char *tzname[2]; extern int dmsize[]; extern char cbuf[]; char *cbp; struct { char name[8]; char tty; char fill1; int wtime[2]; int fill2; } wtmp[2]; main(argc, argv) int argc, **argv; { register char *tzn; extern int timezone, *localtime(); int wf, tfailed; tfailed = 0; if(argc > 1) { cbp = argv[1]; if(gtime()) { write(1, "bad conversion\n", 15); exit(); } if (*cbp != 's') { /* convert to Greenwich time, on assumption of Standard time. */ dpadd(timbuf, if(*cp == 0) return(-1); c = (*cp++ - '0') * 10; if (c<0 || c>100) return(-1); if(*cp == 0) return(-1); if ((d = *cp++ - '0') < 0 || d > 9) return(-1); cbp = cp; return (c+d); } while (i--){ cage[i] = cagetable[*jp++ % 28]; if(xxx && (cage[i] != 0)){ putchar( cage[i]/8 + '0'); putchar( cage[i]%8 + '0'); putchar(' '); } } if(xxx) putchar('\n'); /* the internal settings are now complete it's time to turn the crank, running the cage bars against the wheel lugs. */ while ((precious = getchar()) >=0){ temp = 040*wheel1[1] + 020*wheel2[1] + 010*wheel3[1]; temp =+ 004*wheel4[1] + 002*wheel5[1] + 001*wheel6[1]; wheel1 = *wheel1; wheel2 = *wheel2; wheel3 = *wheel3; whe pb = skip(pb, fp, 0); } else { la = -1; lb = -1; } if(fp->nflg) { while(blank(*pa)) pa++; while(blank(*pb)) pb++; sa = sb = fp->rflg; if(*pa == '-') { pa++; sa = -sa; } if(*pb == '-') { pb++; sb = -sb; } if(sa != sb) sa = 0; for(ipa = pa; ipa pa && ipb > pb) if(b = *--ipb - *--ipa) a = b; while(ipa ' && c >= '0'); } mess(s) char *s; { while(*s) write(2, s++, 1); } copyproto() { register int i, *p, *q; p = proto; q = &fields[nfields]; for(i=0; icode = nofold; break; case 'b': p->bflg++; break; case 'd': p->ignore = dict; break; case 'n': p->nflg++; break; caint ibuf1[131]; /***/ int ibuf2[131]; /***/ int eflg; int lflg 1; int line[2] {0, 1}; int chr[2] { -1, -1}; main(argc, argv) char **argv; { register c1, c2; char *arg; if(argc < 3) goto narg; arg = argv[1]; if(arg[0] == '-' && arg[1] == 's') { lflg--; argv++; argc--; } arg = argv[1]; if(arg[0] == '-' && arg[1] == 'l') { lflg++; argv++; argc--; } if(argc < 3) goto narg; arg = argv[1]; if( arg[0]=='-' && arg[1]==0 ) ibuf1[0] = dup(0); else if(fopen(arg, ibuf1) < 0) goto batimezone); /* Now fix up to local daylight time. */ if (localtime(timbuf)[8]) dpadd(timbuf, -1*60*60); } time(wtmp[0].wtime); wtmp[0].tty = '|'; if(stime(timbuf) < 0) { tfailed++; write(1, "no permission\n", 14); } else if ((wf = open("/usr/adm/wtmp", 1)) >= 0) { time(wtmp[1].wtime); wtmp[1].tty = '}'; seek(wf, 0, 2); write(wf, wtmp, 48); /***/ } } /*** if (tfailed==0) ***/ time(timbuf); cbp = cbuf; ctime(timbuf); write(1, cbuf, 20); tzn = tzname[localtime(timb/* This routine is an exact implementation of Boris Hagelin's cryptographic machine. See U. S. Patent #2,089,603. */ int cagetable[] { 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 8, 8, 9, 10, 12, 16, 16, 17, 18, 20, 24, 32, 32, 33, 34, 36, 40, 48}; int warr1[52]; int warr2[50]; int warr3[46]; int warr4[42]; int warr5[38]; int warr6[34]; int *wheel1 warr1; int *wheel2 warr2; int *wheel3 warr3; int *wheel4 warr4; int *wheel5 warr5; int *wheel6 warr6; char key[130]; int xxx; /* subroutine to manufacture a wheel */ setel4 = *wheel4; wheel5 = *wheel5; wheel6 = *wheel6; random = 0; i = 27; while (i--){ random = random + ((temp & cage[i]) != 0); } random =% 26; /* now we have a random number to use to encrypt the input it is done in such a way that the process is its own inverse. */ if ( precious=='\n' || precious==' ') crypt = precious; else{ crypt = ('a' + 'z' - precious + random)%0400; if (crypt >= 'a' && crypt <= 'z' && precious > 'z') crypt =+ 26; if (crypt > 'z' && precious >= 'a' & precious> pa) if(*--ipa != '0') return(sa ? -sa : sb); while(ipb > pb) if(*--ipb != '0') return(sa ? sa : sb); if(a) return(a*sa); if(*(pa=jpa) == '.') pa++; if(*(pb=jpb) == '.') pb++; while(pacode; ignore = se 't': tabchar = *++s; if(tabchar == 0) s--; break; case 'r': p->rflg = -1; break; default: p->m[k] = number(&s); if(*s == '.') s++; p->n[k] = number(&s); s--; } } } number(ppa) char **ppa; { int n; register char *pa; pa = *ppa; n = 0; while(digit(*pa)) n = n*10 + *pa++ - '0'; *ppa = pa; return(n); } blank(c) { if(c==' ' || c=='\t') return(1); return(0); } rg; arg = argv[2]; if(fopen(arg, ibuf2) < 0) goto barg; loop: if (++chr[1]==0) chr[0]++; c1 = getc(ibuf1); c2 = getc(ibuf2); if (c1 == c2) { if (c1 == '\n') if (++line[1]==0) line[0]++; if(c1 == -1) { if(eflg) exit(1); exit(0); } goto loop; } if(lflg == 0) exit(1); if(c1 == -1) { arg = argv[1]; goto earg; } if(c2 == -1) goto earg; if(lflg == 1) { /*** printf("%s %s differ: char %s, line ", argv[1], arg, locv(chr[0], chr[1])); ***/ printf("%s %s differ:uf)[8]]; if (tzn) write(1, tzn, 3); write(1, cbuf+19, 6); } gtime() { register int i; register int y, t; int d, h, m; extern int *localtime(); int nt[2]; t = gpair(); if(t<1 || t>12) goto bad; d = gpair(); if(d<1 || d>31) goto bad; h = gpair(); if(h == 24) { h = 0; d++; } m = gpair(); if(m<0 || m>59) goto bad; y = gpair(); if (y<0) { time(nt); y = localtime(nt)[5]; } if (*cbp == 'p') h =+ 12; if (h<0 || h>23) goto bad; timbuf[0] = 0; timbuf[1] = 0; y =+ 1900; fup(list,n) int list[]; {int *lp; lp = list; while(--n){ *lp = lp+2; lp[1] = getbit(); if(xxx) putchar(lp[1]+'0'); lp = lp + 2; } *lp = list; lp[1] = getbit(); if(xxx){ putchar(lp[1]+'0'); putchar('\n'); } } /* subroutine to return the next bit from the main routines argument */ getbit(){ static i,j; int b; b = (key[j] >> i) & 1; if (i++ > 5) { j++; i = 0; } return (b); } main(ncooky,cookyp) int ncooky; char *cookyp[]; { char *ip, *jp; int temp; int random; i <= 'z') crypt =- 26; if (crypt == '\n' || crypt == ' ') crypt = precious; } putchar(crypt); } flush(); return; } char ibuf[512]; char obuf[512]; char *ibufp; int icnt; int ocnt; getchar() { if(icnt == 0) { icnt = read(0, ibuf, 512); if(icnt <= 0) return(-1); ibufp = ibuf; } icnt --; return(*ibufp++ & 0377); } putchar(c) { obuf[ocnt++] = c; if(ocnt >= 512) flush(); } flush() { if(ocnt > 0) write(1, obuf, ocnt); ocnt = 0; } /* * who */ extern int fout; char buf[20*24]; /***/ main(argc, argv) char **argv; { char *s, *cbuf; int n, fi, i; int tty; struct { char name[8]; char tty; char pad1; int time[2]; char pad2[2]; } *p; s = "/etc/utmp"; if(argc == 2) s = argv[1]; fi = open(s, 0); if(fi < 0) { write("cannot open wtmp\n", 17); exit(); } fout = dup(1); close(1); if (argc==3) tty = ttyn(0); loop: n = read(fi, buf, sizeof buf); if(n == 0) { flush(); if (argc==3) write(fout, "Nobody.\n" if(*p++ == 0) goto l2; } while(*p++) ; } } while(peek == ','); goto no; l2: if(pwdflg && passwd[0]) { printf("password: "); gtty(0, pbuf); pbuf[3] = pbuf[2]; pbuf[2] =& ~010; stty(0, pbuf); read(0, gbuf, 512); pbuf[2] = pbuf[3]; stty(0, pbuf); printf("\n"); p = name; q = gbuf; while(p < name+8) { if(*q == '\n') break; *p++ = *q++; } *p = 0; p = crypt(name); q = passwd; while(q < passwd+8) if(*p++ != *q++) goto no; } if(setgid(id) < 0) if(fopen(ifil, ibuf) < 0) { write(2, "cannot open input\n", 18); exit(); } if(ofil == 0) ofil = "x"; loop: f = 1; for(i=0; i=0; p++) { if (argc==3 && tty!=p->tty) continue; if(p->name[0] == '\0' && argc==1) continue; for(i=0; i<8; i++) { if(p->name[i] == '\0') p->name[i] = ' '; putchar(p->name[i]); } for(i=0; i<3; i++) putchar("tty"[i]); putchar(p->tty); cbuf = ctime(p->time); for(i=3; i<16; i++) putchar(cbuf[i]); putchar('\n'); if (argc==3) { flush(); exit(); } } goto loop; } { perror("setgid"); goto no; } done(); no: printf("Sorry\n"); done(); } skip(buf) { while(peek > 0) { if(peek == '\n') { peek = 1; return(1); } peek = getc(buf); } return(0); } field(cp, buf) { register c; register char *p, *q; p = cp; q = p+8; while((c = getc(buf)) != '\n') { if(c == ',' || c == ':' || c <= 0) break; if(p < q) *p++ = c; } *p = 0; peek = c; } value(buf) { register n, c; n = 0; while((c = getc(buf)) >= '0' && c <= '9') n = n*10 + c-'0'; putc(c, obuf); } while(c != '\n'); fflush(obuf); close(obuf[0]); goto loop; } number(str) char *str; { register n; register char *s; n = 0; for(s = str; *s; s++) if(*s>='0' && *s<='9') n = n*10 + *s-'0'; return(n); } 0360,0361,0362,0363, 0134,0237,0123,0124,0125,0126,0127,0130, 0131,0132,0364,0365,0366,0367,0370,0371, 0060,0061,0062,0063,0064,0065,0066,0067, 0070,0071,0372,0373,0374,0375,0376,0377, }; char atoe[] { 0000,0001,0002,0003,0067,0055,0056,0057, 0026,0005,0045,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0074,0075,0062,0046, 0030,0031,0077,0047,0034,0035,0036,0037, 0100,0117,0177,0173,0133,0154,0120,0175, 0115,0135,0134,0116,0153,0140,0113,0141, 0360,0361,0362,0363,0364,0365,0366,0367, 0370,0371,0ue; } if(match("of=")) { ofile = string; continue; } if(match("skip=")) { skip = number(); continue; } if(match("count=")) { count = number(); continue; } if(match("conv=")) { cloop: if(match(",")) goto cloop; if(*string == '\0') continue; if(match("ebcdic")) { conv = ebcdic; goto cloop; } if(match("ascii")) { conv = ascii; goto cloop; } if(match("lcase")) { cflag =| LCASE; goto cloop; } if(match("ucase")) { c-; } loop: if(ibc-- == 0) { ibc = 0; if(count==0 || nifr+nipr!=count) { if(cflag&(NERR|SYNC)) for(ip=ibuf+ibs; ip>ibuf;) *--ip = 0; ibc = read(ibf, ibuf, ibs); } if(ibc == -1) { perror("read"); if((cflag&NERR) == 0) { flsh(); term(); } ibc = 0; for(c=0; c= name+8) goto l1; } while(skip(gbuf)); printf("%s:eek = c; return(n); } done() { setuid(getuid()); execl("/bin/sh", "-", 0); exit(); } #define LCASE 01 #define UCASE 02 #define SWAB 04 #define NERR 010 #define SYNC 020 int cflag; int fflag; int skip; int count; char *string; char *ifile; char *ofile; char *ibuf; char *obuf; char *ibs 512; char *obs 512; char *bs; char *cbs; char *ibc; char *obc; char *cbc; int nifr; int nipr; int nofr; int nopr; int ntrunc; int ibf; int obf; char *op; int nspace; char etoa[] { 0000,0001,0002,0003,0234,0011,0206,0177, 0227,0215,0216,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0235,0205,0010,0207, 0030172,0136,0114,0176,0156,0157, 0174,0301,0302,0303,0304,0305,0306,0307, 0310,0311,0321,0322,0323,0324,0325,0326, 0327,0330,0331,0342,0343,0344,0345,0346, 0347,0350,0351,0112,0340,0132,0137,0155, 0171,0201,0202,0203,0204,0205,0206,0207, 0210,0211,0221,0222,0223,0224,0225,0226, 0227,0230,0231,0242,0243,0244,0245,0246, 0247,0250,0251,0300,0152,0320,0241,0007, 0040,0041,0042,0043,0044,0025,0006,0027, 0050,0051,0052,0053,0054,0011,0012,0033, 0060,0061,0032,0063,0064,0065,0066,0010, 0070,0071,0072,0073c>>1) & ~1; if(cflag&SWAB && c) do { a = *ip++; ip[-1] = *ip; *ip++ = a; } while(--c); ip = ibuf; if (fflag) { obc = ibc; flsh(); ibc = 0; } goto loop; } c = 0; c =| *ip++; (*conv)(c); goto loop; } flsh() { register c; if(obc) { if(obc == obs) nofr++; else nopr++; c = write(obf, obuf, obc); if(c != obc) { perror("write"); term(); } obc = 0; } } match(s) char *s; { register char *cs; cs = string; while(*cs++ == *s) if(*s++ == '\0') got not a valid group name\n", argv[1]); done(); l1: if(fopen("/etc/passwd", pbuf) < 0) { printf("cannot open password file\n"); done(); } p = space; id = getuid() & 0377; do { field(p, pbuf); field(name, pbuf); if(value(pbuf) == id) { if(name[0] == 0) pwdflg++; while(*p++) ; } } while(skip(pbuf)); *p = 0; field(passwd, gbuf); id = value(gbuf); if(id == 1) { pwdflg = 0; goto l2; } do { p = space; field(name, gbuf); while(*p) { q = name; while(*p == *q++) { int count 1000; int fnumber; int ibuf[131]; /***/ int obuf[131]; /***/ char fname[100]; char *ifil; char *ofil; main(argc, argv) char *argv[]; { register i, c, f; for(i=1; i= '0' && *cs <= '9') n = n*10 + *cs++ - '0'; for(;;) switch(*cs++) { case 'k': n =* 1024; continue; case 'w': n =* 2; continue; case 'b': n =* 512; continue; case '*': case 'x': string = cs; n =* number(); case '\0': return(n); } printf("not a number: %s\n", string); exit(); } cnull(cc) { register c; c = cc; if(cflag&UCASE && c>='a' && c<='z') c =+ 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c =+ 'a'-'A'; null(c); } null(c) { *op = c; op++; if(++obc >= obs) { flsh(); op = obuf; } } ascii(cc) { register c; c = 0; c =| etoa[cc]; if(cbs == 0) { cnull(c); return; } if(c == ' ') { nspace++; goto out; } while(nspace > 0) { null(' '); nspace--; } cnull(c); out: if(++cbc >= cbs) { null('\n'); cbc = 0; nspace = 0; } } ebcdic(cc) { register c; c = cc; if(cflag&UCASE &&1,041, /*A*/ 076,041,076,041,041,076, /*B*/ 036,041,040,040,041,036, /*C*/ 076,041,041,041,041,076, /*D*/ 077,040,076,040,040,077, /*E*/ 077,040,076,040,040,040, /*F*/ 036,041,040,047,041,036, /*G*/ 041,041,077,041,041,041, /*H*/ 004,004,004,004,004,004, /*I*/ 001,001,001,001,041,036, /*J*/ 041,042,074,044,042,041, /*K*/ 040,040,040,040,040,077, /*L*/ 041,063,055,041,041,041, /*M*/ 041,061,051,045,043,041, /*N*/ 036,041,041,041,041,036, /*O*/ 076,041,041,076,040,040, /*P*/ 036,041,041,045,04pospch;j++){ if(((c[i]<alpha[i][j] = plot; } } return(0); } banset(c,p) char c; struct bann *p; { register i,j; for(i=0;ialpha[i][j] = c; } banprt(ptr) struct bann *ptr; { register i,j; for(i=0;ialpha[i][pposs-1]='\0'; for(j=pposs-2;j>=0;j--){ if(ptr->alpha[i][j]!=blank)break; ptr->alpha[i][j]='\0'; } printf("%s\n",ptr->alpha[i]); } } p++ = '\0'; ttyb.tflags = sflags; stty(0, &ttyb); write(1, "\n", 1); namep = crypt(pwbuf); while (*namep++ == *np++); if (*--namep!='\0' || *--np!=':') goto bad; } np = colon(np); uid = 0; while (*np != ':') uid = uid*10 + *np++ - '0'; np++; gid = 0; while (*np != ':') gid = gid*10 + *np++ - '0'; np++; np = colon(np); namep = np; np = colon(np); if (chdir(namep)<0) { write(1, "No directory\n", 13); goto loop; } time(utmp.time); if ((f = open("/etc/utmp", 1)) >= 0) { t# /* * list file or directory */ struct { int fdes; int nleft; char *nextc; char buff[512]; } inf; struct ibuf { int idev; int inum; int iflags; char inl; char iuid; char igid; char isize0; int isize; int iaddr[8]; char *iatime[2]; char *imtime[2]; int filler; /***/ }; struct lbuf { char lname[15]; int lnum; int lflags; char lnl; char luid; char lgid; char lsize0; int lsize; char *lmtime[2]; }; struct lbufx { char *namep; }; extern struct lbuf end; int aflg, dflg, lflg, s if (argc==0) { argc++; argv = &dotp - 1; } for (i=0; i < argc; i++) { if ((ep = gstat(*++argv, 1))==0) continue; ep->namep = *argv; ep->lflags =| ISARG; } qsort(&end, lastp - &end, sizeof *lastp, compar); slastp = lastp; for (ep = &end; eplflags&DIR && dflg==0 || fflg) { if (argc>1) printf("\n%s:\n", ep->namep); lastp = slastp; readdir(ep->namep); if (fflg==0) qsort(slastp,lastp - slastp,sizeof *lastp,compar); if (statreq) printf("to c>='a' && c<='z') c =+ 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c =+ 'a'-'A'; c = atoe[c] & 0377; if(cbs == 0) { null(c); return; } if(cc == '\n') { while(cbc < cbs) { null(atoe[' ']); cbc++; } cbc = 0; return; } if(cbc == cbs) ntrunc++; cbc++; if(cbc <= cbs) null(c); } term() { stats(); exit(); } stats() { printf("%l+%l records in\n", nifr, nipr); printf("%l+%l records out\n", nofr, nopr); if(ntrunc) printf("%l truncated records\n", ntrunc); } struct { ch2,035, /*Q*/ 076,041,041,076,042,041, /*R*/ 036,040,036,001,041,036, /*S*/ 037,004,004,004,004,004, /*T*/ 041,041,041,041,041,036, /*U*/ 041,041,041,041,022,014, /*V*/ 041,041,041,055,063,041, /*W*/ 041,022,014,014,022,041, /*X*/ 021,012,004,004,004,004, /*Y*/ 077,002,004,010,020,077, /*Z*/ 016,010,010,010,010,016, /*[*/ 040,020,010,004,002,001, /*\*/ 034,004,004,004,004,034, /*]*/ 004,012,000,000,000,000, /*^*/ 000,000,000,000,000,077, /*_*/ 000,000,000,000,000,000, /* */ 010,010,010,010,00# /* * login [ name ] */ struct { char name[8]; char tty; char ifill; int time[2]; int ufill; } utmp; struct { int speeds; char pad1, pad2; /***/ char kill, erase; /***/ int tflags; } ttyb; struct { int junk[4]; /***/ int size; int more[12]; } statb; char *ttyx; char mailfile[32] "/usr/mail/."; int mind; /* mail file name index */ #define ECHO 010 main(argc, argv) char **argv; { char pbuf[128]; register char *namep, *np; char pwbuf[9]; int t, sflags, f, c, uid, gid; signal(3, = utmp.tty; if (t>='a') t =- 'a' - (10+'0'); seek(f, (t-'0')*sizeof utmp, 0); write(f, &utmp, sizeof utmp); close(f); } if ((f = open("/usr/adm/wtmp", 1)) >= 0) { seek(f, 0, 2); write(f, &utmp, sizeof utmp); close(f); } if ((f = open("/etc/motd", 0)) >= 0) { while(read(f, &t, 1) > 0) write(1, &t, 1); close(f); } if (stat(mailfile, &statb) >=0) write(1, "You have mail.\n", 15); chown(ttyx, uid); setgid(gid); setuid(uid); if (*np == '\0') np = "/bin/sh"; execl(np, "-", flg, tflg, uflg, iflg, fflg, gflg; extern int fout; /***/ int rflg 1; char *year; int flags; int uidfil -1; int lastuid -1; char tbuf[16]; int tblocks; int statreq; struct lbuf *lastp &end; struct lbuf *rlastp &end; char *dotp "."; #define IFMT 060000 #define DIR 0100000 #define CHR 020000 #define BLK 040000 #define ISARG 01000 #define LARGE 010000 #define STXT 010000 #define SUID 04000 #define SGID 02000 #define ROWN 0400 #define WOWN 0200 #define XOWN 0100 #define RGRP 040 #define WGRP 020 #define XGRP tal %d\n", tblocks); for (ep1=slastp; ep1lnum == -1) return; if (iflg) printf("%5d ", p->lnum); if (lflg) { pmode(p->lflags); printf("%2d ", p->lnl); t = p->luid; if(gflg) t = p->lgid; t =& 0377; if (getname(t, tbuf)==0) printf("%-6.6s", tbuf); else prinar byte[]; }; putchar(c) { write(2, &c.byte[sizeof c - 1], 1); } 0,010, /*!*/ 022,022,000,000,000,000, /*"*/ 022,077,022,022,077,022, /*#*/ 036,054,036,015,055,036, /*$*/ 001,062,064,013,023,040, /*%*/ 014,022,014,024,042,035, /*&*/ 010,010,000,000,000,000, /*'*/ 004,010,010,010,010,004, /*(*/ 010,004,004,004,004,010, /*)*/ 000,022,014,014,022,000 /***/ }; char blank ' '; char plot 'X'; int msk 040; /*mask at sixth bit*/ main(argc,argp) char **argp;int argc; { register i; /*if invoked with no arguments, prints error comment; if invoked with an argument, p 1); signal(2, 1); nice(0); ttyx = "/dev/ttyx"; if ((utmp.tty=ttyn(0)) == 'x') { write(1, "Sorry.\n", 7); exit(); } ttyx[8] = utmp.tty; gtty(0, &ttyb); ttyb.erase = '#'; ttyb.kill = '@'; stty(0, &ttyb); loop: namep = utmp.name; mind = 10; /* name in at 10th char of mailfile */ if (argc>1) { np = argv[1]; while (namep 0 && *argv[1] == '-') { argv++; while (*++*argv) switch (**argv) { case 'a': aflg++; continue; case 's': sflg++; statreq++; continue; case 'd': dflg++; tf("%-6d", t); if (p->lflags & (BLK|CHR)) printf("%3d,%3d", p->lsize.dmajor&0377, p->lsize.dminor&0377); else /*** printf("%7s", locv(p->lsize0, p->lsize)); ***/ printf("%7d", p->lsize); /***/ cp = ctime(p->lmtime); if(p->lmtime[1] < year) /***/ printf(" %-7.7s %-4.4s ", cp+4, cp+20); else printf(" %-12.12s ", cp+4); } else if (sflg) printf("%4d ", nblock(p->lsize0, p->lsize)); if (p->lflags&ISARG) printf("%s\n", p->namep); else printf("%.14s\n", p->lname); } getname#define nchars 64 /*number of chars in char set*/ #define nlines 6 /*number of lines in a banner character*/ #define pposs 85 /*number of print positions on a line (must be multiple of 4)*/ /*followed by end of string character*/ #define pospch 8 /*number of char positions per banner char*/ #define chpln 10 /*number of banner characters per line*/ struct bann{ char alpha[nlines][pposs]; }; struct bann buffer,*bp buffer; char ctbl[nchars][nlines]{ 036,041,046,051,046,035, /*@*/ 014,022,041,077,04rints it in banner form. */ if(argc<2){ printf("missing argument\n"); exit(); } banner(argp[1],bp); banprt(bp); } banner(s,bufp) char *s;struct bann *bufp; { char c,*p,*q,*r; p=s; r=bufp; banset(blank,bufp); while((c= *s++)!=0){ if((s-p)>chpln)return(s-p); if(c>='`')c =- ' '; /*map lower to upper case*/ if(c<' ')c='#'; if(c>'?')c=- 0100; q=ctbl[c]; banfil(q,r); r=+pospch; } } banfil(c,p) char *c; struct bann *p; { register i,j; for(i=0;ilnum != -1) ep->lnum = dentry.dinode; for (j=0; j<14; j++) ep->lname[j] = dentry.dname[j]; } close(inf.fdes); } gstat(file, argfl) char *file; { struct ibuf statb; register struct lbuf *rep; if (lastp+1 >= rlastp) { rlastp.idev =+ 128; /***/ brk(rlastp.idev); /***/ } rep = lastp; lastp++; rep->lflags = 0; rep->lnum = 0; if (argfl || statreq) { if (stat(file, &statb)<0) { printf("%s not found\n", file); sta p1 = p1->namep; else p1 = p1->lname; if (p2->lflags&ISARG) p2 = p2->namep; else p2 = p2->lname; for (;;) if ((j = *p1.charp++ - *p2.charp++) || p1.charp[-1]==0) return(rflg*j); return(0); } p++!=' ';); *--cp = 0; cp = cat(mailfile, ubuf.name); break; } if (fopen(cp, &fin)>=0 && (c = getchar())) { if (argc < 2) do { putchar(c); } while (c = getchar()); close(fin); c = 'y'; if (argc<2) { if (ttyn(0)!='x') { printf("Save: "); fin = 0; c = getchar(); } } else c = argv[1][1]; if (c=='y') { prepend(cp, "mbox", 1); printf("Saved mail in 'mbox'\n"); } unlink(cp); } else printf("No mail.\n"); } bulkmail(argc, argv, from) char **argv, *fro seek(fin, 0, 0); } getpwent() { register char *p; register c; static struct passwd passwd; static char line[100]; extern fin; p = line; while((c=getchar()) != '\n') { if(c <= 0) return(0); if(p < line+98) *p++ = c; } *p = 0; p = line; passwd.pw_name = p; p = pwskip(p); passwd.pw_passwd = p; p = pwskip(p); passwd.pw_uid = atoi(p); p = pwskip(p); passwd.pw_gid = atoi(p); p = pwskip(p); passwd.pw_gecos = p; p = pwskip(p); passwd.pw_dir = p; p = pwskip(p); passwd.pw_shell = /* * mesg -- set current tty to accept or * forbid write permission. * * mesg [y] [n] * y allow messages * n forbid messages */ int sbuf[40]; main(argc, argv) char *argv[]; { register char *tty; tty = "/dev/ttyx"; tty[8] = ttyn(1); if(stat(tty, sbuf) < 0) { write(2, "cannot stat\n", 12); exit(1); } if(argc < 2) { if(sbuf[2] & 02) goto no; goto yes; } if(*argv[1] == 'y') goto yes; no: if(chmod(tty, 0600) < 0) goto bad; goto was; yes: if(chmod(tty, 0622) < 0) goto bade0, size, 512); if (size&0777) n++; if (n>8) n =+ (n+255)/256; return(n); } int m0[] { 3, DIR, 'd', BLK, 'b', CHR, 'c', '-'}; int m1[] { 1, ROWN, 'r', '-' }; int m2[] { 1, WOWN, 'w', '-' }; int m3[] { 2, SUID, 's', XOWN, 'x', '-' }; int m4[] { 1, RGRP, 'r', '-' }; int m5[] { 1, WGRP, 'w', '-' }; int m6[] { 2, SGID, 's', XGRP, 'x', '-' }; int m7[] { 1, ROTH, 'r', '-' }; int m8[] { 1, WOTH, 'w', '-' }; int m9[] { 1, XOTH, 'x', '-' }; int m10[] { 1, STXT, 't', ' ' }; int *m[] { m0, m1, m2, m3, m4, m5,tb.inum = -1; statb.isize0 = 0; statb.isize = 0; statb.iflags = 0; if (argfl) { lastp--; return(0); } } rep->lnum = statb.inum; statb.iflags =& ~DIR; if ((statb.iflags&IFMT) == 060000) { statb.iflags =& ~020000; } else if ((statb.iflags&IFMT)==040000) { statb.iflags =& ~IFMT; statb.iflags =| DIR; } statb.iflags =& ~ LARGE; if (statb.iflags & RSTXT) statb.iflags =| STXT; statb.iflags =& ~ RSTXT; rep->lflags = statb.iflags; rep->luid = statb.iuid; rep# /* mail command usage mail prints your mail mail people sends standard input to people */ #define SIGINT 2 struct utmp { char name[8]; char tty; char pad1; int ltime[2]; int pad2; }; struct passwd { char *pw_name; char *pw_passwd; int pw_uid; int pw_gid; char *pw_gecos; char *pw_dir; char *pw_shell; }; char lettmp[] "/tmp/maxxxxx"; char preptmp[] "/tmp/mbxxxxx"; char mailfile[] "/usr/mail/"; int pwfil; char *cp; int me; struct passwd *p; struct utmp ubuf; int uf; main(argc, argv) cm; { extern fin, fout; int tbuf[2]; register c; fin = 0; (&fin)[1] = 0; time(tbuf); printf("From %s %s", from, ctime(tbuf)); while (c = getchar()) putchar(c); putchar('\n'); flush(); close(fout); while (--argc > 0) sendto(*++argv); delexit(); } sendto(person) char *person; { static saved; extern fout; extern fin; register struct passwd *p; setpw(); while (p = getpwent()) { if (equal(p->pw_name, person)) { if (prepend(lettmp, cat(mailfile, p->pw_name, 0))==0) break; retu; was: if(sbuf[2] & 02) write(2, "was y\n", 6); else write(2, "was n\n", 6); exit(0); bad: write(2, "cannot change mode\n", 19); exit(1); } m6, m7, m8, m9, m10}; pmode(aflag) { register int **mp; flags = aflag; for (mp = &m[0]; mp < &m[11];) select(*mp++); } select(pairp) int *pairp; { register int n, *ap; ap = pairp; n = *ap++; while (--n>=0 && (flags&*ap++)==0) ap++; putchar(*ap); } makename(dir, file) char *dir, *file; { static char dfile[100]; register char *dp, *fp; register int i; dp = dfile; fp = dir; while (*fp) *dp++ = *fp++; *dp++ = '/'; fp = file; for (i=0; i<14; i++) *dp++ = *fp++; *dp = 0; return(d->lgid = statb.igid; rep->lnl = statb.inl; rep->lsize0 = statb.isize0; rep->lsize = statb.isize; if (rep->lflags & (BLK|CHR) && lflg) rep->lsize = statb.iaddr[0]; rep->lmtime[0] = statb.imtime[0]; rep->lmtime[1] = statb.imtime[1]; if(uflg) { rep->lmtime[0] = statb.iatime[0]; rep->lmtime[1] = statb.iatime[1]; } tblocks =+ nblock(statb.isize0, statb.isize); } return(rep); } compar(ap1, ap2) struct lbuf *ap1, *ap2; { register struct lbuf *p1, *p2; register int i; int j; structhar **argv; { extern fout; register struct passwd *p; maketemp(); if (argc==1 || argc==2 && argv[1][0]=='-') { printmail(argc, argv); delexit(); } signal(SIGINT, delexit); fout = creat(lettmp, 0600); if (((me=ttyn(1))!='x' || (me=ttyn(2))!='x') && (uf = open("/etc/utmp", 0)) > 0) { while (read(uf, &ubuf, sizeof ubuf) == sizeof ubuf) if (ubuf.tty == me) { ubuf.name[8] = ' '; close(uf); for (cp=ubuf.name; *cp++!=' ';); *--cp = 0; bulkmail(argc, argv, ubuf.name); } }rn; } } fout = 1; flush(); printf("Can't send to %s.\n", person); if (ttyn(0)!='x' && saved==0) { unlink("dead.letter"); saved++; printf("Letter saved in 'dead.letter'\n"); prepend(lettmp, "dead.letter", 1); } } prepend(from, to, suid) char *from, *to; { extern int fin, fout; register c; int status; fcreat(preptmp, &fout); fopen(from, &fin); while ((c = getchar()) && putchar(c)) ; close(fin); fopen(to, &fin); while ((c = getchar()) && putchar(c)) ; close(fin); flush(); closp; return(&passwd); } pwskip(ap) char *ap; { register char *p; p = ap; while(*p != ':') { if(*p == 0) return(p); p++; } *p++ = 0; return(p); } delexit() { unlink(lettmp); unlink(preptmp); exit(0); } maketemp() { int i, pid, d; pid = getpid(); for (i=11; i>=7; --i) { d = (pid&07) + '0'; lettmp[i] = d; preptmp[i] = d; pid =>> 3; } } equal(as1, as2) { register char *s1, *s2; s1 = as1; s2 = as2; while (*s1++ == *s2) if (*s2++ == 0) return(1); return(0); } cat(ap1, /* mkdir dirname [dirname...] */ int uid; int gid; struct { int dev; int inode; int modes; char nlinks; char uid; char gid; char size0; int size; int addr[8]; int actime[2]; int modtime[2]; } statbuff; main(argc, argv) char **argv; { uid = getuid() & 0377; gid = getgid() & 0377; while (--argc) make(*++argv); } make(name) char *name; { char buff[100]; register char *pdir, *p, *q; register m; /* * Copy filename to buffer -- leave p pointing at last char */ q = name; for (p=buffile); } readdir(dir) char *dir; { static struct { int dinode; char dname[14]; } dentry; register char *p; register int j; register struct lbuf *ep; if (fopen(dir, &inf) < 0) { printf("%s unreadable\n", dir); return; } tblocks = 0; for(;;) { dentry.dinode = 0; /***/ p = &dentry.dname[-2]; /***/ for (j=0; j<16; j++) *p++ = getc(&inf); if (dentry.dinode==0 || aflg==0 && dentry.dname[0]=='.') continue; if (dentry.dinode == 0177777) { /***/ dentry.dinode = -1; /***/ { char *charp;}; p1 = ap1; p2 = ap2; if (dflg==0) { if ((p1->lflags&(DIR|ISARG)) == (DIR|ISARG)) { if ((p2->lflags&(DIR|ISARG)) != (DIR|ISARG)) return(1); } else { if ((p2->lflags&(DIR|ISARG)) == (DIR|ISARG)) return(-1); } } if (tflg) { i = 0; if (p2->lmtime[0] > p1->lmtime[0]) i++; else if (p2->lmtime[0] < p1->lmtime[0]) i--; else if (p2->lmtime[1] > p1->lmtime[1]) i++; else if (p2->lmtime[1] < p1->lmtime[1]) i--; return(i*rflg); } if (p1->lflags&ISARG) me = getuid() & 0377; setpw(); for (;;) if ((p = getpwent()) && p->pw_uid == me) bulkmail(argc, argv, p->pw_name); fout = 1; printf("Who are you?\n"); delexit(); } printmail(argc, argv) char **argv; { extern fin, fout; register n, c, f; if ((uf=open("/etc/utmp", 0)) < 0) { fout = 1; printf("can't tell who you are\n"); delexit(); } me = ttyn(1); while (read(uf, &ubuf, sizeof ubuf) == sizeof ubuf) if (ubuf.tty == me) { ubuf.name[8] = ' '; close(uf); for (cp=ubuf.name; *ce(fout); fopen(preptmp, &fin); if (suid) if (fork()) { wait(&status); close(fin); fout = 1; return(1); } else setuid(getuid()&0377); if (fcreat(to, &fout) < 0) { close(fin); fout = 1; if (suid) exit(1); else return(0); } while ((c = getchar()) && putchar(c)) ; flush(); close(fout); close(fin); fout = 1; if (suid) exit(0); return(1); } setpw() { extern fin; if (pwfil == 0) { fopen("/etc/passwd", &fin); pwfil = fin; } else fin = pwfil; (&fin)[1] = 0;ap2) char *ap1, *ap2; { register char *p1, *p2; static char fn[32]; p1 = ap1; p2 = fn; while (*p2++ = *p1++); p2--; p1 = ap2; while (*p2++ = *p1++); return(fn); } f; *p = *q++; p++) if (p >= &buff[sizeof buff - 4]) { printf("%.64s... : name too long\n", name); return; } /* * Check for write permission in parent directory */ pdir = parent(name); if (stat(pdir, &statbuff) < 0) { printf("Can't find %s\n", pdir); return; } if (uid) { m = statbuff.modes; if (uid == statbuff.uid) m =>> 6; else if (gid == statbuff.gid) m =>> 3; if ((m & 02) == 0) { printf("No write permission in %s\n", pdir); return; } } /* * Make directory node, and change owner to caller's userid */ if (mknod(name, 0140777, 0) < 0) { perror(name); return; } if (chown(name, (gid<<8) + uid) < 0) perror(name); /* * Link standard entries '.' and '..' */ p[0] = '/'; p[2] = p[1] = '.'; p[3] = '\0'; if (link(pdir, buff) < 0) { printf("Can't make entry '..'\n"); return; } p[2] = '\0'; if (link(name, buff) < 0) { printf("Can't make entry '.'\n"); return; } } /* * Given a filename, construct the name of its parent directory */ parenm[2]; } timeb; char line[LINSIZ]; char *args[ARGSIZ]; int trebuf[TRESIZ]; main(c, av) int c; char **av; { register f; register char *acname, **v; for(f=2; f<15; f++) close(f); if((f=dup(1)) != 2) close(f); dolc = getpid(); for(f=4; f>=0; f--) { dolc = ldiv(0, dolc, 10); pidp[f] = ldivr+'0'; } v = av; acname = "/usr/adm/sha"; promp = "% "; if(((uid = getuid())&0377) == 0) promp = "# "; acctf = open(acname, 1); if(c > 1) { promp = 0; if (*v[1]=='-') { **v = '-'; if (v[1][1]et(); } return(t); } getc() { register char c; if(peekc) { c = peekc; peekc = 0; return(c); } if(argp > eargp) { argp =- 10; while((c=getc()) != '\n'); argp =+ 10; err("Too many args"); gflg++; return(c); } if(linep > elinep) { linep =- 10; while((c=getc()) != '\n'); linep =+ 10; err("Too many characters"); gflg++; return(c); } getd: if(dolp) { c = *dolp++; if(c != '\0') return(c); dolp = 0; } c = readc(); if(c == '\\') { c = readc(); if(c == '\n') t[DTYP] = TLST; t[DLEF] = syn2(p1, p); t[DFLG] = 0; if(l == '&') { t1 = t[DLEF]; t1[DFLG] =| FAND|FPRS|FINT; } t[DRIT] = syntax(p+1, p2); return(t); } } if(l == 0) return(syn2(p1, p2)); error++; } /* * syn2 * syn3 * syn3 | syn2 */ syn2(p1, p2) char **p1, **p2; { register char **p; register int l, *t; l = 0; for(p=p1; p!=p2; p++) switch(**p) { case '(': l++; continue; case ')': l--; continue; case '|': case '^': if(l == 0) { t = tree(4); t[ { int i, f, pv[2]; register *t1; register char *cp1, *cp2; extern errno; if(t != 0) switch(t[DTYP]) { case TCOM: cp1 = t[DCOM]; if(equal(cp1, "chdir")) { if(t[DCOM+1] != 0) { if(chdir(t[DCOM+1]) < 0) err("chdir: bad directory"); } else err("chdir: arg count"); return; } if(equal(cp1, "shift")) { if(dolc < 1) { prs("shift: no args\n"); return; } dolv[1] = dolv[0]; dolv++; dolc--; return; } if(equal(cp1, "login")) { if(promp != 0) { NT; execute(t1); exit(); } close(acctf); gflg = 0; scan(t, &tglob); if(gflg) { t[DSPR] = "/etc/glob"; execv(t[DSPR], t+DSPR); prs("glob: cannot execute\n"); exit(); } scan(t, &trim); *linep = 0; texec(t[DCOM], t); cp1 = linep; cp2 = "/usr/bin/"; while(*cp1 = *cp2++) cp1++; cp2 = t[DCOM]; while(*cp1++ = *cp2++); texec(linep+4, t); texec(linep, t); prs(t[DCOM]); err(": not found"); exit(); case TFIL: f = t[DFLG]; pipe(pv); t1 = t[DLEF]; t1[Dt(fname) char *fname; { static char pbuff[100]; register char *f, *p, *slash; register c; /* * Copy filename to buffer, remembering position of last '/' */ slash = 0; f = fname; for (p = pbuff; c = *f++; p++) { if (c == '/') slash = p; *p = c; } /* * no slash found - parent is "." * otherwise - parent is "xxx/." */ if (slash == 0) return("."); slash[1] = '.'; slash[2] = '\0'; return(pbuff); } =='c' && c>2) arginp = v[2]; else if (v[1][1]=='t') onelflg = 2; } else { close(0); f = open(v[1], 0); if(f < 0) { prs(v[1]); err(": cannot open"); } } } if(**v == '-') { setintr++; signal(QUIT, 1); signal(INTR, 1); } dolv = v+1; dolc = c-1; loop: if(promp != 0) prs(promp); peekc = getc(); main1(); goto loop; } main1() { register char c, *cp; register *t; argp = args; eargp = args+ARGSIZ-5; linep = line; elinep = line+LINSIZ-5; error = 0; gflg = return(' '); return(c|QUOTE); } if(c == '$') { c = readc(); if(c>='0' && c<='9') { if(c-'0' < dolc) dolp = dolv[c-'0']; goto getd; } if(c == '$') { dolp = pidp; goto getd; } } return(c&0177); } readc() { char cc; register c; if (arginp) { if (arginp == 1) exit(); if ((c = *arginp++) == 0) { arginp = 1; c = '\n'; } return(c); } if (onelflg==1) exit(); if(read(0, &cc, 1) != 1) exit(); if (cc=='\n' && onelflg) onelflg--; return(cc); } /* * syDTYP] = TFIL; t[DLEF] = syn3(p1, p); t[DRIT] = syn2(p+1, p2); t[DFLG] = 0; return(t); } } return(syn3(p1, p2)); } /* * syn3 * ( syn1) [ < in ] [ > out ] * word word* [ < in ] [ > out ] */ syn3(p1, p2) char **p1, **p2; { register char **p; char **lp, **rp; register *t; int n, l, i, o, c, flg; flg = 0; if(**p2 == ')') flg =| FPAR; lp = 0; rp = 0; i = 0; o = 0; n = 0; l = 0; for(p=p1; p!=p2; p++) switch(c = **p) { case '(': if(l == 0) { if(lp != 0) error++; close(acctf); execv("/bin/login", t+DCOM); } prs("login: cannot execute\n"); return; } if(equal(cp1, "newgrp")) { if(promp != 0) { close(acctf); execv("/bin/newgrp", t+DCOM); } prs("newgrp: cannot execute\n"); return; } if(equal(cp1, "wait")) { pwait(-1, 0); return; } if(equal(cp1, ":")) return; case TPAR: f = t[DFLG]; i = 0; if((f&FPAR) == 0) i = fork(); if(i == -1) { err("try again"); return; } if(i != 0) { if((f&FPIN) != 0) {FLG] =| FPOU | (f&(FPIN|FINT|FPRS)); execute(t1, pf1, pv); t1 = t[DRIT]; t1[DFLG] =| FPIN | (f&(FPOU|FINT|FAND|FPRS)); execute(t1, pv, pf2); return; case TLST: f = t[DFLG]&FINT; if(t1 = t[DLEF]) t1[DFLG] =| f; execute(t1); if(t1 = t[DRIT]) t1[DFLG] =| f; execute(t1); return; } } texec(f, at) int *at; { extern errno; register int *t; t = at; execv(f, t+DCOM); if (errno==ENOEXEC) { if (*linep) t[DCOM] = linep; t[DSPR] = "/bin/sh"; execv(t[DSPR], t+DSPR); prs("# /* */ #define INTR 2 #define QUIT 3 #define LINSIZ 1000 #define ARGSIZ 100 /***/ #define TRESIZ 100 #define QUOTE 0200 #define FAND 1 #define FCAT 2 #define FPIN 4 #define FPOU 8 #define FPAR 16 #define FINT 32 #define FPRS 64 #define TCOM 1 #define TPAR 2 #define TFIL 3 #define TLST 4 #define DTYP 0 #define DLEF 1 #define DRIT 2 #define DFLG 3 #define DSPR 4 #define DCOM 5 #define ENOMEM 12 #define ENOEXEC 8 char *dolp; char pidp[6]; extern int ldivr; char **dolv; int dolc; char *promp; char *linep; 0; do { cp = linep; word(); } while(*cp != '\n'); treep = trebuf; treeend = &trebuf[TRESIZ]; if(gflg == 0) { if(error == 0) { setexit(); if (error) return; t = syntax(args, argp); } if(error != 0) err("syntax error"); else execute(t); } } word() { register char c, c1; *argp++ = linep; loop: switch(c = getc()) { case ' ': case '\t': goto loop; case '\'': case '"': c1 = c; while((c=readc()) != c1) { if(c == '\n') { error++; peekc = c; returnlp = p+1; } l++; continue; case ')': l--; if(l == 0) rp = p; continue; case '>': p++; if(p!=p2 && **p=='>') flg =| FCAT; else p--; case '<': if(l == 0) { p++; if(p == p2) { error++; p--; } if(any(**p, "<>(")) error++; if(c == '<') { if(i != 0) error++; i = *p; continue; } if(o != 0) error++; o = *p; } continue; default: if(l == 0) p1[n++] = *p; } if(lp != 0) { if(n != 0) error++; t = tree(5); t[DT close(pf1[0]); close(pf1[1]); } if((f&FPRS) != 0) { prn(i); prs("\n"); } if((f&FAND) != 0) return; if((f&FPOU) == 0) pwait(i, t); return; } if(t[DLEF] != 0) { close(0); i = open(t[DLEF], 0); if(i < 0) { prs(t[DLEF]); err(": cannot open"); exit(); } } if(t[DRIT] != 0) { if((f&FCAT) != 0) { i = open(t[DRIT], 1); if(i >= 0) { seek(i, 0, 2); goto f1; } } i = creat(t[DRIT], 0666); if(i < 0) { prs(t[DRNo shell!\n"); exit(); } if (errno==ENOMEM) { prs(t[DCOM]); err(": too large"); exit(); } } err(s) char *s; { prs(s); prs("\n"); if(promp == 0) { seek(0, 0, 2); exit(); } } prs(as) char *as; { register char *s; s = as; while(*s) putc(*s++); } putc(c) { /***/ char cc; /***/ cc = c; /***/ write(2, &cc, 1); } prn(n) int n; { register a; if(a=ldiv(0,n,10)) prn(a); putc(lrem(0,n,10)+'0'); } any(c, as) int c; char *as; { register char *s; s = as; while(*s) if(*s++ == char *elinep; char **argp; char **eargp; int *treep; int *treeend; char peekc; char gflg; char error; char acctf; char uid; char setintr; char *arginp; int onelflg; char *mesg[] { 0, "Hangup", 0, "Quit", "Illegal instruction", "Trace/BPT trap", "IOT trap", "EMT trap", "Arithmetic fault", /***/ "Killed", "Illegal address", /***/ "Memory fault", "Bad system call", 0, "Sig 14", "Sig 15", "Sig 16", "Sig 17", "Sig 18", "Sig 19", }; struct stime { int proct[2]; int cputim[2]; int systi; } *linep++ = c|QUOTE; } goto pack; case '&': case ';': case '<': case '>': case '(': case ')': case '|': case '^': case '\n': *linep++ = c; *linep++ = '\0'; return; } peekc = c; pack: for(;;) { c = getc(); if(any(c, " '\"\t;&<>()|^\n")) { peekc = c; if(any(c, "\"'")) goto loop; *linep++ = '\0'; return; } *linep++ = c; } } tree(n) int n; { register *t; t = treep; treep =+ n; if (treep>treeend) { prs("Command line overflow\n"); error++; resntax * empty * syn1 */ syntax(p1, p2) char **p1, **p2; { while(p1 != p2) { if(any(**p1, ";&\n")) p1++; else return(syn1(p1, p2)); } return(0); } /* * syn1 * syn2 * syn2 & syntax * syn2 ; syntax */ syn1(p1, p2) char **p1, **p2; { register char **p; register *t, *t1; int l; l = 0; for(p=p1; p!=p2; p++) switch(**p) { case '(': l++; continue; case ')': l--; if(l < 0) error++; continue; case '&': case ';': case '\n': if(l == 0) { l = **p; t = tree(4); YP] = TPAR; t[DSPR] = syn1(lp, rp); goto out; } if(n == 0) error++; p1[n++] = 0; t = tree(n+5); t[DTYP] = TCOM; for(l=0; l 0) write(fd, buff, len); if (len < 0) error(tmpio); unlink(tfname); } /* * Error exit */ error(s) { printf("%s\n", s); dexit(); } /* * Delete temp file & exit */ dexit() { if (tfi) unlink(tfname); exit(1); } lp) =+ 2; break; case SI: case SO: (*lp)++; break; default: (*lp)++; cp++; j--; break; } } if (c != ' ' || *(*lp) == '\0') *(*lp) = c; (*lp)++; cp++; } store (ll) { if (page[ll] != 0) free (page[ll]); page[ll] = alloc ( leng (lbuff) + sizeof(int)); copy (page[ll],lbuff); } fetch(ll) { int i; for (i=0; i < LINELN; i++) lbuff[i] = '\0'; copy (/***line=***/lbuff, page[ll]); } copy (s,t) char *s, *t; { if (t == 0) return (*s=0); while (*s++ = *t++); } leng (s) char *s; { int cputim); lsub(tbuf.bsyst, timbuf.systim, timeb.systim); do { np = s; while (*s != '\0' && *s != '/') s++; } while (*s++ != '\0'); for (i=0; i<14; i++) { tbuf.cname[i] = *np; if (*np) np++; } tbuf.datet[0] = timbuf.proct[0]; tbuf.datet[1] = timbuf.proct[1]; tbuf.uid = uid; tbuf.shf = 0; if (promp==0) tbuf.shf = 1; seek(acctf, 0, 2); write(acctf, &tbuf, sizeof(tbuf)); } = %d\n", n, errno); exit(); } } while (--argc) { afname = *++argv; convert(); } } /* * Convert an archive */ convert() { mktemp(); if (!getaf()) error(noar); while (getdir()) { msg('c'); copyfl(); } copyback(); } /* * Open archive file & check format */ getaf() { if (stat(afname, &stbuf) < 0) { afmode = 0666; afi = -1; return(0); } if ((afi = open(afname, 0)) < 0) error("Can't open old archive file"); afmode = stbuf.s_flags & 0777; afdev = stbuf.s_dev; readaf(sizeof magic); if (buff[0] != magic) for (size = dir.size; size >= 512; size =- 512) { readaf(512); write(tfi, buff, 512); } if (size) { readaf(size); write(tfi, buff, size); } /* pad to halfword if necessary */ if (size & 01) { seek(afi, 1, 1); write(tfi, &zero, 1); } } /* * Verbose option -- running commentary */ msg(ch) { if (vflag) printf("%c %.8s\n", ch, dir.fname); } /* * All finished -- replace archive with new temporary file */ copyback() { register fd, len; /* if any errors have occured, don't update the# define PL 102 # define ESC 033 # define SI 017 # define SO 016 # define LINELN 800 char *page[PL]; char lbuff [LINELN], *line; int cp; main () { int c, i, j, ll, mustwr; register ocp; extern int fin, fout; fin = dup(0); fout = dup(1); for (ll=0; ll0) switch (c = getchar()) { case '\n': store (ll%PL); if (++ll >= mustwr) if (page[ll%PL] != 0) { printf ("%s\n",page[ll%PL]); mustwr++; frl; for (l=0; s[l]; l++); return (l); } char *dargv[] { 0, /*** "/dev/rk2", "/dev/rp0", ***/ "/dev/dfix", "/dev/drem", 0 }; struct { char *s_isize; char *s_fsize; int s_nfree; int s_free[50]; int s_ninode; int s_inode[50]; char s_flock; char s_ilock; char s_fmod; int time[2]; int pad[21]; } sblock; int fi; main(argc, argv) char **argv; { register i; if(argc <= 1) { for(argc = 1; dargv[argc]; argc++); argv = dargv; } for(i=1; i 1) printf("%s ", argv[i]); dfree(argv[i]); } } dfree(file) c/* * Convert old format archives to new format */ char noar[] "No archive file"; char noup[] "Archive file not updated"; char nocreat[] "Can't create archive file"; char badform[] "Bad archive format"; char readio[] "Archive file read i/o error"; char inpio[] "Input file i/o error"; char tmpio[] "Temp file i/o error"; char tfname[] "/tmp/arXXXXXXX"; int magic 0177555; /* magic word to identify archive format file */ int nmagic 0177545; /* magic word for new archive format */ struct { /* old archive error(badform); return(1); } /* * Create temporary file */ mktemp() { register pid; register char *p; /* use process id to create unique name in /tmp directory */ for (p = tfname; *p; p++) ; pid = getpid(); while (*--p == 'X') { *p = (pid&7) + '0'; pid =>> 3; } /* * create file & reopen in input/output mode */ if ((tfi = creat(tfname, 0600)) < 0) error("Can't create temp file"); close(tfi); if ((tfi = open(tfname, 2)) < 0) error("Can't open temp file???"); /* write 'magic wo   ee (page[ll%PL]); page[ll%PL]=0; } fetch (ll%PL); line = lbuff; /***/ cp = 0; continue; case '\0': continue; case ESC: c = getchar(); if (c == '7') { store(ll%PL); ll--; fetch (ll%PL); ocp = cp; cp = 0; while (cp < ocp) outc(' ', &line); } else { outc (ESC, &line); outc (c, &line ); cp =- 2; } continue; case SI: case SO: outc(c, &line); cp--; break; case '\r': line = lbuff; cp = 0; continumain(argc, argv) char *argv[]; { register i; for(i=1; i=50) { printf("bad free count\n"); return(0); } b = sblock.s_free[i]; if(b == 0) return(0); if(b=sblock.s_fsize) { printf("bad free block (%l)\n", b); return(0); file header */ char fname[8]; int mtime[2]; char uid; char mode; int size; } dir; struct { /* new archive file header */ char nfname[14]; char nuid; char ngid; long ndate; long nsize; int nmode; } ndir; struct { /* buffer for stat() */ int s_dev; int s_ino; int s_flags; char s_nlinks; char s_uid; char s_gid; char s_size0; int s_size1; int s_addr[8]; int s_atime[2]; int s_mtime[2]; } stbuf; char *afname; /* name of archive file */ int afmode; /* protect mode of archive frd' archive header */ write(tfi, &nmagic, sizeof nmagic); } /* * Read from archive file, checking for i/o errors */ readaf(size) { register len; if ((len = read(afi, buff, size)) == size) return; if (size < 0) /* i/o error */ error(readio); error(badform); /* premature eof */ } /* * Read next file header */ getdir() { register len; if ((len = read(afi, &dir, sizeof dir)) == sizeof dir) return(1); if (len == 0) /* end of file */ return(0); if (len < 0) /* i/o error */ err archive */ if (nerr) error(noup); /* create archive file if it didn't exist before */ if (afi < 0) { if ((fd = creat(afname, afmode)) < 0) error(nocreat); fstat(fd, &stbuf); afdev = stbuf.s_dev; close(fd); } else close(afi); /* prevent interrupts while moving back */ signal(1, 1); signal(2, 1); /* if temp & archive files on same device, just do a mv */ stat(tfname, &stbuf); if (stbuf.s_dev == afdev) { unlink(afname); if (link(tfname, afname) < 0) error(nocreat); unlinke; case '\t': outc (' ', &line); while (cp%8) outc(' ', &line); continue; default: outc(c, &line); } for (i=0; i0 || *(*lp) == '\b' || *(*lp) == ESC || **lp == SI || **lp == SO) { switch (*(*lp)) { case '\b': j++; (*lp)++; cp++; break; case '\0': *(*lp)++ = ' '; cp++; j--; break; case ESC: /* 'escape' */ (*# /* * Editor */ #define BUFFSIZE 512 #define SIGHUP 1 #define SIGINTR 2 #define SIGQUIT 3 #define FNSIZE 64 #define LBSIZE 512 #define ESIZE 128 #define GBSIZE 256 #define NBRA 5 #define EOF -1 #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 #define STAR 01 #define error errfunc() /*** was 'goto errlab ***/ #define READ 0 #define WRITE 1 extern int ldivr; int peekc; int lastc; char savedfile[FNSIZE]; char file[FNSIZE]; char linebuf[LBSIZE]; char rhsbuf[LBSIZE/2]; char expbuf[ESIZE+4]; int circfl; int *zero; int *dot; int *dol; int *endcore; int *fendcore; int *addr1; int *addr2; char genbuf[LBSIZE]; int count[2]; char *nextip; char *linebp; int ninbuf; int io; int pflag; int onhup; int onquit; int vflag 1; int listf; int col; char *globp; int tfile -1; int tline; char *tfname; char *loc1; char *loc2; char *locs; char ibuff[BUFFSIZE]; int iblock -1; char obuff[BUFFSIZE]; int oblock -1; int ichanged; int nleft; int errfunc(); /** continue; case 'g': global(1); continue; case 'i': setdot(); nonzero(); newline(); append(gettty, addr2-1); continue; case 'k': if ((c = agetchar()) < 'a' || c > 'z') error; newline(); setdot(); nonzero(); names[c-'a'] = *addr2 | 01; continue; case 'm': move(0); continue; case '\n': if (addr2==0) addr2 = dot+1; addr1 = addr2; goto print; case 'l': listf++; case 'p': newline(); print: setdot(); nonzero(); a1 = addr1; do puts(getline(*a1 (a1==0) a1 = zero; if (minus<0) n = -n; a1 =+ n; minus = 0; continue; } relerr = 0; if (a1 || minus) relerr++; switch(c) { case ' ': case '\t': continue; case '+': minus++; if (a1==0) a1 = dot; continue; case '-': case '^': minus--; if (a1==0) a1 = dot; continue; case '?': case '/': compile(c); a1 = dot; for (;;) { if (c=='/') { a1++; if (a1 > dol) a1 = zero; } else { a1--; if (a1 < zero)); lastc = '\n'; error; } errfunc() { register c; listf = 0; puts("?"); count[0] = 0; seek(0, 0, 2); pflag = 0; if (globp) lastc = '\n'; globp = 0; peekc = lastc; while ((c = agetchar()) != '\n' && c != EOF); if (io > 0) { close(io); io = -1; } reset(); } agetchar() { char ch; if (lastc=peekc) { peekc = 0; return(lastc); } if (globp) { if ((lastc = *globp++) != 0) return(lastc); globp = 0; return(EOF); } if (read(0, &ch, 1) <= 0) return(lastc = EOF); return(lal; } return(nline); } unix() { register savint, pid, rpid; int retcode; setnoaddr(); if ((pid = fork()) == 0) { signal(SIGHUP, onhup); signal(SIGQUIT, onquit); execl("/bin/sh", "sh", "-t", 0); exit(); } savint = signal(SIGINTR, 1); while ((rpid = wait(&retcode)) != pid && rpid != -1); signal(SIGINTR, savint); puts("!"); } delete() { register *a1, *a2, *a3; setdot(); newline(); nonzero(); a1 = addr1; a2 = addr2+1; a3 = dol; dol =- a2 - a1; do *a1++ = *a2++; while (a2 <= a3 *--p = (pid&07) + '0'; pid =>> 3; } close(creat(tfname, 0600)); tfile = open(tfname, 2); brk(fendcore); dot = zero = dol = fendcore; endcore = fendcore - 2; } global(k) { register char *gp; register c; register int *a1; char globuf[GBSIZE]; if (globp) error; setall(); nonzero(); if ((c=agetchar())=='\n') error; compile(c); gp = globuf; while ((c = agetchar()) != '\n') { if (c==EOF) error; if (c=='\\') { c = agetchar(); if (c!='\n') *gp++ = '\\'; } *gp++ = c; * int *errlab errfunc; *** doesn't work with new compiler ***/ char TMPERR[] "TMP"; int names[26]; char *braslist[NBRA]; char *braelist[NBRA]; main(argc, argv) char **argv; { register char *p1, *p2; extern int onintr(); onquit = signal(SIGQUIT, 1); onhup = signal(SIGHUP, 0); argv++; if (argc > 1 && **argv=='-') { vflag = 0; /* allow debugging quits? */ if ((*argv)[1]=='q') { signal(SIGQUIT, 0); vflag++; } argv++; argc--; } if (argc>1) { p1 = *argv; p2 = savedfile; while (*p2++)); while (a1 <= addr2); dot = addr2; listf = 0; continue; case 'q': setnoaddr(); newline(); unlink(tfname); exit(0); case 'r': caseread: filename(); if ((io = open(file, 0)) < 0) { lastc = '\n'; error; } setall(); ninbuf = 0; append(getfile, addr2); exfile(); continue; case 's': setdot(); nonzero(); substitute(globp); continue; case 't': move(1); continue; case 'v': global(0); continue; case 'w': setall(); nonzero(); filename(); i a1 = dol; } if (execute(0, a1)) break; if (a1==dot) error; } break; case '$': a1 = dol; break; case '.': a1 = dot; break; case '\'': if ((c = agetchar()) < 'a' || c > 'z') error; for (a1=zero; a1<=dol; a1++) if (names[c-'a'] == (*a1|01)) break; break; default: peekc = c; if (a1==0) return(0); a1 =+ minus; if (a1dol) error; return(a1); } if (relerr) error; } } setdot() { if (addr2 == stc = ch&0177); } gettty() { register c, gf; register char *p; p = linebuf; gf = globp; while ((c = agetchar()) != '\n') { if (c==EOF) { if (gf) peekc = c; return(c); } if ((c =& 0177) == 0) continue; *p++ = c; if (p >= &linebuf[LBSIZE-2]) error; } *p++ = 0; if (linebuf[0]=='.' && linebuf[1]==0) return(EOF); return(0); } getfile() { register c; register char *lp, *fp; lp = linebuf; fp = nextip; do { if (--ninbuf < 0) { if ((ninbuf = read(io, genbuf, LBSIZE)); a1 = addr1; if (a1 > dol) a1 = dol; dot = a1; } getline(tl) { register char *bp, *lp; register nl; lp = linebuf; bp = getblock(tl, READ); nl = nleft; tl =& ~0377; while (*lp++ = *bp++) if (--nl == 0) { bp = getblock(tl=+0400, READ); nl = nleft; } return(linebuf); } putline() { register char *bp, *lp; register nl; int tl; lp = linebuf; tl = tline; bp = getblock(tl, WRITE); nl = nleft; tl =& ~0377; while (*bp = *lp++) { if (*bp++ == '\n') { *--bp = 0; linebp = lp if (gp >= &globuf[GBSIZE-2]) error; } *gp++ = '\n'; *gp++ = 0; for (a1=zero; a1<=dol; a1++) { *a1 =& ~01; if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k) *a1 =| 01; } for (a1=zero; a1<=dol; a1++) { if (*a1 & 01) { *a1 =& ~01; dot = a1; globp = globuf; commands(); a1 = zero; } } } substitute(inglob) { register gsubf, *a1, nl; int getsub(); gsubf = compsub(); for (a1 = addr1; a1 <= addr2; a1++) { if (execute(0, a1)==0) continue; inglob =| 01; dosub(); if++ = *p1++); globp = "r"; } fendcore = sbrk(0); init(); if ((signal(SIGINTR, 1) & 01) == 0) signal(SIGINTR, onintr); setexit(); commands(); unlink(tfname); } commands() { int getfile(), gettty(); register *a1, c; register char *p; int r; for (;;) { if (pflag) { pflag = 0; addr1 = addr2 = dot; goto print; } addr1 = 0; addr2 = 0; do { addr1 = addr2; if ((a1 = address())==0) { c = agetchar(); break; } addr2 = a1; if ((c=agetchar()) == ';') { c = ','; dot = a1f ((io = creat(file, 0666)) < 0) error; putfile(); exfile(); continue; case '=': setall(); newline(); count[1] = (addr2-zero)&077777; putd(); aputchar('\n'); continue; case '!': unix(); continue; case EOF: return; } error; } } address() { register *a1, minus, c; int n, relerr; minus = 0; a1 = 0; for (;;) { c = agetchar(); if ('0'<=c && c<='9') { n = 0; do { n = n * 10; n =+ c - '0'; } while ((c = agetchar())>='0' && c<='9'); peekc = c; if0) addr1 = addr2 = dot; if (addr1 > addr2) error; } setall() { if (addr2==0) { addr1 = zero+1; addr2 = dol; if (dol==zero) addr1 = zero; } setdot(); } setnoaddr() { if (addr2) error; } nonzero() { if (addr1<=zero || addr2>dol) error; } newline() { register c; if ((c = agetchar()) == '\n') return; if (c=='p' || c=='l') { pflag++; if (c=='l') listf++; if (agetchar() == '\n') return; } error; } filename() { register char *p1, *p2; register c; count[1] = 0; -1) < 0) return(EOF); fp = genbuf; } if (lp >= &linebuf[LBSIZE]) error; if ((*lp++ = c = *fp++ & 0177) == 0) { lp--; continue; } if (++count[1] == 0) ++count[0]; } while (c != '\n'); *--lp = 0; nextip = fp; return(0); } putfile() { int *a1; register char *fp, *lp; register nib; nib = BUFFSIZE; fp = genbuf; a1 = addr1; do { lp = getline(*a1++); for (;;) { if (--nib < 0) { write(io, genbuf, fp-genbuf); nib = BUFFSIZE-1; fp = genbuf; } if (++co; break; } if (--nl == 0) { bp = getblock(tl=+0400, WRITE); nl = nleft; } } nl = tline; tline =+ (((lp-linebuf)+03)>>1)&077776; return(nl); } getblock(atl, iof) { extern read(), write(); register bno, off; bno = (atl>>8)&0777; off = (atl<<1)&0774; if (bno >= 255) { puts(TMPERR); error; } nleft = BUFFSIZE - off; if (bno==iblock) { ichanged =| iof; return(ibuff+off); } if (bno==oblock) return(obuff+off); if (iof==READ) { if (ichanged) blkio(iblock, ibuff, write); (gsubf) { while (*loc2) { if (execute(1)==0) break; dosub(); } } *a1 = putline(); nl = append(getsub, a1); a1 =+ nl; addr2 =+ nl; } if (inglob==0) error; } compsub() { register seof, c; register char *p; int gsubf; if ((seof = agetchar()) == '\n') error; compile(seof); p = rhsbuf; for (;;) { c = agetchar(); if (c=='\\') c = agetchar() | 0200; if (c=='\n') error; if (c==seof) break; *p++ = c; if (p >= &rhsbuf[LBSIZE/2]) error; } *p++ = 0;; } } while (c==','); if (addr1==0) addr1 = addr2; switch(c) { case 'a': setdot(); newline(); append(gettty, addr2); continue; case 'c': delete(); append(gettty, addr1-1); continue; case 'd': delete(); continue; case 'e': setnoaddr(); if ((peekc = agetchar()) != ' ') error; savedfile[0] = 0; init(); addr2 = zero; goto caseread; case 'f': setnoaddr(); if ((c = agetchar()) != '\n') { peekc = c; savedfile[0] = 0; filename(); } puts(savedfile); "$% &!'(.4:)/5;*06<c = agetchar(); if (c=='\n' || c==EOF) { p1 = savedfile; if (*p1==0) error; p2 = file; while (*p2++ = *p1++); return; } if (c!=' ') error; while ((c = agetchar()) == ' '); if (c=='\n') error; p1 = file; do { *p1++ = c; } while ((c = agetchar()) != '\n'); *p1++ = 0; if (savedfile[0]==0) { p1 = savedfile; p2 = file; while (*p1++ = *p2++); } } exfile() { close(io); io = -1; if (vflag) { putd(); aputchar('\n'); } } onintr() { signal(SIGINTR, onintr); aputchar('\n'unt[1] == 0) ++count[0]; if ((*fp++ = *lp++) == 0) { fp[-1] = '\n'; break; } } } while (a1 <= addr2); write(io, genbuf, fp-genbuf); } append(f, a) int (*f)(); { register *a1, *a2, *rdot; int nline, tl; struct { int integer; }; nline = 0; dot = a; while ((*f)() == 0) { if (dol >= endcore) { if (sbrk(1024) == -1) error; endcore.integer =+ 1024; } tl = putline(); nline++; a1 = ++dol; a2 = a1+1; rdot = ++dot; while (a1 > rdot) *--a2 = *--a1; *rdot = t ichanged = 0; iblock = bno; blkio(bno, ibuff, read); return(ibuff+off); } if (oblock>=0) blkio(oblock, obuff, write); oblock = bno; return(obuff+off); } blkio(b, buf, iofcn) int (*iofcn)(); { seek(tfile, b, 3); if ((*iofcn)(tfile, buf, BUFFSIZE) != BUFFSIZE) { puts(TMPERR); error; } } init() { register char *p; register pid; close(tfile); tline = 0; iblock = -1; oblock = -1; tfname = "/tmp/ed00000"; ichanged = 0; pid = getpid(); for (p = &tfname[11]; p > &tfname[6];) { if ((peekc = agetchar()) == 'g') { peekc = 0; newline(); return(1); } newline(); return(0); } getsub() { register char *p1, *p2; p1 = linebuf; if ((p2 = linebp) == 0) return(EOF); while (*p1++ = *p2++); linebp = 0; return(0); } dosub() { register char *lp, *sp, *rp; int c; lp = linebuf; sp = genbuf; rp = rhsbuf; while (lp < loc1) *sp++ = *lp++; while (c = *rp++) { if (c=='&') { sp = place(sp, loc1, loc2); continue; } else if ((c&0200) && (c =& 0177) >='1' && c < NBRA+'1') { sp = place(sp, braslist[c-'1'], braelist[c-'1']); continue; } *sp++ = c&0177; if (sp >= &genbuf[LBSIZE]) error; } lp = loc2; loc2 = sp + linebuf - genbuf; while (*sp++ = *lp++) if (sp >= &genbuf[LBSIZE]) error; lp = linebuf; sp = genbuf; while (*lp++ = *sp++); } place(asp, al1, al2) { register char *sp, *l1, *l2; sp = asp; l1 = al1; l2 = al2; while (l1 < l2) { *sp++ = *l1++; if (sp >= &genbuf[LBSIZE]) error; } return(sp); } move(cflag) { register int *a; if (c=='\n') goto cerror; *ep++ = c; continue; case '.': *ep++ = CDOT; continue; case '\n': goto cerror; case '*': if (*lastep==CBRA || *lastep==CKET) error; *lastep =| STAR; continue; case '$': if ((peekc=agetchar()) != eof) goto defchar; *ep++ = CDOL; continue; case '[': *ep++ = CCL; *ep++ = 0; cclcnt = 1; if ((c=agetchar()) == '^') { c = agetchar(); ep[-2] = NCCL; } do { if (c=='\n') goto cerror; *ep++oto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep); ep++; goto star; case CCL|STAR: case NCCL|STAR: curlp = lp; while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); ep =+ *ep; goto star; star: do { lp--; if (lp==locs) break; if (advance(lp, ep)) return(1); } while (lp > curlp); return(0); default: error; } } cclass(aset, ac, af) { register char *set, c; register n; set = aset; if ((c = ac) == 0) return(0); n = *set++; while (--n) if (*set++ ==int offset 0; main(argc, argv) char *argv[]; { extern fin; char line[64]; if (argc<2 || ttyn(0)!='x') { write(1, "goto error\n", 11); seek(0, 0, 2); return; } seek(0, 0, 0); fin = dup(0); loop: if (getlin(line)) { write(1, "label not found\n", 16); return; } if (compar(line, argv[1])) goto loop; seek(0, offset, 0); } getlin(s) char s[]; { int ch, i; i =0; l: if ((ch=getch())=='\0') return(1); /***/ if (ch!=':') { while(ch!='\n' && ch!='\0') ch = getch(); /***/ goto l; while((a=nxtarg()) && (!eq(a,"}"))); return(ccode? 0 : 1); } p1 = nxtarg(); if (p1==0) goto err; if(eq(p1, "=")) return(eq(a, nxtarg())); if(eq(p1, "!=")) return(!eq(a, nxtarg())); err: write(1, "if error\n", 9); exit(9); } tio(a, f) { a = open(a, f); if (a>=0) { close(a); return(1); } return(0); } tcreat(a) { return(1); } eq(a, b) char *a, *b; { register int i; i = 0; l: if(a[i] != b[i]) return(0); if(a[i++] == '\0') return(1); goto l; } doex(earg) { register int if (*sp == '^') { circf++; sp++; } for (;;) { if (ep >= &expbuf[ESIZE]) goto cerror; if ((c = *sp++) != '*') lastep = ep; switch (c) { case '\0': *ep++ = CEOF; return; case '.': *ep++ = CDOT; continue; case '*': if (lastep==0) goto defchar; *lastep =| STAR; continue; case '$': if (*sp != '\0') goto defchar; *ep++ = CDOL; continue; case '[': *ep++ = CCL; *ep++ = 0; cclcnt = 1; if ((c = *sp++) == '^') { c = *sp++; ep[-dt, *ad1, *ad2; int getcopy(); setdot(); nonzero(); if ((adt = address())==0) error; newline(); ad1 = addr1; ad2 = addr2; if (cflag) { ad1 = dol; append(getcopy, ad1++); ad2 = dol; } ad2++; if (adt= ad2) { dot = adt++; reverse(ad1, ad2); reverse(ad2, adt); reverse(ad1, adt); } else error; } reverse(aa1, aa2) { register int *a1, *a2, = c; cclcnt++; if (ep >= &expbuf[ESIZE]) goto cerror; } while ((c = agetchar()) != ']'); lastep[1] = cclcnt; continue; defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: expbuf[0] = 0; error; } execute(gf, addr) int *addr; { register char *p1, *p2, c; if (gf) { if (circfl) return(0); p1 = linebuf; p2 = genbuf; while (*p1++ = *p2++); locs = p1 = loc2; } else { if (addr==zero) return(0); p1 = getline(*addr); locs = 0; } p2 = expbuf; i c) return(af); return(!af); } putd() { register r; count[1] = ldiv(count[0], count[1], 10); count[0] = 0; r = ldivr; if (count[1]) putd(); aputchar(r + '0'); } puts(as) { register char *sp; sp = as; col = 0; while (*sp) aputchar(*sp++); aputchar('\n'); } char line[70]; char *linp line; aputchar(ac) { register char *lp; register c; register char *p; lp = linp; c = ac; if (listf) { col++; if (col >= 72) { col = 0; *lp++ = '\\'; *lp++ = '\n'; } if (c==' } while ((ch=getch())==' '); /***/ while (ch!=' ' && ch!='\n' && ch!='\0') { s[i++] = ch; ch = getch(); /***/ } while(ch != '\n') ch = getch(); /***/ s[i] = '\0'; return(0); } compar(s1, s2) char s1[], s2[]; { int c, i; i = 0; l: if(s1[i] != s2[i]) return(1); if (s1[i++] == '\0') return(0); goto l; } getch() /***/ { offset++; return(getchar()); } /*** temporary ttyn() ***/ ttyn() { return('x'); } np, i, c; char *nargv[50], *ncom, *na; np = 0; while (na=nxtarg()) { if(earg && eq(na,"}")) break; nargv[np++] = na; } if(earg && (!eq(na, "}"))) return(9); nargv[np] = 0; if (np==0) return(earg); execv(nargv[0], nargv, np); i = 0; ncom = "/usr/bin/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; while(c=nargv[0][i]) { ncom[9+i++] = c; } ncom[9+i] = '\0'; execv(ncom+4,nargv, np); execv(ncom, nargv, np); return(1); } 2] = NCCL; } do { *ep++ = c; cclcnt++; if (c=='\0' || ep >= &expbuf[ESIZE]) goto cerror; } while ((c = *sp++) != ']'); lastep[1] = cclcnt; continue; case '\\': if ((c = *sp++) == '\0') goto cerror; defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: printf2("RE error\n"); } execute(file) { register char *p1, *p2; register c; int f; char *ebp, *cbp; if (file) { if ((f = open(file, 0)) < 0) { printf2("Can't open %s\n", file); } } elt; a1 = aa1; a2 = aa2; for (;;) { t = *--a2; if (a2 <= a1) return; *a2 = *a1; *a1++ = t; } } getcopy() { if (addr1 > addr2) return(EOF); getline(*addr1++); return(0); } compile(aeof) { register eof, c; register char *ep; char *lastep; char bracket[NBRA], *bracketp; int nbra; int cclcnt; ep = expbuf; eof = aeof; bracketp = bracket; nbra = 0; if ((c = agetchar()) == eof) { if (*ep==0) error; return; } circfl = 0; if (c=='^') { c = agetchar(); circfl++; } if (f (circfl) { loc1 = p1; return(advance(p1, p2)); } /* fast check for first character */ if (*p2==CCHR) { c = p2[1]; do { if (*p1!=c) continue; if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } /* regular algorithm */ do { if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } advance(alp, aep) { register char *lp, *ep, *curlp; char *nextep; lp = alp; ep = aep; for (;;) switch (*ep++) { case CCHR: i\t') { c = '>'; goto esc; } if (c=='\b') { c = '<'; esc: *lp++ = '-'; *lp++ = '\b'; *lp++ = c; goto out; } if (c<' ' && c!= '\n') { *lp++ = '\\'; *lp++ = (c>>3)+'0'; *lp++ = (c&07)+'0'; col =+ 2; goto out; } } *lp++ = c; out: if(c == '\n' || lp >= &line[64]) { linp = line; write(1, line, lp-line); return; } linp = lp; } /* * Get process ID routine if system call is unavailable. getpid() { register f; int b[1]; f = open("/dev/kmem", 0); if(f /* if command */ int ap; int ac; char **av; main(argc, argv) char *argv[]; { argv[argc] = 0; ac = argc; av = argv; ap = 1; if (argc<2) return; if (exp()) if(doex(0)) { write(1, "no command\n", 11); seek(0, 0, 2); } } char *nxtarg() { if (ap>ac) return(0*ap++); return(av[ap++]); } exp(s) { int p1; p1 = e1(); if (eq(nxtarg(), "-o")) return(p1 | exp()); ap--; return(p1); } e1() { int p1; p1 = e2(); if (eq(nxtarg(), "-a")) return (p1 & e1()); ap--; return(p1); } e2() { if (# /* * grep -- print lines matching (or not matching) a pattern * */ #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define STAR 01 #define LBSIZE 256 #define ESIZE 256 char ibuf[512]; char expbuf[ESIZE]; int lnum[2]; char linebuf[LBSIZE+1]; int bflag; int nflag; int cflag; int vflag; int nfile; int circf; int blkno; int tln[2]; main(argc, argv) char **argv; { extern fout; fout = dup(1); flush(); while (--argc > 0 && (++argv)[0][0]=='-') switch (argse f = 0; ebp = ibuf; cbp = ibuf; lnum[0] = 0; lnum[1] = 0; tln[0] = 0; tln[1] = 0; blkno = -1; for (;;) { if ((++lnum[1])==0) lnum[0]++; if((lnum[1]&0377) == 0) flush(); p1 = linebuf; p2 = cbp; for (;;) { if (p2 >= ebp) { if ((c = read(f, ibuf, 512)) <= 0) { close(f); if (cflag) { if (nfile > 1) printf("%s:", file); p1 = locv(tln[0],tln[1]); printf("%s\n", p1); } return; } blkno++; p2 = ibuf; ebp = ibuf+c; } c=='*') goto cerror; peekc = c; for (;;) { if (ep >= &expbuf[ESIZE]) goto cerror; c = agetchar(); if (c==eof) { *ep++ = CEOF; return; } if (c!='*') lastep = ep; switch (c) { case '\\': if ((c = agetchar())=='(') { if (nbra >= NBRA) goto cerror; *bracketp++ = nbra; *ep++ = CBRA; *ep++ = nbra++; continue; } if (c == ')') { if (bracketp <= bracket) goto cerror; *ep++ = CKET; *ep++ = *--bracketp; continue; } *ep++ = CCHRf (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CDOL: if (*lp==0) continue; return(0); case CEOF: loc2 = lp; return(1); case CCL: if (cclass(ep, *lp++, 1)) { ep =+ *ep; continue; } return(0); case NCCL: if (cclass(ep, *lp++, 0)) { ep =+ *ep; continue; } return(0); case CBRA: braslist[*ep++] = lp; continue; case CKET: braelist[*ep++] = lp; continue; case CDOT|STAR: curlp = lp; while (*lp++); g< 0) return(-1); seek(f, 0140074, 0); read(f, b, 2); seek(f, b[0]+8, 0); read(f, b, 2); close(f); return(b[0]); } */ eq(nxtarg(), "!")) return(!e3()); ap--; return(e3()); } e3() { int p1, ccode; register char *a; ccode = 0; if ((a=nxtarg())==0) goto err; if(eq(a, "(")) { p1 = exp(); if(!eq(nxtarg(), ")")) goto err; return(p1); } if(eq(a, "-r")) return(tio(nxtarg(), 0)); if(eq(a, "-w")) return(tio(nxtarg(), 1)); if(eq(a, "-c")) return(tcreat(nxtarg())); if(eq(a, "{")) { /* execute a command for exit code */ if(fork()) /*parent*/ wait(&ccode); else { /*child*/ doex(1); goto err; }v[0][1]) { case 'v': vflag++; continue; case 'b': bflag++; continue; case 'c': cflag++; continue; case 'n': nflag++; continue; default: printf2("Unknown flag\n"); continue; } if (argc<=0) exit(2); compile(*argv); nfile = --argc; if (argc<=0) execute(0); else while (--argc >= 0) { argv++; execute(*argv); } flush(); exit(0); } compile(astr) char *astr; { register c; register char *ep, *sp; char *lastep; int cclcnt; ep = expbuf; sp = astr; if ((c = *p2++) == '\n') break; if(c) if (p1 < &linebuf[LBSIZE-1]) *p1++ = c; } *p1++ = 0; cbp = p2; p1 = linebuf; p2 = expbuf; if (circf) { if (advance(p1, p2)) goto found; goto nfound; } /* fast check for first character */ if (*p2==CCHR) { c = p2[1]; do { if (*p1!=c) continue; if (advance(p1, p2)) goto found; } while (*p1++); goto nfound; } /* regular algorithm */ do { if (advance(p1, p2)) goto found; } while (*p1++); nfound: if (vflag) succeed(file); continue; found: if (vflag==0) succeed(file); } } advance(alp, aep) { register char *lp, *ep, *curlp; char *nextep; lp = alp; ep = aep; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CDOL: if (*lp==0) continue; return(0); case CEOF: return(1); case CCL: if (cclass(ep, *lp++, 1)) { ep =+ *ep; continue; } return(0); case NCCL: , n2) { register char *p; register n; n = n2; p = &nbuf[15]; do *--p = n%10 + '0'; while (n =/ 10); return(p); } if(flg['a'-'a'] || flg['b'-'a']) { bastate = 1; ponam = trim(argv[2]); argv++; argc--; if(argc < 3) usage(); } arnam = argv[2]; namv = argv+3; namc = argc-3; if(comfun == 0) { if(flg['u'-'a'] == 0) { printf("one of [%s] must be specified\n", man); done(); } setcom(rcmd); } (*comfun)(); notfound(); done(); } setcom(fun) int (*fun)(); { if(comfun != 0) { printf("only one of [%s] allowed\n", man); done(); } comfun = fun; } rcmd() { register f; init(); if(getaf())g('c'); copyfil(af, tf, IODD+OODD+HEAD); } install(); } tcmd() { if(getaf()) noar(); while(!getdir()) { if(namc == 0 || match()) { if(flg['v'-'a']) longt(); printf("%s\n", trim(file)); } copyfil(af, -1, IODD+SKIP); } } init() { tfnam = mktemp("/tmp/vXXXXX"); close(creat(tfnam, 0600)); tf = open(tfnam, 2); if(tf < 0) { printf("cannot create temp file\n"); done(); } buf[0] = NARMAG; write(tf, buf, sizeof(int)); /***/ } getaf() { static char oldmsg[] = "%s in old aarnam, 0644); if(af < 0) { printf("cannot create %s\n", arnam); done(); } seek(tf, 0, 0); while((i = read(tf, buf, sizeof buf)) > 0) /***/ write(af, buf, i); if(tf2nam) { seek(tf2, 0, 0); while((i = read(tf2, buf, sizeof buf)) > 0) /***/ write(af, buf, i); } if(tf1nam) { seek(tf1, 0, 0); while((i = read(tf1, buf, sizeof buf)) > 0) /***/ write(af, buf, i); } } /* * insert the file 'file' * into the temporary file */ movefil(f) { register char *cp; register i; cp = trim(fil f = open(tf1nam, 2); if(f < 0) { printf("cannot create second temp\n"); return; } tf1 = tf; tf = f; } } equal(s1, s2) char *s1, *s2; { register char *p1, *p2; p1 = s1; p2 = s2; while(*p1++ == *p2) if(*p2++ == 0) return(1); return(0); } phserr() { printf("phase error on %s\n", file); } mesg(c) { if(flg['v'-'a']) if(c != 'c' || flg['v'-'a'] > 1) printf("%c - %s\n", c, file); } trim(s) char *s; { register char *p1, *p2; for(p1 = s; *p1; p1++) ; while(p1 > s) { ifif (cclass(ep, *lp++, 0)) { ep =+ *ep; continue; } return(0); case CDOT|STAR: curlp = lp; while (*lp++); goto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep); ep++; goto star; case CCL|STAR: case NCCL|STAR: curlp = lp; while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); ep =+ *ep; goto star; star: do { lp--; if (advance(lp, ep)) return(1); } while (lp > curlp); return(0); default: printf2("RE botch\n"); } } cclass(aset, ac, af) { register cha/* * 'New archiver' */ #define NARMAG 0177545 #define OLDMAG 0177555 struct { char name[14]; /***/ char uid; /***/ char gid; /***/ long date; /***/ long size; /***/ int mode; /***/ } arbuf; struct { int idev; /***/ int inumber; int flags; char nlinks; char usrid; char grpid; char siz0; int siz1; int addr[8]; int adate[2]; /***/ int mdate[2]; /***/ } stbuf; #define SKIP 1 #define IODD 2 #define OODD 4 #define HEAD 8 char *man { "mrxtdp" }; char *opt { "uvnbai" }; long itol(); { printf("creating %s\n", arnam); cleanup(); return; } while(!getdir()) { bamatch(); if(namc == 0 || match()) { f = stats(); if(f < 0) { if(namc) printf("cannot open %s\n", file); goto cp; } if(flg['u'-'a']) if(itol(stbuf.mdate[0], stbuf.mdate[1]) /***/ <= (unsigned)arbuf.date) { /***/ close(f); goto cp; } mesg('r'); copyfil(af, -1, IODD+SKIP); movefil(f); continue; } cp: mesg('c'); copyfil(af, tf, IODD+OODD+HEAD); } cleanGMSBHNTCOUDJPVEKQWe); for(i=0; i<14; i++) if(arbuf.name[i] = *cp) cp++; arbuf.size = itol(stbuf.siz0&0377, stbuf.siz1); arbuf.date = itol(stbuf.mdate[0], stbuf.mdate[1]); /***/ arbuf.uid = stbuf.usrid; arbuf.gid = stbuf.grpid; arbuf.mode = stbuf.flags; copyfil(f, tf, OODD+HEAD); close(f); } stats() { register f; f = open(file, 0); if(f < 0) return(f); if(fstat(f, &stbuf) < 0) { close(f); return(-1); } return(f); } /* * copy next file * size given in arbuf */ copyfil(fi, fo, flag) { register i,(*--p1 != '/') break; *p1 = 0; } p2 = s; for(p1 = s; *p1; p1++) if(*p1 == '/') p2 = p1+1; return(p2); } #define IFMT 060000 #define ISARG 01000 #define LARGE 010000 #define SUID 04000 #define SGID 02000 #define ROWN 0400 #define WOWN 0200 #define XOWN 0100 #define RGRP 040 #define WGRP 020 #define XGRP 010 #define ROTH 04 #define WOTH 02 #define XOTH 01 #define STXT 01000 longt() { register char *cp; register t; static time[2]; /***/ pmode(); printf("%3d/%1d", arbuf.uid&0377, arbuf.gi8>-39?@FRAint done(); int rcmd(); int dcmd(); int xcmd(); int tcmd(); int pcmd(); int mcmd(); int (*comfun)(); char flg[26]; char **namv; int namc; char *arnam; char *ponam; char *tfnam; char *tf1nam; char *tf2nam; char *file; char name[16]; int af; int tf; int tf1; int tf2; int bastate; int buf[512/sizeof(int)]; /***/ main(argc, argv) char *argv[]; { register i; register char *cp; for(i=1; i<4; i++) if((signal(i, 1) & 1) == 0) signal(i, done); if(argc < 3) usage(); cp = argv[1]; if (*(cp = argv[1]) =up(); } dcmd() { init(); if(getaf()) noar(); while(!getdir()) { if(match()) { mesg('d'); copyfil(af, -1, IODD+SKIP); continue; } mesg('c'); copyfil(af, tf, IODD+OODD+HEAD); } install(); } xcmd() { register f; if(getaf()) noar(); while(!getdir()) { if(namc == 0 || match()) { f = creat(file, arbuf.mode & 0777); if(f < 0) { printf("%s cannot create\n", file); goto sk; } mesg('x'); copyfil(af, f, IODD); close(f); continue; } sk: mesg('c'); crchive format - to convert it type:\n\tarcv %s\n"; af = open(arnam, 0); if(af < 0) return(1); buf[0] = 0; read(af, buf, sizeof(int)); /***/ if(buf[0] != NARMAG) { if (buf[0] == OLDMAG) /***/ printf(oldmsg, arnam, arnam); /***/ else /***/ printf("%s not in archive format\n", arnam); done(); } return(0); } usage() { printf("usage: ar [%s][%s] archive files ...\n", opt, man); done(); } noar() { printf("%s does not exist\n", arnam); done(); } done() { if(tfnam) unlink(tfn o; int pe; if(flag & HEAD) write(fo, &arbuf, sizeof arbuf); pe = 0; while(arbuf.size > 0) { i = o = 512; if(arbuf.size < i) { i = o = arbuf.size; if(i&1) { if(flag & IODD) i++; if(flag & OODD) o++; } } if(read(fi, buf, i) != i) pe++; if((flag & SKIP) == 0) write(fo, buf, o); arbuf.size =- 512; } if(pe) phserr(); } getdir() { register i; i = read(af, &arbuf, sizeof arbuf); if(i != sizeof arbuf) { if(tf1nam) { i = tf; tf = tf1; tf1 = i; d&0377); /*** temporary mod until printf supports longs printf("%6s", locv(arbuf.size)); ***/ printf("%6d", arbuf.size); /*** temporary mod until ctime supports longs cp = ctime(&arbuf.date); ***/ time[1] = arbuf.date; cp = ctime(time); printf(" %-6.6s %-4.4s ", cp+4, cp+20); } int m1[] { 1, ROWN, 'r', '-' }; int m2[] { 1, WOWN, 'w', '-' }; int m3[] { 2, SUID, 's', XOWN, 'x', '-' }; int m4[] { 1, RGRP, 'r', '-' }; int m5[] { 1, WGRP, 'w', '-' }; int m6[] { 2, SGID, 's', XGRP, 'x', '-' }; int m7[] { 1, Rr *set, c; register n; set = aset; if ((c = ac) == 0) return(0); n = *set++; while (--n) if (*set++ == c) return(af); return(!af); } printf2(s, a) { extern fout; flush(); fout = 2; printf(s, a); flush(); exit(2); } succeed(f) { if (cflag) { if (++tln[1]==0) tln[0]++; return; } if (nfile > 1) printf("%s:", f); if (bflag) printf("%l:", blkno); if (nflag) printf("%s:", locv(lnum[0], lnum[1])); printf("%s\n", linebuf); } /*** Temporary locv() ***/ char nbuf[16]; locv(n1= '-') /* allow '-' before keys */ cp++; for (; *cp; cp++) switch(*cp) { case 'v': case 'u': case 'n': case 'a': case 'b': case 'i': flg[*cp - 'a']++; continue; case 'r': setcom(rcmd); continue; case 'd': setcom(dcmd); continue; case 'x': setcom(xcmd); continue; case 't': setcom(tcmd); continue; case 'p': setcom(pcmd); continue; case 'm': setcom(mcmd); continue; default: printf("bad option `%c'\n", *cp); done(); } if(flg['i'-'a']) flg['b'-'a']++; opyfil(af, -1, IODD+SKIP); } } pcmd() { if(getaf()) noar(); while(!getdir()) { if(namc == 0 || match()) { copyfil(af, 1, IODD); continue; } copyfil(af, -1, IODD+SKIP); } } mcmd() { init(); if(getaf()) noar(); tf2nam = mktemp("/tmp/v2XXXXX"); close(creat(tf2nam, 0600)); tf2 = open(tf2nam, 2); if(tf2 < 0) { printf("cannot create third temp\n"); done(); } while(!getdir()) { bamatch(); if(match()) { mesg('m'); copyfil(af, tf2, IODD+OODD+HEAD); continue; } mesam); if(tf1nam) unlink(tf1nam); if(tf2nam) unlink(tf2nam); exit(); } notfound() { register i; for(i=0; i=0 && (arbuf.mode&*ap++)==0) ap++; putchar(*ap); } /* * opr -- off line print via daemon */ char tfname[] "/usr/lpd/tfaXXXXX"; char cfname[] "/usr/lpd/cfaXXXXX"; char lfname[] "/usr/lpd/lfaXXXXX"; char dfname[] "/usr/lpd/dfaXXXXX"; int nact; int tff; int mailflg; char person[10]; int inchar; int maxrec 1000; main(argc, argv) int argc; char *argv[]; { register char *arg; int c, f, flag; int out(); pidfn(); if((signal(1, 1) & 01) == 0) signal(1, out); if((signal(2, 1) & 01) == 0) signal(2, out); if((signal(3, 1) & 01) == 0) signal(3, out); e((c = *p2++) != '\0') { *p1++ = c; col++; } *p1++ = '\n'; write(tff, buf, col+2); } ident() { /*** int c, n; register char *b1p, *pp, *b2p; static char b1[100], b2[100]; b1p = b1; if(getpw(getuid(), b1p)) { b1p = "pdp::::m0000,m000:"; } n = 0; b2p = b2; while(*b2p++ = "$ ident "[n++]); b2p--; n = 5; while(--n) while(*b1p++ != ':'); while((*b2p++ = *b1p++) != ':'); b2p[-1] = ','; b1p = b1; pp = person; while((c = *b1p++) != ':') { *b2p++ = c; *pp++ = c; } *b2p++ = 0; *pp++char *argv[]; { register ufil; register char *p, *q; register nlflag = 1; char ch; if (argc < 2) error(usage); if (argc > 2) ltty = argv[2][0]; if ((mtty = ttyn(0)) == 'x' && (mtty = ttyn(2)) == 'x') mtty = 0; if ((ufil = open(utmp, 0)) < 0) error("Can't open utmp"); while (read(ufil, &ubuf, sizeof ubuf) == sizeof ubuf) { if (ubuf.tty == mtty) for (p = ubuf.name, q = name; p < &ubuf.name[8] && *p != ' '; *q++ = *p++) ; if (ltty && (ubuf.tty != ltty)) continue; for char buf[100]; main(argc, argv) char **argv; { register i; register char *c1, *c2; int stat; if(argc < 3) { write(2, "arg count\n", 10); exit(); } argc--; c1 = buf; c2 = argv[argc]; while(*c1++ = *c2++); c1[-1] = '/'; *c1++ = '.'; *c1 = '\0'; for(i=1; i= 0); flush(); exit(); } compare(a,b) char *a,*b; { register char *ra,*rb; ra = --a; rb = --b; while(*++ra == *++rb) if(*ra == '\0') return(0); if(*ra < *rb) return(1); return(2); } fexit() { flush(); exit(); } openfil(s,b) char *s; int *b; { if(s[0]=='-' && s[1]==0)goto out; case 0410: printf("pure executable\n"); goto out; case 0411: printf("separate executable\n"); goto out; /***/ case 0177555: /***/ printf("old "); /***/ case 0177545: printf("archive\n"); goto out; } i = 0; if(ccom() == 0)goto notc; while(buf[i] == '#'){ j = i; while(buf[i++] != '\n'){ if(i - j > 255){ printf("data\n"); goto out; } if(i >= in)goto notc; } if(ccom() == 0)goto notc; } check: if(lookup(c) == 1){ while((ch = buf[i++]) != ';' && ch != flag = 0; tff = nfile(tfname); while (argc>1 && (arg = argv[1])[0]=='-') { switch (arg[1]) { case 'c': flag = '+'; break; case 'r': flag = '-'; break; case 'm': mailflg = 1; break; } argc--; argv++; } ident(); if(argc == 1) copy(0); while(--argc) { arg = *++argv; if(flag == '+') goto cf; if(*arg == '/' && flag != '-') { card('F', arg); nact++; continue; } if(link(arg, lfname) < 0) goto cf; card('F', lfname); card('U', lfname); lfnam = 0; card('L', b2); if (mailflg) card('M', person); ***/ } pidfn() { register i, j, c; int p; p = getpid(); i = 0; while(tfname[i] != 'X') i++; i =+ 4; for(j=0; j<5; j++) { c = (p%10) + '0'; p =/ 10; tfname[i] = c; cfname[i] = c; lfname[i] = c; dfname[i] = c; i--; } inchar = i; } nfile(name) char *name; { register f; f = creat(name, 0666); if(f < 0) { printf("Cannot create %s\n", name); out(); } name[inchar]++; return(f); } out() { register i; signal(1, 1); s(p = argv[1], q = ubuf.name; *p == *q; p++, q++) ; if (q < &ubuf.name[8] && (*q != ' ' || *p != '\0')) continue; otty.ttyno = ubuf.tty; } if (otty.ttyno == '\0') error("Not logged in."); if (name[0] == '\0') name[0] = name[1] = '?'; if ((ttyf = open(&otty, 1)) < 0 || fstat(ttyf, &stbuf) < 0 || (stbuf.flags&02) == 0) error("Permission denied."); wrs(ttyf, "\007\007\007\n\nMessage from "); wrs(ttyf, name); wrs(ttyf, " ...\n"); signal(2, finish); while (read(0, &ch, 1) == 1) { #define LB 250 int one; int two; int three; char *ldr[3]; char ib1[524]; /***/ char ib2[524]; /***/ main(argc,argv) char *argv[]; { extern fout; int l; char lb1[LB],lb2[80]; ldr[0] = ""; ldr[1] = "\t"; ldr[2] = "\t\t"; if(argc > 1) { if(*argv[1] == '-' && argv[1][1] != 0) { l = 1; while(*++argv[1]) { switch(*argv[1]) { case'1': if(!one) { one = 1; ldr[1][0] = ldr[2][l--] = '\0'; } break; case '2': if(!two) { two = 1; ldr[2 b[0] = 0; else if(fopen(s, b) == -1) { printf("Can't open %s\n", s); exit(1); } } '{')if(i >= in)goto notc; printf("c program"); goto outa; } nl = 0; while(buf[i] != '('){ if(buf[i] <= 0){ printf("data\n"); goto out; } if(buf[i] == ';'){ i++; goto check; } if(buf[i++] == '\n') if(nl++ > 6)goto notc; if(i >= in)goto notc; } while(buf[i] != ')'){ if(buf[i++] == '\n') if(nl++ > 6)goto notc; if(i >= in)goto notc; } while(buf[i] != '{'){ if(buf[i++] == '\n') if(nl++ > 6)goto notc; if(i >= in)goto notc; } printf("c program"); goto oute[inchar]++; nact++; goto df; cf: f = open(arg, 0); if(f < 0) { printf("Cannot open %s\n", arg); continue; } copy(f); close(f); df: if(flag == '-') { f = unlink(arg); if(f < 0) printf("Cannot remove %s\n", arg); } } if(nact) { tfname[inchar]--; f = link(tfname, dfname); if(f < 0) { printf("Cannot rename %s\n", dfname); tfname[inchar]++; out(); } unlink(tfname); execl("/etc/lpd", "lpd", 0); dfname[inchar]++; printf("Cannot execute /etc/lpd\n")ignal(2, 1); signal(3, 1); i = inchar; while(tfname[i] != 'a') { tfname[i]--; unlink(tfname); } while(cfname[i] != 'a') { cfname[i]--; unlink(cfname); } while(lfname[i] != 'a') { lfname[i]--; unlink(lfname); } while(dfname[i] != 'a') { dfname[i]--; unlink(dfname); } exit(); } switch (ch) { case '\n': nlflag = 1; break; case '!': if (nlflag) { shell(); wrs(2, "!\n"); continue; } break; case '\004': finish(); default: nlflag = 0; } write(ttyf, &ch, 1); } finish(); } shell() { int status; signal(2, 1); if (fork() == 0) { signal(2, 0); execl("/bin/sh", "sh", "-t", 0); error("Can't exec shell."); } wait(&status); signal(2, finish); } finish() { wrs(ttyf, "EOT\n"); exit(0); } error(s) char *s; { wrs(2,][l--] = '\0'; } break; case '3': three = 1; break; default: printf("Illegal flag: %c\n",*argv[1]); exit(); } } argv++; argc--; } } if(argc < 3) { printf("Argc = %d\n",argc); exit(); } openfil(argv[1],ib1); openfil(argv[2],ib2); fout = dup(1); if(rd(ib1,lb1) < 0) { if(rd(ib2,lb2) < 0) exit(); copy(ib2,lb2,2); } if(rd(ib2,lb2) < 0) copy(ib1,lb1,1); while(1) { switch(compare(lb1,lb2)) { case 0: wr(lb1,3); if(rd(ib1,lb1) 1) { printf("%s: ", argv[1]); type(argv[1]); argc--; argv++; } } type(file) char *file; { int j,nl; chara; notc: i = 0; while(buf[i] == 'c' || buf[i] == '#'){ while(buf[i++] != '\n')if(i >= in)goto notfort; } if(lookup(fort) == 1){ printf("fortran"); goto outa; } notfort: i=0; if(ascom() == 0)goto notas; j = i-1; if(buf[i] == '.'){ i++; if(lookup(as) == 1){ printf("assembler program"); goto outa; } else if(buf[j] == '\n'){ printf("roff, nroff, or eqn input"); goto outa; } } while(lookup(asc) == 0){ if(ascom() == 0)goto notas; while(buf[i] != '\n' && buf[i++] != ':'); exit(1); } out(); } copy(f) int f; { int ff, i, nr, nc; static int buf[256]; card('F', cfname); card('U', cfname); ff = nfile(cfname); nc = 0; nr = 0; while((i = read(f, buf, 512)) > 0) { write(ff, buf, i); nc =+ i; if(nc >= 512) { nc =- 512; nr++; if(nr > maxrec) { printf("Copy file is too large\n"); break; } } } close(ff); nact++; } card(c, s) int c; char s[]; { char *p1, *p2; static char buf[512]; int col; p1 = buf; p2 = s; col = 0; *p1++ = c; whil/* * write user [tty-no] */ char usage[] = "Usage: write user [ttyno]"; char utmp[] = "/etc/utmp"; char name[10]; struct { char name[8]; char tty; int date[2]; int unused; } ubuf; struct { int dev; int inumber; int flags; char nlinks; char uid; char gid; char size0; int size1; int addr[8]; int actime[2]; int modtime[2]; } stbuf; struct { char ttyn[8]; char ttyno; char zero; } otty = { "/dev/tty", '\0', '\0' }; char ltty; char mtty; int ttyf; extern finish(); main(argc, argv) s); wrs(2, "\n"); exit(1); } wrs(fd, s) char *s; { register char *p; register n; n = 0; for (p = s; *p; p++) n++; write(fd, s, n); } 0) { if (rd(ib2,lb2) < 0) fexit(); copy(ib2,lb2,2); } if(rd(ib2,lb2) < 0) copy(ib1,lb1,1); continue; case 1: wr(lb1,1); if(rd(ib1,lb1) < 0) copy(ib2,lb2,2); continue; case 2: wr(lb2,2); if(rd(ib2,lb2) < 0) copy(ib1,lb1,1); continue; } } } rd(file,buf) char *buf; { register int i; i = 0; while((*buf = getc(file)) >=0) { if(*buf == '\n' || i > LB-2) { *buf = '\0'; return(0); } i++; buf++; } return(-1); } wr(str,n) char *str; { ch; int mbuf[20]; if(stat(file, mbuf) < 0) { printf("cannot stat\n"); return; } switch(mbuf[2]&060000) { case 020000: printf("character"); goto spcl; case 040000: printf("directory\n"); return; case 060000: printf("block"); spcl: printf(" special (%d/%d)\n", (mbuf[6]>>8)&0377, mbuf[6]&0377); return; } ibuf[0] = open(file, 0); if(ibuf[0] < 0) { printf("cannot open\n"); return; } in = read(ibuf[0], buf, 512); switch(*wd) { case 0407: printf("executable\n"); if(i >= in)goto notas; while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas; j = i-1; if(buf[i] == '.'){ i++; if(lookup(as) == 1){ printf("assembler program"); goto outa; } else if(buf[j] == '\n'){ printf("roff, nroff, or eqn input"); goto outa; } } } printf("assembler program"); goto outa; notas: for(i=0; i < in; i++)if(buf[i] <= 0){ printf("data\n"); goto out; } if((mbuf[2] & 00111) != 0) printf("commands"); else printf("probably text"); outa: while(i < in) if(buf[i++] <= 0){ printf(" with garbage\n"); goto out; } while((in = read(ibuf[0],buf,512)) > 0) for(i = 0; i < in; i++) if(buf[i] <= 0){ printf(" with garbage\n"); goto out; } printf("\n"); out: close(ibuf[0]); } lookup(tab) char *tab[]; { char r; int k,j,l; while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++; for(j=0; tab[j] != 0; j++){ l=0; for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++); if(r == '\0') if(buint letters 0; int linec; int mode; int uniq; int fields; char *skip(); /***/ main(argc, argv) int argc; char *argv[]; { extern fin, fout; int f; static char b1[1000], b2[1000]; loop: if(argc > 1) { if(*argv[1] == '-') { if(argv[1][1] <= '9') fields = conv(&argv[1][1]); else mode = argv[1][1]; argc--; argv++; goto loop; } if(*argv[1] == '+') { letters = conv(&argv[1][1]); argc--; argv++; goto loop; } f = open(argv[1], 0); if(f < 0) { printf("cannot ope# /* wc line and word count */ #define LONG int /***/ int buf[131]; /***/ LONG wordct; LONG twordct; LONG linect; LONG tlinect; main(argc,argv) char **argv; { int i, token; register char *p1, *p2; register int c; i = 1; do { if(argc<=1) buf[0] = 0; else if(fopen(argv[i],buf)<0) { diag(argv[i]); diag(": cannot open\n"); continue; } p1 = 0; p2 = 0; linect = 0; wordct = 0; token = 0; for(;;) { if(p1 >= p2) { p1 = &buf[1]; c = read(buf[0], p1, 512); if(c <= if(*--q == '\0' && *--p == ':') goto ok; goto error; badpw: printf("bad password file\n"); ok: setuid(0); execl("/bin/sh", "-", 0); printf("cannot execute shell\n"); error: printf("sorry\n"); } getpw(name, buf) char *name, *buf; { static int pwbuff[131]; int r, c; register char *gnp, *rnp; r = 1; if((pwbuff[0] = open("/etc/passwd", 0)) < 0) return(1); loop: gnp = name; rnp = buf; while((c=getc(pwbuff)) != '\n') { if(c <= 0) goto ret; *rnp++ = c; } *rnp++ = '\0'; rnp = buf; w int ptr[8]; int atime[2]; int mtime[2]; }; main(argc, argv) char **argv; { int nfdone; int onintr(); extern fout; tty= "/dev/ttyx"; fout = dup(1); close(1); if ((signal(2, 1) & 01) == 0) signal(2, onintr); fixtty(); for (nfdone=0; argc>1; argc--) { argv++; if (**argv == '-') { switch (*++*argv) { case 'h': if (argc>=2) { header = *++argv; argc--; } continue; case 't': ntflg++; continue; case 'l': length = getn(++*argv); continue; cr) colp[ncol] = &buffer[BUFS]; } line = 0; if (ntflg==0) { puts("\n\n"); puts(cbuf+4); puts(" "); puts(cbuf+20); puts(" "); puts(header); puts(" Page "); putd(page); puts("\n\n\n"); } putpage(); if (ntflg==0) while(line= in)return(0); if(buf[i] == '/' && buf[i+1] == '*'){ i =+ 2; while(buf[i] != '*' || buf[i+1] != '/'){ if(buf[i] == '\\')i =+ 2; else i++; if(i >= in)return(0); } if((i =+ 2) >= in)return(0); } if(buf[i] == '\n')if(ccom() == 0)return(0); return(1); } ascom(){ while(buf[in %s\n", argv[1]); exit(); } fin = f; } else fin = dup(0); if(argc > 2) { f = creat(argv[2], 0666); if(f < 0) { printf("cannot create %s\n", argv[2]); exit(); } fout = f; } else fout = dup(1); close(0); close(1); gline(b1); l1: linec++; if(gline(b2)) { pline(b1); flush(); exit(); } if(equal(b1, b2)) goto l1; pline(b1); linec = 0; l2: linec++; if(gline(b1)) { pline(b2); flush(); exit(); } if(equal(b1, b2)) goto l2; pline(b2); linec = 0; goto l1; } glin 0) break; p2 = p1+c; } c = 0; c =| *p1++; if(' ' 2) { printf("%7s ",locv(tlinect)); printf("%7s ",locv(twordct)); printf("hile (*gnp++ == *rnp++); if (*--gnp != '\0' || *--rnp != ':') goto loop; r = 0; ret: close(pwbuff[0]); pwbuff[1] = 0; pwbuff[2] = 0; return(r); } ase 'w': width = getn(++*argv); continue; case 's': if (*++*argv) tabc = **argv; else tabc = '\t'; continue; case 'm': mflg++; continue; default: ncol = getn(*argv); continue; } } else if (**argv == '+') { fpage = getn(++*argv); } else { print(*argv, argv); nfdone++; if (mflg) break; } } if (nfdone==0) print(0); flush(); onintr(); } onintr() { chmod(tty, mode); exit(0); } fixtty() { struct inode sbuf; extern fout/***/ if (++nofile>=10) { write(2, "Too many args.\n", 15); exit(); } } } putpage() { register int lastcol, i, c; int j; if (ncol==0) { while (line72 || ncol>width) { write(2, "Very funny.\n", 12); exit(); } if (mflg) { mopen(argp); ncol = nofile; } colw = width/ncol; sncol = ncol; sheader = headeastcol = colw; for (i=0; i512) n = 512; if ((n = read(file, rbufp, n)) <= 0) *rbufp = 0376; else { rbufp =+ n] == '/'){ i++; while(buf[i++] != '\n')if(i >= in)return(0); while(buf[i] == '\n')if(i++ >= in)return(0); } return(1); } ++) return(0); if(*b2 != 0) return(0); uniq++; return(1); } char * skip(s) char *s; { int nf, nl; nf = nl = 0; while(nf++ < fields) { while(*s==' ' || *s=='\t') s++; while( !(*s==' ' || *s=='\t') ) if(*s == 0) return(s); else s++; } while(nl++ < letters) if(*s == 0) return(s); else s++; return(s); } conv(s) char *s; { int d, n; n = 0; for(;;) { d = *s++ - '0'; if(0>d || d>9) break; n = n*10 + d; } return(n); } /* su -- become super-user */ char password[100]; char pwbuf[100]; int ttybuf[3]; main() { register char *p, *q; if(getpw("root", pwbuf)) goto badpw; p = pwbuf; while(*p != ':') if(*p++ == '\0') goto badpw; if(*++p == ':') goto ok; gtty(0, ttybuf); ttybuf[2] =& ~010; stty(0, ttybuf); printf("password: "); q = password; while((*q = getchar()) != '\n') if(*q++ == '\0') return; *q = '\0'; ttybuf[2] =| 010; stty(0, ttybuf); printf("\n"); q = crypt(password); while(*q++ == *p++);# /* * print file with headings * 2+head+2+page[56]+5 */ int ncol 1; char *header; int col; int icol; int file; char *bufp; #define BUFS 5240 char buffer[BUFS]; #define FF 014 int line; char *colp[72]; int nofile; char isclosed[10]; int peekc; int fpage; int page; int colw; int nspace; int width 72; int length 66; int plength 61; int margin 10; int ntflg; int mflg; int tabc; char *tty; int mode; struct inode { int dev; int inum; int flags; char nlink; char uid; char gid; char siz0; int size;r; plength = length-5; if (ntflg) plength = length; if (mflg) fp = 0; if (fp) { file = open(fp, 0); if (file<0) return; fstat(file, &sbuf); } else { file = 0; time(sbuf.mtime); } if (--ncol<0) ncol = 0; if (header == 0) header = fp; cbuf = ctime(sbuf.mtime); cbuf[16] = '\0'; cbuf[24] = '\0'; page = 1; icol = 0; colp[ncol] = bufp = buffer; if (mflg==0) nexbuf(); while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) { if (mflg==0) { colp[ncol]--; if (colp[ncol] < buffetzu{; if (rbufp >= &buffer[BUFS]) rbufp = buffer; *rbufp = 0375; } bufp = rbufp; } tpgetc(ai) { register char **p; register int c, i; i = ai; if (mflg) { if ((c = getc(&buffer[524*i])) < 0) { /***/ if (isclosed[i]==0) { isclosed[i] = 1; if (--nofile <= 0) return(0); } return('\n'); } if (c==FF && ncol>0) c = '\n'; return(c); } loop: c = **(p = &colp[i]) & 0377; if (c == 0375) { nexbuf(); c = **p & 0377; } if (c == 0376) return(0); (*p)++; if (*p >= &b# /* mail command usage mail prints your mail mail people sends standard input to people */ #define SIGINT 2 struct utmp { char name[8]; char tty; char pad1; int ltime[2]; int pad2; }; struct passwd { char *pw_name; char *pw_passwd; int pw_uid; int pw_gid; char *pw_gecos; char *pw_dir; char *pw_shell; }; char lettmp[] "/tmp/maxxxxx"; char preptmp[] "/tmp/mbxxxxx"; int pwfil; main(argc, argv) char **argv; { register me; extern fout; register struct passwd *p; register char *cp; passwd *p; setpw(); while (p = getpwent()) { if (equal(p->pw_name, person)) { if (prepend(lettmp, cat(p->pw_dir, "/.mail"))==0) break; return; } } fout = 1; flush(); printf("Can't send to %s.\n", person); if (ttyn(0)!='x' && saved==0) { unlink("dead.letter"); saved++; printf("Letter saved in 'dead.letter'\n"); prepend(lettmp, "dead.letter"); } } prepend(from, to) char *from, *to; { extern int fin, fout; fcreat(preptmp, &fout); fopen(from, &fin); while (putchar(getchar()case 020000: case 060000: return(0); /* directory */ case 040000: len = (stbuf.size1+511)/512; total =+ len; if (aflag) printf("%4d %s\n", len, file); if ((fi = open(file, 0)) < 0) msg("can't open"); else { tot = 0; while (read(fi, buff, 16) == 16) if ((buff[0] | buff[1]) != 0 && (buff[2] != '.' || (buff[3] != '\0' && (buff[3] != '.' || buff[4] != '\0'))) && nxtpath(&buff[2])) { tot =+ du(); lstpath(); } close(fi); if (!( } f = creat(tfil, 0600); if(f < 0) { printf("cannot create %s\n", tfil); exit(); } fout = f; if ((signal(2, 1) & 01) ==0) signal(2, onintr); pass1(); flush(); close(fin); fin = 0; close(fout); fout = 1; f = fork(); if(f < 0) { printf("try again\n"); exit(); } if(f == 0) { execl("/bin/sort", "sort", "-d", "-o", tfil, tfil, 0); execl("/usr/bin/sort", "sort", "-d", "-o", tfil, tfil, 0); printf("someone moved sort\n"); exit(); } while(wait() != f); fin = open(tfil, 0); if(uffer[BUFS]) *p = buffer; if (c==0) goto loop; return(c); } pgetc(i) { register int c; if (peekc) { c = peekc; peekc = 0; } else c = tpgetc(i); if (tabc) return(c); switch (c) { case '\t': icol++; if ((icol&07) != 0) peekc = '\t'; return(' '); case '\n': icol = 0; break; case 010: case 033: icol--; break; } if (c >= ' ') icol++; return(c); } puts(as) char *as; { register int c; register char *s; if ((s=as)==0) return; while (c = *s++) put(c); } pustatic struct utmp ubuf; int uf; maketemp(); if (argc==1 || argc==2 && argv[1][0]=='-') { printmail(argc, argv); delexit(); } signal(SIGINT, delexit); fout = creat(lettmp, 0600); if (((me=ttyn(1))!='x' || (me=ttyn(2))!='x') && (uf = open("/etc/utmp", 0)) > 0) { while (read(uf, &ubuf, sizeof ubuf) == sizeof ubuf) if (ubuf.tty == me) { ubuf.name[8] = ' '; close(uf); for (cp=ubuf.name; *cp++!=' ';); *--cp = 0; bulkmail(argc, argv, ubuf.name); } } me = getuid() & 0377)); close(fin); fopen(to, &fin); while (putchar(getchar())); close(fin); flush(); close(fout); if (fcreat(to, &fout) < 0) { fout = 1; return(0); } fopen(preptmp, &fin); while(putchar(getchar())); flush(); close(fout); close(fin); fout = 1; return(1); } setpw() { extern fin; if (pwfil == 0) { fopen("/etc/passwd", &fin); pwfil = fin; } else fin = pwfil; (&fin)[1] = 0; seek(fin, 0, 0); } getpwent() { register char *p; register c; static struct passwd passwd; static char lin); p2--; p1 = ap2; while (*p2++ = *p1++); return(fn); } aflag | sflag)) printf("%4d %s\n", tot, file); } return(len); } } nxtpath(fn) char *fn; { register char *f, *t, *p; f = fend; if (f[-1] != '/') *f++ = '/'; for (p = fn; p < &fn[14] && (*f = *p++); ++f) if (f>=&file[sizeof(file)-1]) { msg("name too long"); return(0); } fend = f; return(1); } lstpath() { register char *f, *t; f = fend; while (--f >= file && *f != '/') ; *f = '\0'; fend = f; } msg(s) char *s; { puts(file); puts(" -- "); puts(s); putchar('\n'); } pfin < 0) { printf("cannot reopen %s\n", tfil); exit(); } if (argc>=3) f = creat(argv[2], 0666); else f = dup(1); if(f < 0) { printf("%s: cannot open\n", argv[2]); exit(); } fout = f; pass2(); flush(); onintr(); } onintr() { unlink(tfil); exit(); } pass1() { int n, c, i, ll, j, k, cc, ccc; loop: if ((c=getchar())=='\0') return; n = 0; i = 0; while(c!='\n' && c!='\0') { if(c == '(') c = 0177; if(c==' ' || c=='\t') { i++; c = getchar(); continue; } if(i) { td(an) { register int a, n; n = an; if (a = n/10) putd(a); put(n%10 + '0'); } put(ac) { register int ns, c; c = ac; if (tabc) { putcp(c); if (c=='\n') line++; return; } switch (c) { case ' ': nspace++; col++; return; case '\n': col = 0; nspace = 0; line++; break; case 010: case 033: if (--col<0) col = 0; if (--nspace<0) nspace = 0; } while(nspace) { if (nspace>2 && col > (ns=((col-nspace)|07))) { nspace = col-ns-1; putcp('\t'); } else { n; setpw(); for (;;) if ((p = getpwent()) && p->pw_uid == me) bulkmail(argc, argv, p->pw_name); fout = 1; printf("Who are you?\n"); delexit(); } printmail(argc, argv) char **argv; { extern fin, fout; register n, c, f; if (fopen(".mail", &fin)>=0 && (c = getchar())) { do { putchar(c); } while (c = getchar()); close(fin); c = 'y'; if (argc<2) { if (ttyn(0)!='x') { printf("Save?"); fin = 0; c = getchar(); } } else c = argv[1][1]; if (c=='y') { prepend(".mae[100]; extern fin; p = line; while((c=getchar()) != '\n') { if(c <= 0) return(0); if(p < line+98) *p++ = c; } *p = 0; p = line; passwd.pw_name = p; p = pwskip(p); passwd.pw_passwd = p; p = pwskip(p); passwd.pw_uid = atoi(p); p = pwskip(p); passwd.pw_gid = atoi(p); p = pwskip(p); passwd.pw_gecos = p; p = pwskip(p); passwd.pw_dir = p; p = pwskip(p); passwd.pw_shell = p; return(&passwd); } pwskip(ap) char *ap; { register char *p; p = ap; while(*p != ':') { if(*p == 0) /* * Quick and dirty version of du * * - no inumber check is made, so links are counted twice */ char *dargv[] { "." }; struct { int dev; int ino; int flags; char nlinks; char uid; char gid; char size0; int size1; int addr[8]; int actime[2]; int mtime[2]; } stbuf; char buff[16]; char file[128]; char *fend file; int sflag; int aflag; int total; main(argc, argv) char **argv; { register char *p, *q; while (--argc > 0 && **++argv == '-') { if (argv[0][1] == 's') sflag++; else if uts(s) char *s; { register char *p; for (p = s; putchar(*p); p++) ; } i = 0; if(n<=llen) line[n++] = ' '; } if (n<=llen) line[n++] = c; c = getchar(); } ll = n; line[n++] = 0; i = -1; l1: while((cc=line[++i])==' '); n = i; j = 0; while(sw[j]) { i = n; k = 0; while ((cc=sw[j][k++])==line[i++]); if(cc==0 && ((ccc=line[--i])==' '||ccc==0)) goto l1; j++; } i = n; while (c=line[n++]) putchar(c); putchar('~'); n = 0; while (n= ' ') col++; putcp(c); } getn(ap) char *ap; { register int n, c; register char *p; p =ap; n = 0; while ((c = *p++) >= '0' && c <= '9') n = n*10 + c - '0'; return(n); } putcp(c) { if (page >= fpage) putchar(c); } il", "mbox"); printf("Saved mail in 'mbox'\n"); } close(creat(".mail")); } else printf("No mail.\n"); } bulkmail(argc, argv, from) char **argv, *from; { extern fin, fout; int tbuf[2]; register c; fin = 0; (&fin)[1] = 0; time(tbuf); printf("From %s %s", from, ctime(tbuf)); while (c = getchar()) putchar(c); putchar('\n'); flush(); close(fout); while (--argc > 0) sendto(*++argv); delexit(); } sendto(person) char *person; { static saved; extern fout; extern fin; register structreturn(p); p++; } *p++ = 0; return(p); } delexit() { unlink(lettmp); unlink(preptmp); exit(0); } maketemp() { int i, pid, d; pid = getpid(); for (i=11; i>=7; --i) { d = (pid&07) + '0'; lettmp[i] = d; preptmp[i] = d; pid =>> 3; } } equal(as1, as2) { register char *s1, *s2; s1 = as1; s2 = as2; while (*s1++ == *s2) if (*s2++ == 0) return(1); return(0); } cat(ap1, ap2) char *ap1, *ap2; { register char *p1, *p2; static char fn[32]; p1 = ap1; p2 = fn; while (*p2++ = *p1++(argv[0][1] == 'a') aflag++; } if (argc < 1) { argv = dargv; argc = 1; } while (argc--) { p = *argv++; for (q = file; *q = *p++; *q++) ; fend = q; du(); } printf("Total %d\n", total); } du() { register fi, len, tot; if (stat(file, &stbuf) < 0) { msg("can't find"); return(0); } switch (stbuf.flags & 060000) { /* ordinary file */ case 0000000: len = (stbuf.size1+511)/512; total =+ len; if (aflag) printf("%4d %s\n", len, file); return(len); /* special file */ /* permuted title index */ char *tfil "/tmp/p.tmp"; char *sw[] { "a", "an", "and", "as", "for", "is", "of", "on", "or", "the", "to", "up", 0}; char line[200]; int ch; int ptflg; int llen 72; main(argc, argv) int argc; char *argv[]; { extern fin, fout; extern onintr(); int f; if(argc>1 && *argv[1]=='-') { llen = 100; ptflg++; argc--; argv++; } if(argc<2) { printf("arg count\n"); exit(); } fin = open(argv[1]); if(fin < 0) { printf("%s: cannot open\n", argv[1]); exit(); if (c) goto l1; goto loop; } pass2() { int i, n, c, tilde, llen2, nbfore, nafter; llen2 = llen/2+6; loop: if ((c=getchar())=='\0') return; n = nbfore = nafter = 0; tilde = -1; while(c!='\n' && c!='\0') { if(c == 0177) c = '('; if (n<=llen) line[n] = c; if (c=='~') tilde = n; if (tilde>=0) nafter++; else nbfore++; n++; c = getchar(); } if (tilde<0) tilde = n++; nafter--; if (nbfore>llen2) { i = tilde; while (nbfore > llen2) while(line[--i]!=' ' && i>=0) nbfore--; if (i<0) goto l1; line[tilde] = 0200; nafter =+ (tilde-i+2); tilde = i; } if (nafter >= llen-llen2) { i = tilde; while(nafter-- >= llen-llen2) while(line[++i]!=' ' && i=n) goto l1; line[tilde] = 0200; nafter++; tilde = i; } l1: if(!ptflg) { for(i=llen-llen2-nafter; i>=8; i =- 8) putchar('\t'); while(--i>=0) putchar(' '); } else printf(".xx \""); i = tilde; while (++i> 3; } /* * create file & reopen in input/output mode */ if ((tfi = creat(tfname, 0600)) < 0) error("Can't crear aname[12]; if (nfiles) return(0); cpy8(dir.fname, aname); curname = aname; return(1); } /* * Compare two 8-char strings */ cmp8(s1, s2) char *s1, *s2; { register char *p, *q; register i; p = s1; q = s2; for (i=0; i<8; i++) { if (p[i] != q[i]) return(0); if (p[i] == '\0') break; } return(1); } /* * Copy 8 chars of a filename */ cpy8(s1, s2) char *s1, *s2; { register char *p, *q; register i; p = s1; q = s2; for (i=0; i < 8; i++) if ((q[i] = p[i]) == '\0') break; whi] = stbuf.s_mtime[1]; dir.uid = stbuf.s_uid; dir.mode = stbuf.s_flags & 0377; dir.size = stbuf.s_size1; write(tfi, &dir, sizeof dir); /* copy file */ for (size = dir.size; size >= 512; size =- 512) { if (read(ifi, buff, 512) != 512) error(inpio); write(tfi, buff, 512); } if (size) { if (read(ifi, buff, size) != size) error(inpio); write(tfi, buff, size); } close(ifi); /* pad to halfword if necessary */ if (size & 01) write(tfi, &zero, 1); } /* * Copy a file from the archive to(afname, afmode)) < 0) error(nocreat); seek(tfi, 0, 0); while ((len = read(tfi, buff, 512)) > 0) write(fd, buff, len); if (len < 0) error(tmpio); unlink(tfname); } /* * Error exit */ error(s) { printf("%s\n", s); dexit(); } /* * Delete temp file & exit */ dexit() { if (tfi) unlink(tfname); exit(1); } ile(++i= 512; size =- 512) { readaf(512); write(tfi, buff, 512); } if (size) { readaf(size); write(tfi, buff, size); } /* pad to halfword if necessary */ if (size & 01) { seek(afi, 1, 1); write(tfi, &zero, 1); } } /* * Skip to the next file in the archive */ skipfl() { register s; s = (dir.size+1) & ~01; seek(afi, s, 1); } /* * Verbocpall \ ar \ cat \ chmod \ cmp \ cp \ date \ dd \ df \ dsw \ du \ echo \ ed \ exit \ file \ goto \ if \ kill \ ld \ ln \ login \ ls \ mail \ mkdir \ mv \ newgrp \ nm \ od \ passwd \ pr \ ps \ rm \ rmdir \ sh \ size \ sort \ strip \ stty \ su \ sync \ time \ tty \ who \ write \ /bin cpall \ arcv \ cal \ col \ comm \ cpall \ crypt \ diff \ find \ grep \ mesg \ nice \ nohup \ prof \ ptx \ pwd \ quiz \ sleep \ split \ tee \ tr \ uniq \ units \ usort \ wc \ /usr/bin rm \ ar \ arcv \ cal \ cat \ chmod \ cmp \ c /* * Archiver: * * A free translation of ar.s */ char usage[] "Usage: ar -drtx archive [file ...]"; char noar[] "No archive file"; char noup[] "Archive file not updated"; char nocreat[] "Can't create archive file"; char badform[] "Bad archive format"; char readio[] "Archive file read i/o error"; char inpio[] "Input file i/o error"; char tmpio[] "Temp file i/o error"; char tfname[] "/tmp/arXXXXXXX"; int magic 0177555; /* magic word to identify archive format file */ struct { /* archive file headeaf()) error(noar); while (getdir()) if (match()) { msg('d'); skipfl(); } else { msg('c'); copyfl(); } while (leftover()) nfound(); copyback(); } /* * Replace or append files in the archive */ replace() { mktemp(); if (getaf()) while (getdir()) if (match()) { msg('r'); skipfl(); infl(); } else { msg('c'); copyfl(); } while (leftover()) { msg('a'); infl(); } copyback(); } /* * List table of contents */ table() { if (!getaf()) erroextern char *ctime(); register char *p; printf("%-8.8s", dir.fname); if (vflag) { printf("%8d", dir.size); p = ctime(dir.mtime); printf(" %-12.12s", &p[4]); } putchar('\n'); } /* * Extract a file from the archive */ exfl() { register ofi, len, size; /* create new file with mode & owner of archived file */ if ((ofi = creat(curname, dir.mode|0400)) < 0) { printf("-- %s: can't create\n", dir.fname); nerr++; skipfl(); return; } /* copy file */ for (size = dir.size; size >= 512; sise option -- running commentary */ msg(ch) { if (vflag) printf("%c %.8s\n", ch, dir.fname); } /* * Error message for missing file */ nfound() { printf("-- %.8s not found\n", trim(curname)); /* record error so archive will not be updated */ nerr++; } /* * All finished -- replace archive with new temporary file */ copyback() { register fd, len; /* if any errors have occured, don't update the archive */ if (nerr) error(noup); /* create archive file if it didn't exist before */ if (afi < ol \ comm \ cp \ cpall \ crypt \ date \ dd \ df \ diff \ dsw \ du \ echo \ ed \ exit \ file \ find \ goto \ grep \ if \ kill \ ld \ ln \ login \ ls \ mail \ mesg \ mkdir \ mv rm \ newgrp \ nice \ nm \ nohup \ od \ passwd \ pr \ prof \ ps \ ptx \ pwd \ quiz \ rm \ rmdir \ sh \ size \ sleep \ sort \ split \ strip \ stty \ su \ sync \ tee \ time \ tr \ tty \ uniq \ units \ usort \ wc \ who \ write r */ char fname[8]; int mtime[2]; char uid; char mode; int size; } dir; struct { /* buffer for stat() */ int s_dev; int s_ino; int s_flags; char s_nlinks; char s_uid; char s_gid; char s_size0; int s_size1; int s_addr[8]; int s_atime[2]; int s_mtime[2]; } stbuf; char **ffile, **lfile; /* first & last file in arg list */ int nfiles; /* no. of files in arg list */ char *curname; /* name of current file arg */ char *afname; /* name of archive file */ int afmode; /* protect moder(noar); while (getdir()) { if (all() || match()) tabfl(); skipfl(); } while (leftover()) nfound(); } /* * Extract files from the archive */ extract() { if (!getaf()) error(noar); while (getdir()) if (all() || match()) { msg('x'); exfl(); } else skipfl(); while (leftover()) nfound(); } /* * Open archive file & check format */ getaf() { if (stat(afname, &stbuf) < 0) { afmode = 0666; afi = -1; return(0); } if ((afi = open(afname, 0)) < 0) error("Can't open)) == sizeof dir) return(1); if (len == 0) /* end of file */ return(0); if (len < 0) /* i/o error */ error(readio); error(badform); /* premature eof */ } /* * Test whether current header filename matches any argument file */ match() { register char **fn; register i; for (fn = ffile; fn < lfile; fn++) if (*fn && cmp8(trim(*fn), dir.fname)) { curname = *fn; *fn = 0; return(1); } return(0); } /* * If no filename arguments, match all files in archive */ all() { static chaze =- 512) { readaf(512); write(ofi, buff, 512); } if (size) { readaf(size); write(ofi, buff, size); } close(ofi); /* pad to halfword if necessary */ if (size & 01) seek(afi, 1, 1); } /* * Copy a file into the (temporary) archive */ infl() { register size, ifi; if (stat(curname, &stbuf) < 0 || (ifi = open(curname, 0)) < 0) { printf("-- %s: can't open\n", curname); nerr++; return; } /* make header */ cpy8(trim(curname), dir.fname); dir.mtime[0] = stbuf.s_mtime[0]; dir.mtime[10) { if ((fd = creat(afname, afmode)) < 0) error(nocreat); fstat(fd, &stbuf); afdev = stbuf.s_dev; close(fd); } else close(afi); /* prevent interrupts while moving back */ signal(1, 1); signal(2, 1); /* if temp & archive files on same device, just do a mv */ stat(tfname, &stbuf); if (stbuf.s_dev == afdev) { unlink(afname); if (link(tfname, afname) < 0) error(nocreat); unlink(tfname); chmod(afname, afmode); return; } /* copy temp file to archive file */ if ((fd = creat/* * strip file [...] */ int buf[512/sizeof(int)]; int fi, fo; char *tf; struct { /* buffer for fstat() call */ int dev; int ino; int mode; int pad[15]; } stbuf; main(argc, argv) char **argv; { extern int delexit(); tf = mktemp("/tmp/stmXXXXX"); signal(1, delexit); signal(2, delexit); signal(3, delexit); while (--argc) { fi = fo = -1; strip(*++argv); if (fi > 0) close(fi); if (fo > 0) close(fo); } delexit(); } delexit() { unlink(tf); exit(); } #define ERR(msg) return(printf(error, file, msg)) char error[] = "%s: %s\n"; strip(file) register char *file; { register int size, len; if ((fi = open(file, 0)) < 0) ERR("can't open"); if ((fo = creat(tf, 0600)) < 0) ERR("can't create temp file"); if (read(fi, buf, 8*sizeof(int)) != 8*sizeof(int)) ERR("bad format"); switch (buf[0]) { /* Check a.out magic word */ default: ERR("bad format"); case 0407: case 0410: case 0411: ; } if (buf[7]) /* Already stripped? */ return; size = buf[1] + buf[2]; /* tcts the equivalence classes in file1 together. * Subroutine equiv____ replaces the value of each line in * file0 by the index of the first element of its * matching equivalence in (the reordered) file1. * To save space equiv_____ squeezes file1 into a single * array member______ in which the equivalence classes * are simply concatenated, except that their first * members are flagged by changing sign. * * Next the indices that point into member______ are unsorted_______ into zation and * maximize the range of doable problems by dynamically * allocating what is needed and reusing what is not. * The core requirements for problems larger than somewhat * are (in words) 2*length(file0) + length(file1) + * 3*(number of k-candidates installed), typically about * 6n words for files of length n. There is also space for buf1 * used which could, by moving data underfoot and reallocating * buf1 together with buf2, be completely overlaid. */ struct buf { int fdes; char data[524]; /***/ ue > ai[0].value || aim->value == ai[0].value && aim->serial > ai[0].serial) break; w.value = ai[0].value; ai[0].value = aim->value; aim->value = w.value; w.serial = ai[0].serial; ai[0].serial = aim->serial; aim->serial = w.serial; } } } } unsort(f, l, b) struct line *f; int *b; { int *a; int i; a = alloc((l+1)*sizeof(a[0])); for(i=1;i<=l;i++) a[f[i].serial] = f[i].value; for(i=1;i<=l;i++) b[i] = a[i]; area = a; } prepare(i, arg) char *arg; { regstruct cand **c; { register int i, k,y; int j, l; int skip; k = 0; c[0] = 0; for(i=1; i<=n; i++) { j = a[i]; if(j==0) continue; skip = 0; do { y = b[j]; if(y<0) y = -y; if(skip) continue; l = search(c, k, y); if(l > k) { c[k+1] = newcand(i,y,c[k]); skip = 1; k++; } else if(c[l]->y > y && c[l]->x < i) c[l] = newcand(i,y,c[l-1]); } while(b[++j] > 0); } return(k); } struct cand * newcand(x,y,pred) struct cand *pred; { struct cand *p; p = alloc(sidir = **argv=='-'; fout = dup(1); buf1->fdes = open(argv[1],0); buf2->fdes = open(argv[2],0); m = len[0]; J[0] = 0; J[m+1] = len[1]+1; if(dir==0) for(i0=1;i0<=m;i0=i1+1) { while(i0<=m&&J[i0]==J[i0-1]+1) i0++; j0 = J[i0-1]+1; i1 = i0-1; while(i1=1;i0=i1-1) { while(i0>=1&&J[i0]==J[i0+1]-1&&J[i0]!=0) i0--; j0 = J[i0+1]-1; i1 = i0+1; while(i1>1&&J[i1-1]==0) i1--; j1 = J[i1-1]+1; J[i1] ext + data size */ buf[4] = 0; /* symtab size */ buf[7] = 1; /* no relocation bits */ if (write(fo, buf, 8*sizeof(int)) != 8*sizeof(int)) ERR("temp file write error"); while (size > sizeof(buf)) { if (read(fi, buf, sizeof(buf)) != sizeof(buf)) ERR("unexpected eof"); if (write(fo, buf, sizeof(buf)) != sizeof(buf)) ERR("temp file write error"); size -= sizeof buf; } if (size) { if (read(fi, buf, size) != size) ERR("unexpected eof"); if (write(fo, buf, size) != size) ERR("tem* array class_____ according to the original order of file0. * * The cleverness lies in routine stone______. This marches * through the lines of file0, developing a vector klist_____ * of "k-candidates". At step i a k-candidate is a matched * pair of lines x,y (x in file0 y in file1) such that * there is a common subsequence of lenght k * between the first i line file0 and the first y * lines of file1, but there is no such subsequence for * any smaller y. x is the earliest possible mate to y} *buf1, *buf2; struct cand { int x; int y; struct cand *pred; } cand; struct line { int serial; int value; } *file[2], line; int len[2]; int *class; /*will be overlaid on file[0]*/ int *member; /*will be overlaid on file[1]*/ struct cand **klist; /*will be overlaid on file[0] after class*/ int *J; /*will be overlaid on class*/ int *ixold; /*will be overlaid on klist*/ int *ixnew; /*will be overlaid on file[1]*/ struct cand *newcand(); char *area; char *top; alloc(n) { register char *p; p = area;ister char *temp; temp = file[i] = area; alloc(sizeof(line)); input(arg); len[i] = (area - temp)/sizeof(line) - 1; alloc(sizeof(line)); sort(file[i], len[i]); } input(arg) { register int h, i; register struct line *p; if(fopen(arg,buf1) == -1) { mesg("Cannot open "); mesg(arg); mesg("\n"); exit(1); } for(i=0; h=readhash(buf1);) { p = alloc(sizeof(line)); p->serial = ++i; p->value = h; } close(buf1->fdes); } equiv(a,n,b,m,c) struct line *a, *b; int *c; { register int i, j; i = zeof(cand)); p->x = x; p->y = y; p->pred = pred; return(p); } search(c, k, y) struct cand **c; { register int i, j, l; int t; i = 0; j = k+1; while((l=(i+j)/2) > i) { t = c[l]->y; if(t > y) j = l; else if(t < y) i = l; else return(l); } return(l+1); } unravel(p) struct cand *p; { int i; for(i=0; i<=len[0]; i++) J[i] = 0; while(p) { J[p->x] = p->y; p = p->pred; } } /* check does double duty: 1. ferret out any fortuitous correspondences due to counfounding by hashing = j1; change(i1,i0,j1,j0,dir); } if(m==0) change(1,0,1,len[1],dir); flush(); } change(a,b,c,d,dir) { if(a>b&&c>d) return; range(a,b); putchar(a>b? 'a' : (c>d?'d':'c')); if(dir==0) range(c,d); putchar('\n'); if(dir==0) { fetch(ixold,a,b,buf1,"* "); if(a<=b&&c<=d) printf("---\n"); } fetch(ixnew,c,d,buf2,dir==0?". ":""); if(dir!=0&&c<=d) printf(".\n"); } range(a,b) { if(a>b) printf("%d",b); if(a<=b) printf("%d",a); if(a 0) if (write(fo, buf, len) != len) ERR("temp file write error"); if (len < 0) ERR("temp file read error"); } * that occurs in such a subsequence. * * Whenever any of the members of the equivalence class of * lines in file1 matable to a line in file0 has serial number * less than the y of some k-candidate, that k-candidate * with the smallest such y is replaced. The new * k-candidate is chained (via pred____) to the current * k-1 candidate so that the actual subsequence can * be recovered. When a member has serial number greater * that the y of all k-candidates, the klist is extended. * At the end, the long n = (n+3) & ~3; /***/ area =+ n; while(area > top) { if(brk(top =+ 1024) == -1) { /***/ mesg("Out of space\n"); exit(1); } } return(p); } mesg(s) char *s; { while(*s) write(2,s++,1); } sort(a,n) /*shellsort CACM #201*/ struct line *a; { struct line w; register int j,m; struct line *ai; register struct line *aim; int k; for(j=1;j<=n;j=* 2) m = 2*j - 1; for(m=/2;m!=0;m=/2) { k = n-m; for(j=1;j<=k;j++) { for(ai = &a[j]; ai > a; ai =- m) { aim = &ai[m]; if(aim->valj = 1; while(i<=n && j<=m) { if(a[i].value 1 && *argv[1]=='-') { argc--; argv++; } if(argc!=3) { mesg("Arg count\n"); exit(1); } area = top = (which result in "jackpot") 2. collect random access indexes to the two files */ check(argv) char **argv; { register int i, j; int ctold, ctnew; int jackpot; char c,d; fopen(argv[1],buf1); fopen(argv[2],buf2); j = 1; ctold = ctnew = 0; ixold[0] = ixnew[0] = 0; jackpot = 0; for(i=1;i<=len[0];i++) { if(J[i]==0) { while(getc(buf1)!='\n') ctold++; ixold[i] = ++ctold; continue; } while(jfdes,f[i-1],0); nc = read(lb->fdes,lb->data,f[i]-f[i-1]); printf(pref); for(j=0;jdata[j]); } } /*** Hash routine: *** Originally written in pdp-11 assembler *** *** Should probably be rewritten in assembler for efficiency *** R Miller ***/ readhash(buff) char *buff; { register char *bp; register first, hash, c, off; first = hash = 1; off = 0; bp = buff; while ((c = getc(bp)) > 0) { if (c =/* diff - differential file comparison * * Uses an algorithm due to Harold Stone, which finds * a pair of longest identical subsequences in the two * files. * * The major goal is to generate the match vector J. * J[i] is the index of the line in file1 corresponding * to line i file0. J[i] = 0 if there is no * such line in file1. * * Lines are hashed so as to work in core. All potential * matches are located by sorting the lines of each file * on the hash (called value_____). In particular, this * colleest subsequence is pulled out * and placed in the array J by unravel_______. * * With J in hand, the matches there recorded are * check_____ed against reality to assure that no spurious * matches have crept in due to hashing. If they have, * they are broken, and "jackpot " is recorded--a harmless * matter except that a true match for a spuriously * mated line may now be unnecessarily reported as a change. * * Much of the complexity of the program comes simply * from trying to minimize core utilisbrk(0); buf1 = alloc(sizeof(*buf1)); prepare(0, argv[1]); prepare(1, argv[2]); member = file[1]; equiv(file[0], len[0], file[1], len[1], member); class = file[0]; unsort(file[0], len[0], class); klist = &class[len[0]+2]; area = &member[len[1]+2]; k = stone(class, len[0], member, klist); J = class; unravel(klist[k]); ixold = klist; ixnew = file[1]; area = &ixnew[len[1]+2]; buf2 = alloc(sizeof(*buf2)); if(check(argv)) mesg("Jackpot\n"); output(argv); } stone(a,n,b,c) int *a; int *b; 1))==(d=getc(buf2))) { if(c=='\n') break; ctold++; ctnew++; } while(c!='\n') { jackpot++; J[i] = 0; c = getc(buf1); ctold++; } ixold[i] = ++ctold; while(d!='\n') { jackpot++; J[i] = 0; d = getc(buf2); ctnew++; } ixnew[j] = ++ctnew; j++; } for(;j<=len[1];j++) { while(getc(buf2)!='\n') ctnew++; ixnew[j] = ++ctnew; } close(buf1->fdes); close(buf2->fdes); return(jackpot); } output(argv) char **argv; { int dir; int m; int i0,i1,j0,j1; extern fout; = '\n') return(hash); hash =+ (c<>(16-off); if ((off =+ 7) >= 16) off =- 16; } if (!first) write(2, "Incomplete line omitted\n", 24); return(0); } /** *** *** / hash routine for diff *** / effectively spreads the string out into 7-bit *** / bytes, then sums the result 1's-complement *** / by 16-bit bytes and adds 1 to avoid zero answer *** *** / r4 hash accumulator *** / r3 current offset *** / r2 first time flag *** .globl _readhash *** .globl getc *** *** .data *** _readhash: *** mov 2(sp),0f *** mov r5,-(sp) *** mov r4,-(sp) *** mov r3,-(sp) *** mov r2,-(sp) *** mov $1,r4 *** mov r4,r2 *** clr r3 *** 1: *** jsr r5,getc; 0: 0 *** bes 2f *** clr r2 *** cmp r0,$'\n *** beq 1f *** ashc $-16.,r0 *** ashc r3,r0 *** add r0,r4 *** adc r4 *** add r1,r4 *** adc r4 *** add $7,r3 *** cmp r3,$16. *** blt 1b *** sub $16.,r3 *** br 1b *** 2: *** tst r2 *** bne 2f *** mov $2,r0 *** sys write; 3f; 4f-3f *** 2: *** clr r4 *** 1: *** mov r4,r0 *** m[128]; char dict[128] { 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 }; char nodict[128] { 1 }; struct field { char *code; char *ignore; int nflg; int rflg; int bflg; char *m[2]; char *n[2]; } fields[NF]; int proto[9] { &fold, &nodict, 0, 1, 0, 0,-1, 0,0 }; int nfields; p++; if ((signal(2, 1) & 01) == 0) signal(2, term); nfiles = eargc; if(!mflg) { ibuf[0] = -1; sort(); close(0); } for(a = mflg?0:eargc; a+N < nfiles; a=+N) { newfile(); merge(a, a+N); } if(a != nfiles) { oldfile(); merge(a, nfiles); } error = 0; term(); } sort() { register char *cp; register *lp, c; int done; int i; int f; done = 0; i = 0; do { cp = tspace; lp = lspace; while(lp < lspace+nlines && cp < tspace+ntext) { *lp++ = cp; while((*cp++ = c = getc(ibuf))[i]; if(*cp == '\0') { l = 1; if(rline(ibuf[i])) { k = i; while(++k < j) ibuf[k-1] = ibuf[k]; j--; } } } } while(l); i = j; if(i > 0) for(;;) { cp = ibuf[i-1]; if(i == 1 || cmp(&ibuf[i-1], &ibuf[i-2])) do putc(*cp, obuf); while(*cp++ != '\n'); if(rline(ibuf[i-1])) { i--; if(i == 0) break; } cp = &ibuf[i]; while (--cp.ip > ibuf && cmp(cp.ip, cp.ip-1) < 0) { p = *cp.ip; *cp.ip = *(cp.ip-1); *(cp.ip-1) = p; } } p = lspace++; i = fp->n[j]; while(i-- > 0) { if(*p != '\n') p++; else goto ret; } ret: return(p); } digit(c) { return(c <= '9' && c >= '0'); } mess(s) char *s; { while(*s) write(2, s++, 1); } copyproto() { register int i, *p, *q; p = proto; q = &fields[nfields]; for(i=0; icode = nofold; xc(j, lp =- es, i); j = hp =- es; } } qsexc(i, j) char *i, *j; { register char *ri, *rj, c; int n; n = qses; ri = i; rj = j; do { c = *ri; *ri++ = *rj; *rj++ = c; } while(--n); } qstexc(i, j, k) char *i, *j, *k; { register char *ri, *rj, *rk; char c; int n; n = qses; ri = i; rj = j; rk = k; do { c = *ri; *ri++ = *rk; *rk++ = *rj; *rj++ = c; } while(--n); } ov (sp)+,r2 *** mov (sp)+,r3 *** mov (sp)+,r4 *** mov (sp)+,r5 *** rts pc *** 3: *** *** 4: *** .even *** **/ int error 1; char *setfil(); main(argc, argv) char **argv; { register a, i; char *arg; register int *p; int *q; for(a=0; a<128; a++) nofold[a] = a; nodict[127] = 1; copyproto(); eargv = argv; while (--argc > 0) { if(**++argv == '-') for(arg = *argv;;) { switch(*++arg) { case '\0': if(arg[-1] == '-') eargv[eargc++] = "-"; break; case 'm': mflg++; continue; case 'o': if(--argc > 0) outfil = *++argv; continue; default: field(++*argv,1); != '\n') { if(c >= 0) continue; cp--; close(ibuf[0]); if(i < eargc) { if((f = setfil(i++)) == 0) ibuf[0] = 0; else if(fopen(f, ibuf) < 0) cant(f); } else break; } if(c < 0) { done++; lp--; break; } } qsort(lspace, lp-lspace, sizeof(*lspace), cmp); /***/ if(done == 0 || nfiles != eargc) newfile(); else oldfile(); while(lp > lspace) { cp = *--lp; if(*cp) do putc(*cp, obuf); while(*cp++ != '\n'); } fflush(o; for(i=a; ib[0]); p++; if(i >= eargc) close(creat(setfil(i))); } fflush(obuf); close(obuf[0]); } rline(mp) struct merg *mp; { register char *cp; register *bp, c; bp = mp->b; cp = mp->l; do { c = getc(bp); if(c < 0) return(1); *cp++ = c; } while(c != '\n'); *cp = '\0'; return(0); } newfile() { if(fcreat(setfil(nfiles), obuf) < 0) { mess("Can't create temp\n"); term(); } nfiles++; } char * setfil(i) { if(i < eargc) if(eargv[i][0] == '-' && ear break; case 'b': p->bflg++; break; case 'd': p->ignore = dict; break; case 'n': p->nflg++; break; case 't': tabchar = *++s; if(tabchar == 0) s--; break; case 'r': p->rflg = -1; break; default: p->m[k] = number(&s); if(*s == '.') s++; p->n[k] = number(&s); s--; } } } number(ppa) char **ppa; { int n; register char *pa; pa = *ppa; n = 0; while(digit(*pa)) n = n*10 + *pa++ - '0'; *ppa = pa; return(n); } blank(c) { if(c==' ' || c==#define NF 10 #define NL 200 #define NC 200 #define SL 100 #define NA 10 int tflag; int xx[NL]; char score[NL]; int rights; int wrongs; int guesses; int buf[259]; int nl 0; int na NA; int inc; int ptr 0; int nc 0; char line[150]; char response[100]; char *tmp[NF]; int select[NF]; readline() { char *t; loop: for(t=line;(*t=getc(buf))!=-1;t++) { nc++; if(*t==' '&&(t==line||t[-1]==' ')) t--; if(*t=='\n') { if(t[-1]=='\\') /*inexact test*/ continue; while(t>line&&t[-1]==' ') *--t = '#define L 512 #define N 7 #define C 20 #define MEM (16*2048) #define NF 10 int ibuf[3+512/sizeof(int)]; /***/ int obuf[3+512/sizeof(int)]; /***/ char *file; char *filep; int nfiles; int nlines; int ntext; int *lspace; char *tspace; int cmp(); int term(); int mflg; char *outfil; char tabchar; int eargc; char **eargv; char fold[128] { 0000,0001,0002,0003,0004,0005,0006,0007, 0010,0011,0012,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0024,0025,0026,0027, 0030,0031,0032,0033,0034,0035,0036,0037, 0040 break; } break; } else if (**argv == '+') { if(++nfields>=NF) { mess("Too many keys\n"); exit(1); } copyproto(); field(++*argv,0); } else eargv[eargc++] = *argv; } q = &fields[0]; for(a=1; a<=nfields; a++) { p = &fields[a]; for(i=0; i<5; i++) /*sensitive to sizeof(proto)*/ if(p[i] != proto[i]) goto next; for(i=0; i<5; i++) p[i] = q[i]; next: ; } if(eargc == 0) eargv[eargc++] = "-"; a = MEM; i = lspace = sbrk(0); while(brk(a) == -1) a =- 512; gv[i][1] == '\0') return(0); else return(eargv[i]); i =- eargc; filep[0] = i/26 + 'a'; filep[1] = i%26 + 'a'; return(file); } oldfile() { if(outfil) { if(fcreat(outfil, obuf) < 0) { mess("Can't create output\n"); term(); } } else obuf[0] = 1; } cant(f) { mess("Can't open "); mess(f); mess("\n"); term(); } term() { register i; if(nfiles == eargc) nfiles++; for(i=eargc; i=NC) { printf("Too hard for me\n"); do { *line = getc(buf); if(*line==0377) return(0); } while(*line!='\n'); goto loop; } } return(0); } char *eu; char *ev; cmp(u,v) { int x; eu = u; ev = v; x = disj(1); if(x!=1) return(x); return(eat(1,0)); } disj(s) { int t, x; char *u; u = eu; t = 0; for(;;) { x = string(s); if(x>1) return(x); switch(*ev) { case 0: case ']': case '}': return(t|x&s); case '|': ,0041,0042,0043,0044,0045,0046,0047, 0050,0051,0052,0053,0054,0055,0056,0057, 0060,0061,0062,0063,0064,0065,0066,0067, 0070,0071,0072,0073,0074,0075,0076,0077, 0100,0101,0102,0103,0104,0105,0106,0107, 0110,0111,0112,0113,0114,0115,0116,0117, 0120,0121,0122,0123,0124,0125,0126,0127, 0130,0131,0132,0133,0134,0134,0136,0137, 0140,0101,0102,0103,0104,0105,0106,0107, 0110,0111,0112,0113,0114,0115,0116,0117, 0120,0121,0122,0123,0124,0125,0126,0127, 0130,0131,0132,0173,0174,0175,0176,0177 }; char nofoldbrk(a =- 512); /* for recursion */ a =- i; nlines = ((a-L)/sizeof(*lspace)) & 077777; /***/ nlines =/ 5; ntext = nlines*8; tspace = lspace+nlines; file = "/usr/tmp/stmXaa"; loop: filep = file; while(*filep != 'X') filep++; for(*filep = 'a';;(*filep)++) { if(stat(file, lspace) < 0) { a = creat(file, 0600); if(a >= 0) break; } if(*filep == 'z') { if(file[1] != 't') { file = "/tmp/stmXaa"; goto loop; } mess("Cannot locate temp\n"); exit(1); } } close(a); filebuf); close(obuf[0]); } while(done == 0); } struct merg { char l[L]; int b[3+512/sizeof(int)]; /***/ }; merge(a, b) { register struct merg *p; register char *cp; register i; struct { int *ip;}; int f; int j; int k,l,c; p = lspace; j = 0; for(i=a; ib[0] = dup(0); else if(fopen(f, p->b) < 0) cant(f); ibuf[j] = p; if(!rline(p)) j++; p++; } do { i = j; qsort(ibuf, i, sizeof(*ibuf), cmp); /***/ l = 0; while(i--) { cp = ibuf*rb; ra = *a - 1; rb = *b - 1; while(*++ra == *++rb) if(*ra == '\n') return(0); return(*rb - *ra); } skip(pp, fp, j) struct field *fp; char *pp; { register i; register char *p; p = pp; if( (i=fp->m[j]) < 0) return(-1); while(i-- > 0) { if(tabchar != 0) { while(*p != tabchar) if(*p != '\n') p++; else goto ret; p++; } else { while(blank(*p)) p++; while(!blank(*p)) if(*p != '\n') p++; else goto ret; } } if(fp->bflg) while(blank(*p)) pntinue; } } loop: if(j > hp) { if((c = (*qscmp)(hp, j)) == 0) { qsexc(hp =+ es, j); goto loop; } if(c > 0) { if(i == lp) { qstexc(i, hp =+ es, j); i = lp =+ es; goto loop; } qsexc(i, j); j =- es; i =+ es; continue; } j =- es; goto loop; } if(i == lp) { for(k=lp+sizeof(*k); k<=hp;) *(*k++)='\0'; /***/ if(lp-a >= l-hp) { qs1(hp+es, l); l = lp; } else { qs1(a, lp); a = hp+es; } goto start; } qste ev++; t =| s; s = 0; continue; } if(s) eu = u; if(string(0)>1) return(2); switch(*ev) { case 0: case ']': return(0); case '}': return(1); case '|': ev++; continue; default: return(2); } } } string(s) { int x; for(;;) { switch(*ev) { case 0: case '|': case ']': case '}': return(1); case '\\': ev++; if(*ev==0) return(2); if(*ev=='\n') { ev++; continue; } default: if(eat(s,*ev)==1) continue; return(0); case '[': ev++; x = disj(s); if(*ev!=']' || x>1) return(2); ev++; if(s==0) continue; if(x==0) return(0); continue; case '{': ev++; x = disj(s); if(*ev!='}'||x>1) return(2); ev++; continue; } } } eat(s,c) char c; { if(*ev!=c) return(2); if(s==0) { ev++; return(1); } if(fold(*eu)!=fold(c)) return(0); eu++; ev++; return(1); } fold(c) char c; { if(c<'A'||c>'Z') return(c); return(c|040); } publish(t) char *t; { ev = t; pub1(1); } pub1f(argc>2) info = argv[2]; argc =- 2; argv =+ 2; goto loop; case 't': tflag = 1; argc--; argv++; goto loop; } } if(fopen(info,buf)== -1) { printf("No info\n"); exit(); } talloc(); if(argc<=2) instruct(info); signal(2,done); argv[argc] = 0; if(find(&argv[1],argc-1)==0) dunno(); close(buf[0]); if(fopen(tmp[0],buf)== -1) dunno(); readindex(); if(!tflag || na>nl) na = nl; for(;;) { i = next(); seek(buf[0],xx[i],0); read(buf[0],line,xx[i+1]-xx[i]); s printf("\nRights %d, wrongs %d, ", rights, wrongs); if(guesses) printf("extra guesses %d, ", guesses); printf("score %d%%\n",100*rights/(rights+wrongs)); exit(); } instruct(info) { char *t; int i, n; printf("Subjects:\n\n"); while(readline()) { printf("-"); n = segment(line,tmp); for(i=1;i name+1 && *--cp1 == 's') { *cp1 = 0; goto loop; } printf("cannot recognize %s\n", name); return(1); } equal(s1, s2) char *s1, *s2; { register char *c1, *c2; c1 = s1; c2 = s2; while(*c1++ == *c2) if(*c2++ =e = np; f = 0; i++; if(lp->factor != 1.0) goto l0; for(c=0; cdim[c]; if(t>1 || (f>0 && t!=0)) goto l0; if(f==0 && t==1) { if(unames[c]) goto l0; f = c+1; } } if(f>0) unames[f-1] = np; goto l0; redef: printf("redefination %s\n", np); goto l0; } double getflt() { register c, i, dp; double d, e; int f; d = 0.; dp = 0; do c = get(); while(c == ' ' || c == '\t'); l1: if(c >= '0' && c <= '9') { d = d*10. + c-'0'; if(dp) dp++; c = get()(s) { for(;;ev++){ switch(*ev) { case '|': s = 0; ev; continue; case ']': case '}': case 0: return; case '[': case '{': ev++; pub1(s); ev; continue; case '\\': if(*++ev=='\n') continue; default: if(s) putchar(*ev); } } } segment(u,w) char *u, *w[]; { char *s; int i; char *t; s = u; for(i=0;ifactor); f = 0; for(i=0; idim[i], i, f); if(f&1) { putchar('/'); f = 0; for(i=0; idim[i], i, f); } putchar('\n'); } pu(u, i, f) { if(u > 0) { if(f&2) putchar('-'); if(unames[i]) printf("%s", unames[i]); else printf("*%c*", i+'a'); if(u > 1) putchar(u+'0'); return(2); } if(u < 0) return(1); return(0); } convr(up) struct unit *up; { register s= 0) return(1); return(0); } init() { register char *cp; register struct table *tp, *lp; int c, i, f, t; char *np; cp = names; for(i=0; iname = np; lp->factor = 1.0; lp->dim[i] = 1; } lp = hash(""); lp->name = cp-1; lp->factor = 1.0; l0: c = get(); if(c == 0) { printf("%l units; %l bytes\n\n", i, cp-names); if(dumpflg) for(tp = &table[0]; tp < &table[NTAB]; tp++) { if(t; goto l1; } if(c == '.') { dp++; c = get(); goto l1; } if(dp) dp--; if(c == '+' || c == '-') { f = 0; if(c == '-') f++; i = 0; c = get(); while(c >= '0' && c <= '9') { i = i*10 + c-'0'; c = get(); } if(f) i = -i; dp =- i; } e = 1.; i = dp; if(i < 0) i = -i; while(i--) e =* 10.; if(dp < 0) d =* e; else d =/ e; if(c == '|') return(d/getflt()); peekc = c; return(d); } get() { register c; if(c=peekc) { peekc = 0; return(c); } c = getc(ibuf= *s++; } *t++ = *s++; } while(*s!=':'&&*s!='\n') s++; *t = 0; if(*s++=='\n') { return(i+1); } } printf("Too many facts about one thing\n"); } perm(u,m,v,n,p) int p[]; char *u[], *v[]; { int i, j; int x; for(i=0;i1) badinfo(); if(x==0) continue; p[i] = j; goto uloop; } return(0); uloop: ; } return(1); } find(u,m) char *u[]; { int n; while(readline()){ n = segment(line,tmp); if(perm(u,m,tmp+1egment(line,tmp); if(*tmp[select[0]] == '\0' || *tmp[select[1]] == '\0') { score[i] = 1; continue; } publish(tmp[select[0]]); printf("\n"); for(count=0;;count++) { if(query(response)==0) { publish(tmp[select[1]]); printf("\n"); if(count==0) wrongs++; score[i] = tflag?-1:1; break; } x = cmp(response,tmp[select[1]]); if(x>1) badinfo(); if(x==1) { printf("Right!\n"); if(count==0) rights++; if(++score[i]>=1 && nadim[c] = 0; p->factor = getflt(); if(p->factor == 0.) p->factor = 1.0; err = 0; den = 0; cp = name; loop: switch(c=get()) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': case '/': case ' ': case '\t': case '\n': if(cp != name) { *cp++ = 0; cp = name; err =| lookup(cp, p, den, c); } if(c == '/') den); if(c <= 0) { if(ibuf[0]) return(0); printf("\n"); exit(); } return(c); } hash(name) char *name; { register struct table *tp; register char *np; register h; h = 0; np = name; while(*np) h = h*57 + *np++ - '0'; h = lrem(0, h, NTAB); tp = &table[h]; l0: if(tp->name == 0) return(tp); if(equal(name, tp->name)) return(tp); tp++; if(tp >= &table[NTAB]) tp = table; goto l0; } fperr() { /***/ csignal(8, fperr); fperrc++; } ,n-1,select)) return(1); } return(0); } readindex() { xx[0] = nc = 0; while(readline()) { xx[++nl] = nc; if(nl>=NL) { printf("I've forgotten some of it\n"); break; } } } talloc() { int i; for(i=0;i1&&*argv[1]=='-') { switch(argv[1][1]) { case 'i': iintf("What?\n"); if(count==0) wrongs++; score[i] = tflag?-1:1; } guesses =+ count; } } query(r) char *r; { char *t; for(t=r;;t++) { if(read(0,t,1)==0) done(); if(*t==' '&&(t==r||t[-1]==' ')) t--; if(*t=='\n') { while(t>r&&t[-1]==' ') *--t = '\n'; break; } } *t = 0; return(t-r); } next() { int flag; inc = inc*3125&077777; ptr = (inc>>2)%na; flag = 0; while(score[ptr]>0) if(++ptr>=na) { ptr = 0; if(flag) done(); flag = 1; } return(ptr); } done() { mega", 1e6, "meg", 1e9, "giga", 1e12, "tera", 0.0, 0 }; int ibuf[259]; int fperrc; int peekc; int dumpflg; main(argc, argv) char *argv[]; { register i; register char *file; struct unit u1, u2; double f; if(argc>1 && *argv[1]=='-') { argc--; argv++; dumpflg++; } file = dfile; if(argc > 1) file = argv[1]; if(fopen(file, ibuf) < 0) { printf("no table\n"); exit(); } /*** ldfps(07600); /* interrupt on fp errors */ /***/ csignal(8, fperr); init(); close(ibuf[0]); ibuf[0] = 0; loop:++; if(c == '\n') return(err); goto loop; } *cp++ = c; goto loop; } lookup(name, up, den, c) char *name; struct unit *up; { register struct unit *p; register struct table *q; register i; char *cp1, *cp2; double e; p = up; e = 1.0; loop: q = hash(name); if(q->name) { l1: if(den) { p->factor =/ q->factor*e; for(i=0; idim[i] =- q->dim[i]; } else { p->factor =* q->factor*e; for(i=0; idim[i] =+ q->dim[i]; } if(c >= '2' && c <= '9')p->name == 0) continue; printf("%s", tp->name); units(tp); } return; } if(c == '/') while(c != '\n') c = get(); if(c == '\n') goto l0; np = cp; while(c != ' ' && c != '\t') { *cp++ = c; c = get(); if(c == '\n') { *cp++ = 0; tp = hash(np); if(tp->name) goto redef; tp->name = np; tp->factor = lp->factor; for(c=0; cdim[c] = lp->dim[c]; i++; goto l0; } } *cp++ = 0; lp = hash(np); if(lp->name) goto redef; convr(lp); lp->namcc -o ar -s ar.c cc -o arcv -s arcv.c cc -o cal -s cal.c cc -o cat -s cat.c cc -o chmod -s chmod.c cc -o cmp -s cmp.c cc -o col -s col.c cc -o comm -s comm.c cc -o cp -s cp.c cc -o cpall -s cpall.c cc -o crypt -s crypt.c cc -o date -s date.c cc -o dd -s dd.c cc -o df -s df.c cc -o diff -s diff.c cc -o dsw -s dsw.c cc -o du -s du.c cc -o echo -s echo.c cc -o ed -s -n ed.c cc -o exit -s exit.c cc -o file -s file.c cc -o find -s find.c cc -o goto -s goto.c cc -o grep -s grep.c cc -o if -s if.c cc -o kill -s kill.c cc -o ld -s -n ld.c cc -o ln -s ln.c cc -o login -s login.c; chmod 4711 login cc -o ls -s ls.c cc -o mail -s mail.c; /etc/chown mail mail; chmod 4711 mail cc -o mesg -s mesg.c cc -o mkdir -s mkdir.c; chmod 4711 mkdir cc -o mv -s mv.c; chmod 4711 mv cc -o newgrp -s newgrp.c; chmod 4711 newgrp cc -o nice -s nice.c cc -o nm -s nm.c cc -o nohup -s nohup.c cc -o od -s od.c cc -o passwd -s passwd.c; chmod 4711 passwd cc -o pr -s pr.c cc -o prof -s prof.c cc -o ps -s ps.c cc -o ptx -s ptx.c cc -o pwd -s pwd.cC subroutine library - SVC interface routines src.a - source for /lib/liba.a routines rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end close.s[ close title unix c svc library -- close entry close r0 equ 0 rf equ 15 sp equ 7 * pure close equ * l r0,0(sp) file descriptor svc 14,6 bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end icreat.s\ hcreat title unix c svc library -- creat entry creat r0 equ 0 rf equ 15 sp equ 7 * impur creatsvcf equ 15 sp equ 7 * pure exit equ * l r0,0(sp) status svc 14,1 dc 0 it had better work! end efork.s\?fork title unix c svc library -- fork entry fork r0 equ 0 rf equ 15 sp equ 7 * pure fork equ * svc 14,2 b child child process return bc error br rf parent process return error equ * st r0,errno lcs r0,1 error return br rf * child equ * lis r0,0 child process returns 0 br rf errno comn das 1 ends end fstat.s\rfstat title unix c svc library -- fs file descriptor svc 14,0 dc a(gttysvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end kill.s]Ekill title unix c svc library -- kill entry kill r0 equ 0 rf equ 15 sp equ 7 * impur killsvc equ * svc 14,37 sig dc a(*-*) * pure kill equ * l r0,adc(sp) sig st r0,sig l r0,0(sp) process id svc 14,0 dc a(killsvc) bc error br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ror equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end open.s]Wbopen title unix c svc library -- open entry open r0 equ 0 rf equ 15 sp equ 7 * impur opensvc equ * svc 14,5 fname dc a(*-*) mode dc a(*-*) * pure open equ * l r0,0(sp) filename st r0,fname l r0,adc(sp) mode st r0,mode svc 14,0 dc a(opensvc) bc error br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end pipe.s]Upipe title unix c cc -o quiz -s quiz.c cc -o rm -s rm.c cc -o rmdir -s rmdir.c; chmod 4711 rmdir cc -o sh -s -n sh.c cc -o size -s size.c cc -o sleep -s sleep.c cc -o sort -s sort.c cc -o split -s split.c cc -o strip -s strip.c cc -o stty -s stty.c cc -o su -s su.c; chmod 4711 su cc -o sync -s sync.c cc -o tee -s tee.c cc -o time -s time.c cc -o tr -s tr.c cc -o tty -s tty.c cc -o units -s units.c cc -o uniq -s uniq.c cc -o usort -s usort.c cc -o wc -s wc.c cc -o who -s who.c cc -o write -s write.c ebrk.s[brk title unix c svc library -- sbrk, brk entry sbrk,brk extrn end r0 equ 0 r1 equ 1 sp equ 7 rf equ 15 impur svcbrk svc 14,17 top dc a(end) pure brk equ * l r0,top previous top l r1,0(sp) new top b dosvc * sbrk equ * l r0,top previous top lr r1,r0 a r1,0(sp) add increment dosvc equ * st r1,top new top svc 14,0 dc a(svcbrk) * set new break * bncr rf ok - return st r0,errno error lcs r0,1 br rf errno comn das 1 ends end chdir.s[9Hchdi equ * svc 14,8 fname dc a(*-*) mode dc a(*-*) * pure creat equ * l r0,0(sp) filename st r0,fname l r0,adc(sp) mode st r0,mode svc 14,0 dc a(creatsvc) bc error br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end csw.s,tcsw title unix c svc library -- csw entry csw r0 equ 0 rf equ 15 sp equ 7 * pure csw equ * svc 14,38 br rf end dup.s\>dup title unix c svc library -- dup entry dup r0 equ 0 rf equ 15 sp equ 7 *    $*%+ & ends end nlink.s]{link title unix c svc library -- link entry link r0 equ 0 rf equ 15 sp equ 7 * impur linksvc equ * svc 14,9 name1 dc a(*-*) name2 dc a(*-*) * pure link equ * l r0,0(sp) name1 st r0,name1 l r0,adc(sp) name2 st r0,name2 svc 14,0 dc a(linksvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end rmknod.s]0mknod title unix c svc library -- mknod entry mknod r0 equ 0 rfsvc library -- pipe entry pipe r0 equ 0 r1 equ 1 r2 equ 2 rf equ 15 sp equ 7 * pure pipe equ * svc 14,42 bc error l r2,0(sp) return area st r0,0(r2) read file descriptor st r1,adc(r2) write file descriptor lis r0,0 return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end 1profil.s]profil title unix c svc library -- profil entry profil r0 equ 0 rf equ 15 sp equ 7 * impur profsvc equ * svc 14,44 buff dc a(*-*) bufsiz dc a(*-*) offset dc ar x src.a cc -c *.s r title unix c svc library -- chdir entry chdir r0 equ 0 rf equ 15 sp equ 7 * impur chdirsvc equ * svc 14,12 dirname dc a(*-*) * pure chdir equ * l r0,0(sp) dirname st r0,dirname svc 14,0 dc a(chdirsvc) bc error lis r0,0 br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end chmod.s[Zmchmod title unix c svc library -- chmod entry chmod r0 equ 0 rf equ 15 sp equ 7 * impur chmodsvc equ * svc 14,15 name dc a(*-*) mode dc a(*-*) * pure chmod pure dup equ * l r0,0(sp) file descriptor svc 14,41 bc error br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end execl.s\^oexecl title unix c svc library -- execl entry execl r0 equ 0 rf equ 15 sp equ 7 * impur execsvc equ * svc 14,11 name dc a(*-*) args dc a(*-*) * pure execl equ * l r0,0(sp) name st r0,name la r0,adc(sp) args are in stack st r0,args svc 14,0 dc a(execsvc) bc error br rf error equ * st r0,errno lcs r0,1 error rettat entry fstat r0 equ 0 rf equ 15 sp equ 7 * impur fstatsvc equ * svc 14,28 buffer dc a(*-*) * pure fstat equ * l r0,adc(sp) buffer st r0,buffer l r0,0(sp) file descriptor svc 14,0 dc a(fstatsvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end getgid.s,getgid title unix c svc library -- getgid entry getgid r0 equ 0 rf equ 15 sp equ 7 * pure getgid equ * svc 14,47 br rf end getpid.s, equ 15 sp equ 7 * impur mknodsvc equ * svc 14,14 name dc a(*-*) mode dc a(*-*) addr dc a(*-*) * pure mknod equ * l r0,0(sp) name st r0,name l r0,adc(sp) mode st r0,mode l r0,2*adc(sp) addr st r0,addr svc 14,0 dc a(mknodsvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end mount.s]<mount title unix c svc library -- mount entry mount r0 equ 0 rf equ 15 sp equ 7 * impur mountsvc equ * svc 14,21 speca(*-*) scale dc a(*-*) * pure profil equ * l r0,0(sp) buff st r0,buff l r0,adc(sp) bufsiz st r0,bufsiz l r0,2*adc(sp) offset st r0,offset l r0,3*adc(sp) scale st r0,scale svc 14,0 dc a(profsvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end ptrace.s]ptrace title unix c svc library -- ptrace entry ptrace r0 equ 0 rf equ 15 sp equ 7 * impur ptrcsvc equ * svc 14,26 pid dc a(*-*) addr dc a(*-*) reqstripsym *.o ar ru /lib/liba.a rm *.o rm *.s equ * l r0,0(sp) name st r0,name l r0,adc(sp) mode st r0,mode svc 14,0 dc a(chmodsvc) bc error lis r0,0 br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end chown.s[npchown title unix c svc library -- chown entry chown r0 equ 0 rf equ 15 sp equ 7 * impur chownsvc equ * svc 14,16 name dc a(*-*) owner dc a(*-*) * pure chown equ * l r0,0(sp) name st r0,name l r0,adc(sp) owner st r0,owner svc 14,0 dc a(chownsvc) bc error lis r0,0 brurn br rf errno comn das 1 ends end execv.s\saexecv title unix c svc library -- execv entry execv r0 equ 0 rf equ 15 sp equ 7 * impur execsvc equ * svc 14,11 name dc a(*-*) args dc a(*-*) * pure execv equ * l r0,0(sp) name st r0,name l r0,adc(sp) args st r0,args svc 14,0 dc a(execsvc) bc error br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end exit.s\exit title unix c svc library -- exit entry exit r0 equ 0 rgetpid title unix c svc library -- getpid entry getpid r0 equ 0 rf equ 15 sp equ 7 * pure getpid equ * svc 14,20 br rf end getuid.s,getuid title unix c svc library -- getuid entry getuid r0 equ 0 rf equ 15 sp equ 7 * pure getuid equ * svc 14,24 br rf end gtty.s]lgtty title unix c svc library -- gtty entry gtty r0 equ 0 rf equ 15 sp equ 7 * impur gttysvc equ * svc 14,32 buffer dc a(*-*) * pure gtty equ * l r0,adc(sp) buffer st r0,buffer l r0,0(sp)f dc a(*-*) name dc a(*-*) rwflag dc a(*-*) * pure mount equ * l r0,0(sp) specf st r0,specf l r0,adc(sp) name st r0,name l r0,2*adc(sp) rwflag st r0,rwflag svc 14,0 dc a(mountsvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end nice.s]Hnice title unix c svc library -- nice entry nice r0 equ 0 rf equ 15 sp equ 7 * pure nice equ * l r0,0(sp) priority svc 14,34 bc error lis r0,0 return br rf eruest dc a(*-*) * pure ptrace equ * l r0,adc(sp) pid st r0,pid l r0,2*adc(sp) addr st r0,addr l r0,0(sp) request st r0,request l r0,3*adc(sp) data svc 14,0 dc a(ptrcsvc) bncr rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end read.s]read title unix c svc library -- read entry read r0 equ 0 rf equ 15 sp equ 7 * impur readsvc equ * svc 14,3 buffer dc a(*-*) nbytes dc a(*-*) * pure read equ * l r0,adc(sp) buffer st r0,buffer l r0,2*adc(sp) nbytes st r0,nbytes l r0,0(sp) file descriptor svc 14,0 dc a(readsvc) bc error br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end seek.s]seek title unix c svc library -- seek entry seek r0 equ 0 rf equ 15 sp equ 7 * impur seeksvc equ * svc 14,19 offset dc a(*-*) ptrnam dc a(*-*) * pure seek equ * l r0,adc(sp) offset st r0,offset l r0,2*adc(sp) ptrnam st r0,ptrnam l r0,0(sp) file descriptor svc 14,0 dc a(seeksvc) bc error l) time[0] l r1,adc(r2) time[1] svc 14,0 dc a(svcmdat) bc error lis r0,0 return ok br rf error equ * st r0,errno return error lcs r0,1 br rf errno comn das 1 ends end stat.s^Jsstat title unix c svc library -- stat entry stat r0 equ 0 rf equ 15 sp equ 7 * impur statsvc equ * svc 14,18 name dc a(*-*) buf dc a(*-*) * pure stat equ * l r0,0(sp) name st r0,name l r0,adc(sp) buf st r0,buf svc 14,0 dc a(statsvc) bc error lis r0,0 normal return br rf error equ * st r0,umount title unix c svc library -- umount entry umount r0 equ 0 rf equ 15 sp equ 7 * impur umntsvc equ * svc 14,22 specl dc a(*-*) * pure umount equ * l r0,0(sp) specl st r0,specl svc 14,0 dc a(umntsvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end runlink.s^Sunlink title unix c svc library -- unlink entry unlink r0 equ 0 rf equ 15 sp equ 7 * impur unlksvc equ * svc 14,10 fname dc a(*-*) * pure #define NMOUNT 16 #define NAMSIZ 32 struct mtab { char file[NAMSIZ]; char spec[NAMSIZ]; } mtab[NMOUNT]; main(argc, argv) char **argv; { register int ro; register struct mtab *mp; register char *np; int n, mf; mf = open("/etc/mtab", 0); read(mf, mtab, NMOUNT*2*NAMSIZ); if (argc==1) { for (mp = mtab; mp < &mtab[NMOUNT]; mp++) if (mp->file[0]) printf("%s on %s\n", mp->spec, mp->file); return; } if(argc < 3) { printf("arg count\n"); return; } ro = 0; if(argc > 3) ro++; if(moun == '/') p1++; argv[1] = p1; for (mp = mtab; mp < &mtab[NMOUNT]; mp++) { p1 = argv[1]; p2 = &mp->spec[0]; while (*p1++ == *p2) if (*p2++ == 0) { for (p1 = mp->file; p1 < &mp->file[NAMSIZ*2];) *p1++ = 0; mp = &mtab[NMOUNT]; while ((--mp)->file[0] == 0); mf = creat("/etc/mtab", 0644); write(mf, mtab, (mp-mtab+1)*2*NAMSIZ); return; } } printf("%s not in mount table\n", argv[1]); } inode, sizeof inode); for (j=0; ji_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR) return; lookup(ino, 1); } pass2(ip) struct inode *ip; { register doff; register struct htab *hp; register struct dir *dp; int i; register inum; /***/ if ((ip->i_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR) return; doff = 0; while (dp = dread(ip, doff)) { doff =+ 16; if ((inum = (is r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end ssetgid.s]setgid title unix c svc library -- setgid entry setgid r0 equ 0 rf equ 15 sp equ 7 * pure setgid equ * l r0,0(sp) id svc 14,46 bncr rf * error st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end setuid.s^ setuid title unix c svc library -- setuid entry setuid r0 equ 0 rf equ 15 sp equ 7 * pure setuid equ * l r0,0(sp)errno lcs r0,1 error return br rf errno comn das 1 ends end nstime.s^ZZstime title unix c svc library -- stime entry stime r1 equ 1 r2 equ 2 r0 equ 0 rf equ 15 sp equ 7 * pure stime equ * l r2,0(sp) ptr to time buffer l r0,0(r2) high order time l r1,adc(r2) low order time svc 14,25 bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end stty.s^elstty title unix c svc library -- stty entunlink equ * l r0,0(sp) fname st r0,fname svc 14,0 dc a(unlksvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end owait.s^wait title unix c svc library -- wait entry wait r0 equ 0 r1 equ 1 r2 equ 2 rf equ 15 sp equ 7 * pure wait equ * svc 14,7 bc error l r2,0(sp) return area for status st r1,0(r2) br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end write.st(argv[1], argv[2], ro) < 0) { perror("mount"); return; } np = argv[1]; while(*np++) ; np--; while(*--np == '/') *np = '\0'; while(np > argv[1] && *--np != '/') ; if(*np == '/') np++; argv[1] = np; for (mp = mtab; mp < &mtab[NMOUNT]; mp++) { if (mp->file[0] == 0) { for (np = mp->spec; np < &mp->spec[NAMSIZ-1];) if ((*np++ = *argv[1]++) == 0) argv[1]--; for (np = mp->file; np < &mp->file[NAMSIZ-1];) if ((*np++ = *argv[2]++) == 0) argv[2]--; mp = &mtab[NMOUNT]# char *dargv[] { "/dev/rdf0", "/dev/rdr0", "/dev/rdf1", "/dev/rdr1", 0 }; #define NINODE 16*8 /***/ #include "/usr/sys/ino.h" #include "/usr/sys/filsys.h" struct filsys sblock; struct inode inode[NINODE]; int sflg; int aflg; #define NI 20 #define NDIRS 787 int ilist[NI] { -1}; int fi; struct htab { int hino; int hpino; char hname[14]; } htab[NDIRS]; int nhent 10; int pass1(), pass2(), pass3(); /***/ int (*pass[])() { pass1, pass2, pass3 }; char *lasts; int ino; int nerror; int nffil; extern idp->ino[0]<<8) | dp->ino[1])==0) continue; if ((hp = lookup(inum, 0)) == 0) continue; if (dotname(dp)) continue; hp->hpino = ino; for (i=0; i<14; i++) hp->hname[i] = dp->name[i]; } } pass3(ip) struct inode *ip; { register doff; register struct dir *dp; register int *ilp; register inum; /***/ if ((ip->i_mode&IALLOC)==0 || (ip->i_mode&IFMT)!=IFDIR) return; doff = 0; while (dp = dread(ip, doff)) { doff =+ 16; if ((inum = (dp->ino[0]<<8) | dp->ino[1])==0) continue; if id svc 14,23 bncr rf st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end dsignal.s^"Lsignal title unix c svc library -- signal entry signal r0 equ 0 rf equ 15 sp equ 7 * impur sigsvc equ * svc 14,48 sig dc a(*-*) func dc a(*-*) * pure signal equ * l r0,0(sp) sig st r0,sig l r0,adc(sp) func st r0,func svc 14,0 dc a(sigsvc) bncr rf st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end sleep.s^5sleep title unix c svc lry stty r0 equ 0 rf equ 15 sp equ 7 * impur sttysvc equ * svc 14,31 buffer dc a(*-*) * pure stty equ * l r0,adc(sp) buffer st r0,buffer l r0,0(sp) file descriptor svc 14,0 dc a(sttysvc) bc error lis r0,0 normal return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end sync.s^wsync title unix c svc library -- sync entry sync r0 equ 0 r1 equ 1 r2 equ 2 rf equ 15 sp equ 7 * pure sync equ * svc 14,36 br rf end time.s^^write title unix c svc library -- write entry write r0 equ 0 rf equ 15 sp equ 7 * impur writesvc equ * svc 14,4 buffer dc a(*-*) nbytes dc a(*-*) * pure write equ * l r0,adc(sp) buffer st r0,buffer l r0,2*adc(sp) nbytes st r0,nbytes l r0,0(sp) file descriptor svc 14,0 dc a(writesvc) bc error br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end ; while ((--mp)->file[0] == 0); mf = creat("/etc/mtab", 0644); write(mf, mtab, (mp-mtab+1)*2*NAMSIZ); return; } } } nt fout; int nfiles; struct dir { char ino[2]; /***/ char name[14]; }; main(argc, argv) char **argv; { register char **p; register int n, *lp; nffil = dup(1); if (argc == 1) { for (p = dargv; *p;) check(*p++); return(nerror); } while (--argc) { argv++; if (**argv=='-') switch ((*argv)[1]) { case 's': sflg++; continue; case 'a': aflg++; continue; case 'i': lp = ilist; while (lp < &ilist[NI-1] && (n = number(argv[1]))) { *lp++ = n; argv++; argc--; (aflg==0 && dotname(dp)) continue; for (ilp=ilist; *ilp >= 0; ilp++) if (*ilp == inum) break; if (ilp > ilist && *ilp!=inum) continue; printf("%d ", inum); pname(ino, 0); printf("/%.14s\n", dp->name); } } dotname(adp) { register struct dir *dp; dp = adp; if (dp->name[0]=='.') if (dp->name[1]==0 || dp->name[1]=='.' && dp->name[2]==0) return(1); return(0); } pname(i, lev) { register struct htab *hp; if (i==1) return; if ((hp = lookup(i, 0)) == 0) { printf("???"); ibrary -- sleep entry sleep r0 equ 0 rf equ 15 sp equ 7 * pure sleep equ * l r0,0(sp) seconds svc 14,35 bc error lis r0,0 return br rf error equ * st r0,errno lcs r0,1 error return br rf errno comn das 1 ends end rsmdate.s^?smdate title unix c svc library -- smdate entry smdate r0 equ 0 r1 equ 1 r2 equ 2 sp equ 7 rf equ 15 impur svcmdat equ * svc 14,30 * smdate * svc.fn dc a(*-*) filename pure smdate equ * l r0,0(sp) filename st r0,svc.fn l r2,adc(sp) time l r0,0(r2time title unix c svc library -- time entry time r0 equ 0 r1 equ 1 r2 equ 2 rf equ 15 sp equ 7 * pure time equ * svc 14,13 l r2,0(sp) ptr to time doubleword st r0,0(r2) high order time st r1,adc(r2) low order time br rf end times.s^times title unix c svc library -- times entry times r0 equ 0 rf equ 15 sp equ 7 * impur timessvc equ * svc 14,43 buffer dc a(*-*) * pure times equ * l r0,0(sp) buffer st r0,buffer svc 14,0 dc a(timessvc) br rf end umount.s^Qmain() { if (fork()) exit(); for(;;) { sleep(30); sync(); } } #define NMOUNT 16 #define NAMSIZ 32 struct mtab { char file[NAMSIZ]; char spec[NAMSIZ]; } mtab[NMOUNT]; main(argc, argv) char **argv; { register struct mtab *mp; register char *p1, *p2; int mf; sync(); mf = open("/etc/mtab", 0); read(mf, mtab, NMOUNT*2*NAMSIZ); if(argc != 2) { printf("arg count\n"); return; } if (umount(argv[1]) < 0) { perror("umount"); return; } p1 = argv[1]; while(*p1++) ; p1--; while(*--p1 == '/') *p1 = '\0'; while(p1 > argv[1] && *--p1 != '/') ; if(*p1 } *lp++ = -1; continue; default: printf2("Bad flag\n"); } check(*argv); } return(nerror); } check(file) char *file; { register i, j, pno; fi = open(file, 0); if (fi < 0) { printf2("cannot open %s\n", file); return; } printf2("%s:\n", file); sync(); bread(1, &sblock, 512); nfiles = sblock.s_isize*8; /***/ for (i=0; i 10) { printf("..."); return; } pname(hp->hpino, ++lev); printf("/%.14s", hp->hname); } lookup(i, ef) { register struct htab *hp; for (hp = &htab[i%NDIRS]; hp->hino;) { if (hp->hino==i) return(hp); if (++hp >= &htab[NDIRS]) hp = htab; } if (ef==0) return(0); if (++nhent >= NDIRS) { printf2("Out of core-- increase NDIRS\n"); flush(); exit(1); } hp->hino = i; return(hp); } dread(aip, aoff) { register b, off; register struct inode *ip; static ibuf[256]; static char buf[512]; off = aoff; ip = aip; if ((off&0777)==0) { if (off==0177000) { printf2("Monstrous directory %l\n", ino); return(0); } if ((ip->i_mode&ILARG)==0) { if (off>=010000 || (b = ip->i_addr[off>>9])==0) return(0); bread(b, buf, 512); } else { if (off==0) { if (ip->i_addr[0]==0) return(0); bread(ip->i_addr[0], ibuf, 512); } if ((b = ibuf[(off>>9)&0177])==0) return(0); bread(b, buf, 512); } } return(&buf[off&0777]); } bread(bno, bmain(argc, argv) int argc; char **argv; { int m, a, b; if(argc != 5) { printf("arg count\n"); goto usage; } if(*argv[2] == 'b') m = 0160666; else if(*argv[2] == 'c') m = 0120666; else goto usage; a = number(argv[3]); if(a < 0) goto usage; b = number(argv[4]); if(b < 0) goto usage; if(mknod(argv[1], m, (a<<8)|b) < 0) perror("mknod"); exit(); usage: printf("usage: mknod name b/c major minor\n"); } number(s) char *s; { int n, c; n = 0; while(c = *s++) { if(c<'0' || c>'9') return(cp); case LIST: while(*cp != LIST) if(*cp++ == v) { while(*cp++ != LIST) ; return(cp); } flag++; return(cp+1); case RANGE: if(*cp > v || cp[1] < v) flag++; return(cp+2); } if(cp[-1] != v) flag++; return(cp); } slp() { register i; int t[2]; time(t); i = itime[1] - t[1]; if(i > 0) sleep(i); } ex(s) char *s; { register i; int stat; /***/ if(fork()) { wait(&stat); /***/ return; } for(i=0; s[i]; i++); close(0); creat(crontmp, 0600); write(0 goto loop; ignore: cp = ocp; while(c != '\n') { if(c <= 0) { close(ib[0]); *cp++ = EOF; *cp++ = EOF; aend = cp; brk(aend); return; } c = getc(ib); } goto loop; } s.s_isize); if(fn != 1) printf("free list %d/%d\n", fm, fn); charp = "d--777 0 0 $ "; goto f3; } /* * get name of boot load program * and read onto block 0 */ getstr(); f = open(string, 0); if(f < 0) { printf("%s: cannot open init\n", string); goto f2; } read(f, buf, 020); if(buf[0] != 0407) { printf("%s: bad format\n", string); goto f1; } n = buf[1]+buf[2]; if(n > 512) { printf("%s: too big\n", string); goto f1; } read(f, buf, n); wtfs(0, buf); f1: close(f); n.i_nlink--; } dbc = 0; ibc = 0; switch(in.i_mode&IFMT) { case 0: /* * regular file * contents is a file name */ getstr(); f = open(string, 0); if(f < 0) { printf("%s: cannot open\n", string); break; } while((i=read(f, db, 512)) > 0) { in.i_size1 =+ i; newblk(&dbc, db, &ibc, ib); } close(f); break; case IFBLK: case IFCHR: /* * special file * content is maj/min types */ in.i_addr[0] = getnum()<<8; in.i_addr[0] =| getnum(); break; case IFDIR"(.#)/0< return(-1); n = n*10 + c-'0'; } return(n); } , s, i); close(0); open(crontmp, 0); unlink(crontmp); if(fork()) exit(); execl("/bin/sh", "sh", "-t", 0); exit(); } init() { int ib[131], t[10]; /***/ register i, c; register char *cp; char *ocp; int n; extern char end[]; if(fopen(crontab, ib) < 0) { write(1, "cannot open table\n", 18); exit(); } cp = end; if(aend == 0) aend = cp; loop: ocp = cp; if(cp+100 > aend) { aend =+ 512; brk(aend); } for(i=0;; i++) { do c = getc(ib); while(c == ' ' || c == '\t'); if(c <= 0# struct { char *s_isize; char *s_fsize; int s_nfree; int s_free[50]; /***/ int s_ninode; int s_inode[50]; /***/ char s_flock; char s_ilock; char s_fmod; int s_time[2]; } filsys; struct inode { int i_number; int i_mode; char i_nlink; char i_uid; char i_gid; char i_size0; char *i_size1; int i_addr[8]; int i_time[4]; }; /* modes */ #define IALLOC 0100000 #define IFMT 060000 #define IFDIR 040000 #define IFCHR 020000 #define IFBLK 060000 #define ILARG 010000 #define ISUID 04000 #define I/* * get total disk size * and inode block size */ f2: filsys.s_fsize = getnum(); filsys.s_isize = getnum(); f3: if(filsys.s_isize > filsys.s_fsize || filsys.s_fsize-filsys.s_isize-2 < filsys.s_isize) { printf("%l/%l: bad ratio\n", filsys.s_fsize, filsys.s_isize); exit(); } bflist(); /* * initialize files */ for(n=0; n<128; n++) /***/ buf[n] = 0; for(n=0; n!=filsys.s_isize; n++) wtfs(n+2, buf); cfile(0); /* * write out super block */ for(n=0; n<128; n++) /***/ 9?E4:@F5AGHNTZIOuf, cnt) { seek(fi, bno, 3); if (read(fi, buf, cnt) != cnt) { printf2("read error %d\n", bno); exit(); } } bwrite(bno, buf) { seek(fi, bno, 3); if (write(fi, buf, 512) != 512) { printf2("write error %d\n", bno); exit(); } } number(as) char *as; { register n, c; register char *s; s = as; n = 0; while ((c = *s++) >= '0' && c <= '9') { n = n*10+c-'0'; } return(n); } printf2(s, a1, a2) { extern fout; flush(); fout = 2; printf(s, a1, a2); fout = nffil; flush(); } #define ANY (256-1) #define LIST (256-2) #define RANGE (256-3) #define EOF (256-4) char *crontab "/usr/lib/crontab"; char *crontmp "/tmp/crontmp"; char *aend; char *itime[2]; int *loct; int *localtime(); int reset(); int flag; main() { register i, t; register char *cp; extern char end[]; /*** setuid(1); ***/ itime[0] = fork(); if(itime[0]) exit(); setexit(); signal(1, reset); time(itime); while(*localtime(itime)) if(itime[1]-- == 0) itime[0]--; loop: init(); for(i=60; i; i--) { loct = || c == '\n') goto ignore; if(i == 5) break; if(c == '*') { *cp++ = ANY; continue; } n = 0; while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getc(ib); } if(n < 0 || n > 100) goto ignore; if(c == ',') goto list; if(c == '-') goto range; if(c != '\t' && c != ' ') goto ignore; *cp++ = n; continue; list: *cp++ = LIST; *cp++ = n; list1: n = 0; c = getc(ib); while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getc(ib); } if(n < 0 || SGID 02000 #define IREAD 0400 #define IWRITE 0200 #define IEXEC 0100 int utime[2]; extern int fin; int fsi; int fso; char *charp; int buf[128]; /***/ char string[50]; char *fsys; char *proto; int fn 24; int fm 6; main(argc, argv) char **argv; { int f, n; /* * open relevent files */ time(utime); if(argc != 3) { printf("arg count\n"); exit(); } fsys = argv[1]; for(n=0; f=fsys[n+1]; n++) if(fsys[n] == 'r') { if(f == 'k') { fn = 24; fm = 3; } if(f == 'p') { fn = 10; fm = 4;buf[n] = 0; filsys.s_time[0] = utime[0]; filsys.s_time[1] = utime[1]; wtfs(1, &filsys); } cfile(par) struct inode *par; { struct inode in; int db[128], ib[128]; /***/ int dbc, ibc; static ino; int i, f, *p1, *p2; /* * get mode, uid and gid */ getstr(); in.i_mode = IALLOC; in.i_mode =| gmode(string[0], "bcd", IFBLK, IFCHR, IFDIR); in.i_mode =| gmode(string[1], "u", ISUID); in.i_mode =| gmode(string[2], "g", ISGID); for(i=3; i<6; i++) { if(string[i]<'0' || string[i]>'7') { printf(": /* * directory * put in extra links * call recursively until * name of "$" found */ par->i_nlink++; entry(par->i_number, "..", &dbc, db, &ibc, ib); in.i_nlink++; entry(in.i_number, ".", &dbc, db, &ibc, ib); in.i_size1 = 32; for(;;) { getstr(); if(string[0]=='$' && string[1]=='\0') break; entry(ino+1, string, &dbc, db, &ibc, ib); in.i_size1 =+ 16; cfile(&in); } break; } if(dbc != 0) newblk(&dbc, db, &ibc, ib); if(ibc > 8) { in.i_mode =| ILARG; d/* * clri inumber filesystem */ int zeroes[16]; main(argc, argv) char *argv[]; { register fd, inode; if (argc != 3) { printf("Arg count\n"); exit(1); } if ((fd = open(argv[2], 2)) < 0) { printf("Can't open %s\n", argv[2]); exit(1); } if ((inode = atoi(argv[1])-1) < 0) { printf("Illegal i-number\n"); exit(1); } seek(fd, 1024+inode*64, 0); write(fd, zeroes, 64); } localtime(itime); for(cp = end; *cp != EOF;) { flag = 0; cp = cmp(cp, loct[1]); /* minute */ cp = cmp(cp, loct[2]); /* hour */ cp = cmp(cp, loct[3]); /* day */ cp = cmp(cp, loct[4]); /* month */ cp = cmp(cp, loct[6]); /* day of week */ if(flag == 0) { slp(); ex(cp); } while(*cp++ != 0) ; } t = itime[1] + 60; if(t < itime[1]) itime[0]++; itime[1] = t; } slp(); goto loop; } cmp(p, v) char *p; { register char *cp; cp = p; switch(*cp++) { case ANY: n > 100) goto ignore; *cp++ = n; if(c == ',') goto list1; if(c != '\t' && c != ' ') goto ignore; *cp++ = LIST; continue; range: *cp++ = RANGE; *cp++ = n; n = 0; c = getc(ib); while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getc(ib); } if(n < 0 || n > 100) goto ignore; if(c != '\t' && c != ' ') goto ignore; *cp++ = n; } while(c != '\n') { if(c <= 0) goto ignore; if(c == '%') c = '\n'; *cp++ = c; c = getc(ib); } *cp++ = '\n'; *cp++ = 0; } } proto = argv[2]; fso = creat(fsys, 0666); if(fso < 0) { printf("%s: cannot create\n", fsys); exit(); } fsi = open(fsys, 0); if(fsi < 0) { printf("%s: cannot open\n", fsys); exit(); } fin = open(proto, 0); if(fin < 0) { n = 0; for(f=0; proto[f]; f++) { if(proto[f]<'0' || proto[f]>'9') { printf("%s: cannot open\n", proto); exit(); } n = n*10 + proto[f]-'0'; } filsys.s_fsize = n; filsys.s_isize = ldiv(0, n, 43+ldiv(0, n, 1000)); printf("isize = %d\n", filsy%c/%s: bad digit\n", string[i], string); exit(); } in.i_mode =| (string[i]-'0')<<(15-3*i); } in.i_uid = getnum(); in.i_gid = getnum(); /* * general initialization prior to * switching on format */ ino++; in.i_number = ino; if(ldiv(0, ino, 16) > filsys.s_isize) { printf("too many inodes\n"); exit(); } in.i_nlink = 1; in.i_size0 = 0; in.i_size1 = 0; for(i=0; i<8; i++) in.i_addr[i] = 0; for(i=0; i<128; i++) { /***/ db[i] = 0; ib[i] = 0; } if(par == 0) { par = ∈ ibc = alloc(); wtfs(dbc, ib); in.i_addr[0] = dbc; } else for(i=0; i'9') { printf("%s: bad number\n", string); exit(); } n = n*10 + string[i] - '0'; } return(n); } getstr() { int i, c; loop: switch(c=getch()) { case ' ': case '\t': case '\n': goto loop; case '\0': printf("EOF\n"); exit(); case ':': while(getch() != '\n'); goto loop; } i = 0; do { string[i++] = (*charp++); return(getchar()); } bflist() { char flg[100], adr[100]; register i, j; char *low, *high; if(fn > 100) fn = 100; for(i=0; i= low+fn; i =- fn) for(j=0; j= low; i--) freennot open %s\n", file); return; } headpr = 0; printf("%s:\n",file); sync(); bread(1, &sblock, 512); nfiles = sblock.s_isize*8; /***/ if (lasts < nfiles) { if ((sbrk(nfiles - lasts + 1)) == -1) { /***/ printf("Not enough core\n"); exit(04); } lasts = nfiles; } for (i=0; i= '0' && c <= '9') { n = n*10+c-'0'; } return(n); } rgv); if (uflg) { flush(); return; } /* * cleanup pass * put junk togr */ if (vflg) strip(); if(!aflg) for (ip = tab; ip < &tab[size]; ip++) if (ip->name[0]) { for(j=0; j<8; j++) if(ip->name[j] == '?') goto yes; if(ip->count != 1) continue; yes: if(junkp == 0) junkp = enter("***other"); junkp->count =+ ip->count; junkp->realt =+ ip->realt; junkp->cput =+ ip->cput; junkp->syst =+ ip->syst; ip->name[0] = 0; } for (ip = kp = tab; ip < &tab[size]; ip++) if(ip->n printf("%9.2f", a/(n*60.)); else printf("%9.2f", a/3600.); if(cflg) { if(a == m) printf("%7s", ""); else printf("%6.2f%%", 100.*a/m); } } acct(f) char *f; { register ff; register struct tab *ip; float x; struct ftab fbuf; register char *cp; register int c; extern double ltod(); if (sflg && sname) { printf("Only 1 file with -s\n"); exit(); } if (sflg) sname = f; if ((ff=open(f, 0))<0) { printf("Can't open %s\n", f); return; } while (read(ff, &fbuf, sizeof(fbuf))==sizeofc; c = getch(); } while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0'); string[i] = '\0'; } rdfs(bno, bf) { int n; seek(fsi, bno, 3); n = read(fsi, bf, 512); if(n != 512) { printf("read error: %l\n", bno); exit(); } } wtfs(bno, bf) { int n; seek(fso, bno, 3); n = write(fso, bf, 512); if(n != 512) { printf("write error: %l\n", bno); exit(); } } alloc() { int bno, i; filsys.s_nfree--; bno = filsys.s_free[filsys.s_nfree]; filsys.s_free[filsys.s_nfree] = 0; if(bno == 0) { printf("out of f(i); } noi_mode&IALLOC) == 0) return; if((ip->i_mode&IFMT) != IFDIR) return; doff = 0; while (dp = dread(ip, doff)) { doff =+ 16; in = (dp->ino[0]<<8) | dp->ino[1]; /***/ if (in == 0) /***/ co#define size 1000 /***/ /* interpret command time accounting */ int lflg; int cflg; int jflg; int nflg; int aflg; int rflg; int tflg; int vflg; int uflg; int thres 1; int sflg; int bflg; int mflg; extern int fout; struct user { int ncomm; /*** int fill; ***/ float fctime; } user[256]; struct tab { char name[8]; int count; float realt; float cput; float syst; } *tab; struct tab *enter(); struct ftab { char fname[14]; char shf; char uid; int fdatet[2]; int frealt[2]; int fcput[2]; int fsyst[2ame[0]) { for(j=0; j<8; j++) kp->name[j] = ip->name[j]; tcopy(ip, kp); kp++; } k = kp-tab; if (sflg) { signal(2, 1); i = creat("/usr/adm/shm", 0666); write(i, user, sizeof(user)); close(i); if ((i = creat("/usr/adm/sht", 0666))<0) { printf("Can't save\n"); exit(); } write(i, tab, k*sizeof(*tab)); close(i); if (sname) { if ((i = creat(sname, 0666))<0) printf("Can't truncate\n"); close(i); } signal(2, 0); } /* * sort and print */ if (mflg) { printmoney(QW]LRX^MY_`flraree space\n"); exit(); } if(filsys.s_nfree <= 0) { rdfs(bno, buf); filsys.s_nfree = buf[0]; for(i=0; i<50; i++) /***/ filsys.s_free[i] = buf[i+1]; } return(bno); } free(bno) { int i; if(filsys.s_nfree >= 50) { /***/ buf[0] = filsys.s_nfree; for(i=0; i<50; i++) /***/ buf[i+1] = filsys.s_free[i]; wtfs(bno, buf); filsys.s_nfree = 0; } filsys.s_free[filsys.s_nfree] = bno; filsys.s_nfree++; } entry(ino, str, adbc, db, aibc, ib) char *str; int *adbc, *db, *aibc, *ib; { char *# char *dargv[] { "/dev/rdf0", /***/ "/dev/rdr0", /***/ "/dev/rdf1", /***/ "/dev/rdr1", /***/ 0 }; #define NINODE 32*8 #define NI 20 #include "/usr/sys/ino.h" #include "/usr/sys/filsys.h" struct inode inode[NINODE]; struct filsys sblock; int sflg; int headpr; int ilist[NI] { -1}; int fi; char *ecount; char *lasts; int ino; int nerror; int nfiles; struct dir { char ino[2]; /***/ char name[14]; }; main(argc, argv) char **argv; { register char **p; register int n, *lp; ecount = sbrk(ntinue; for (i=0; ilist[i] != -1; i++) if (ilist[i]==in) printf("%5l arg; %l/%.14s\n", in, ino, dp->name); ecount[in]++; } } pass2(aip) { register struct inode *ip; register i; ip = aip; i = ino; if ((ip->i_mode&IALLOC)==0 && ecount[i]==0) return; if (ip->i_nlink==ecount[i] && ip->i_nlink!=0) return; if (headpr==0) { printf("entries link cnt\n"); headpr++; } printf("%l %d %d\n", ino, ecount[i]&0377, ip->i_nlink&0377); } dread(aip, aoff) { register b, off; register stru]; }; float treal; float tcpu; float tsys; struct tab *junkp 0; char *sname; float ncom; main(argc, argv) char **argv; { register i, j, k; register struct tab *ip, *kp; extern tcmp(), ncmp(), bcmp(); extern float sum(); float ft; init(); if (argc>1) if (argv[1][0]=='-') { argv++; argc--; for(i=1; argv[0][i]; i++) switch(argv[0][i]) { case 'b': bflg++; break; case 'l': lflg++; break; case 'c': cflg++; break; case 'j': jflg++; break; case 'n': nflg+); flush(); exit(); } qsort(tab, k, sizeof *tab, nflg? &ncmp: (bflg?&bcmp:&tcmp)); printf("%8s", ""); column(ncom, treal, tcpu, tsys); for (ip=tab; ipname[0]) { ft = ip->count; printf("%-8.8s", ip->name); column(ft, ip->realt, ip->cput, ip->syst); } flush(); } printmoney() { register i; char buf[128]; register char *cp; for (i=0; i<256; i++) { if (user[i].ncomm) { if (getpw(i, buf)!=0) printf("%-8d", i); else { cp = buf; while (*cp!=':' &&*cp!='(fbuf)) { for (cp = fbuf.name; cp < &fbuf.name[8]; cp++) { c = *cp & 0377; if (c && (c < ' ' || c >= 0200)) *cp = '?'; } if (uflg) { printdate(fbuf.fdatet); printf(" %3d %.8s\n", fbuf.uid, fbuf.name); continue; } if (fbuf.shf==0) { c = fbuf.uid&0377; user[c].ncomm++; user[c].fctime =+ (ltod(fbuf.fcput)+ltod(fbuf.fsyst))/60; } ncom =+ 1.0; ip = enter(&fbuf); ip->count++; x = ltod(fbuf.frealt); x =* 60.; ip->realt =+ x; treal =+ x; x = ltod(fbuf.fcput); s; int i; db[*adbc] = ino<<16; s = &db[*adbc]; s =+ 2; /***/ for(i=0; i<14; i++) { *s++ = *str; if(*str != '\0') str++; } *adbc =+ 4; /***/ if(*adbc >= 128) /***/ newblk(adbc, db, aibc, ib); } newblk(adbc, db, aibc, ib) int *adbc, *db, *aibc, *ib; { int bno, i; bno = alloc(); wtfs(bno, db); for(i=0; i<128; i++) /***/ db[i] = 0; *adbc = 0; ib[*aibc] = bno; (*aibc)++; if(*aibc >= 128) { /***/ printf("indirect block full\n"); exit(); } } getch() { if(charp) return0); if (argc == 1) { for (p = dargv; *p;) check(*p++); return(nerror); } while (--argc) { argv++; if (**argv=='-') switch ((*argv)[1]) { case 's': sflg++; continue; case 'i': lp = ilist; while (lp < &ilist[NI-1] && (n = number(argv[1]))) { *lp++ = n; argv++; argc--; } *lp++ = -1; continue; default: printf("Bad flag\n"); } check(*argv); } return(nerror); } check(file) char *file; { register i, j; fi = open(file, 0); if(fi < 0) { printf("cact inode *ip; static ibuf[128]; /***/ static char buf[512]; off = aoff; ip = aip; if (off >= ip->i_size1) return(0); if ((off&0777)==0) { if (off==0177000) { printf("Monstrous directory %l\n", ino); return(0); } if ((ip->i_mode&ILARG)==0) { if (off>=010000 || (b = ip->i_addr[off>>9])==0) return(0); bread(b, buf, 512); } else { if (off==0) { if (ip->i_addr[0]==0) return(0); bread(ip->i_addr[0], ibuf, 512); } if ((b = ibuf[(off>>9)&0177])==0) retu+; break; case 'a': aflg++; break; case 'r': rflg++; break; case 't': tflg++; break; case 's': sflg++; aflg++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': thres = argv[0][i]-'0'; break; case 'v': vflg++; break; case 'u': uflg++; break; case 'm': mflg++; break; } } fout = dup(1); if (argc<2) acct("/usr/adm/sha"); else while (--argc) acct(*++a\n' && *cp) cp++; *cp = 0; printf("%-8s", buf); } printf("%5l %7.2f\n", user[i].ncomm, user[i].fctime/60); } } } column(n, a, b, c) double n, a, b, c; { register i; printf("%6d", i = n); if(cflg) { if(n == ncom) printf("%7s", ""); else printf("%6.2f%%", 100.*n/ncom); } col(n, a, treal); if(lflg) { col(n, b, tcpu); col(n, c, tsys); } else col(n, b+c, tcpu+tsys); if(tflg) printf("%6.1f", a/(b+c)); putchar('\n'); } col(n, a, m) double n, a, m; { if(jflg) ip->cput =+ x; tcpu =+ x; x = ltod(fbuf.fsyst); ip->syst =+ x; tsys =+ x; } close(ff); } ncmp(p1, p2) struct tab *p1, *p2; { if(p1->count == p2->count) return(tcmp(p1, p2)); if(rflg) return(p1->count - p2->count); return(p2->count - p1->count); } bcmp(p1, p2) struct tab *p1, *p2; { float f1, f2; extern float sum(); f1 = sum(p1)/p1->count; f2 = sum(p2)/p2->count; if(f1 < f2) { if(rflg) return(-1); return(1); } if(f1 > f2) { if(rflg) return(1); return(-1); } return(0); } tcmp(p1, p2) struct tab *p1, *p2; { extern float sum(); float f1, f2; f1 = sum(p1); f2 = sum(p2); if(f1 < f2) { if(rflg) return(-1); return(1); } if(f1 > f2) { if(rflg) return(1); return(-1); } return(0); } float sum(p) struct tab *p; { if(p->name[0] == 0) return(0.0); return( p->cput+ p->syst); } init() { struct tab tbuf; register i, j, f; register struct tab *ip; /*** tab must be obtained dynamically to avoid Interdata ***/ /*** assembler bug! ***/ t() -- long integer->float conversion ***/ double ltod(d) int d[2]; { float x; return(x = d[1]); } /*** temporary getpw() - get password file entry ***/ getpw() { return(-1); } .kludge); loop(); print(); } loop() { extern float flt(); register i; register struct tbuf *tp; register struct ubuf *up; if (ibuf.fill1||ibuf.fill2) return; ibuf.time = flt(&ibuf.time)/60.; if(ibuf.tty == '|') { dtime = ibuf.time; return; } if(ibuf.tty == '}') { if(dtime == 0.) return; for(tp = tbuf; tp < &tbuf[TSIZE]; tp++) tp->ttime =+ ibuf.time-dtime; dtime = 0.; return; } if (lastime>ibuf.time || lastime+(1.5*day) midnight) break; yrs++; tim =+ ye speeds */ #define B110 3 #define B150 5 #define B300 7 #define B600 8 #define B1200 9 #define B1800 10 #define B2400 11 #define B4800 12 #define B9600 13 #define SIGINT 2 #define SIGQIT 3 struct sgtty { char pad1, pad2; /***/ char sgispd, sgospd; char pad3, pad4; /***/ char sgkill, sgerase; /***/ int sgflag; } tmode; struct tab { int tname; /* this table name */ int nname; /* successor table name */ int iflags; /* initial flags */ int fflags; /* final flags */ int ispeed; /* input spee tabp->fflags; if(crmod) tmode.sgflag =| CRMOD; if(upper) tmode.sgflag =| LCASE; if(lower) tmode.sgflag =& ~LCASE; stty(0, &tmode); execl("/bin/login", "login", name, 0); exit(1); } tname = tabp->nname; } } getname() { register char *np; register c; static char cs; /***/ crmod = 0; upper = 0; lower = 0; np = name; do { if (read(0, &cs, 1) <= 0) exit(0); if ((c = cs&0177) == 0) return(0); write(1, &cs, 1); if (c>='a' && c <='z') lower++; else iab = sbrk(size * sizeof *tab); if ((f=open("/usr/adm/sht", 0))<0) goto gshm; while (read(f, &tbuf, sizeof(tbuf)) == sizeof(tbuf)) { ip = enter(&tbuf); tcopy(&tbuf, ip); ncom =+ tbuf.count; treal =+ tbuf.realt; tcpu =+ tbuf.cput; tsys =+ tbuf.syst; } close(f); gshm: if ((f=open("/usr/adm/shm", 0)) < 0) return; read(f, user, sizeof(user)); close(f); } struct ftab *enter(fbuf) struct ftab *fbuf; { register i, j; struct ftab *ip; i = 0; for (j=0; j<8; j++) { i = i*7 + fbuf->fname# /* * acct [ -w wtmp ] [ -d ] [ -p people ] */ #define TSIZE 30 #define USIZE 200 struct { char name[8]; char tty; char fill1; int kludge; float time; int fill2; } ibuf; struct ubuf { char name[8]; float utime; } ubuf[USIZE]; struct tbuf { struct ubuf *userp; float ttime; } tbuf[TSIZE]; char *wtmp; int pflag, byday; double dtime; double midnight; double lastime; double day 1440.; int pcount; char **pptr; int montab[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28, 31, 30, 31, day(); lastime = ibuf.time; if (byday && ibuf.time > midnight) { upall(1); print(); newday(); for (up=ubuf; up < &ubuf[USIZE]; up++) up->utime = 0.0; } if (ibuf.tty == '~') { ibuf.name[0] = '\0'; upall(0); return; } if ((i = ibuf.tty) >= 'a') i =- 'a' - '9'; i =- '0'; if (i<0 || i>=TSIZE) i = TSIZE-1; tp = &tbuf[i]; update(tp, 0); } print() { int i; float ttime, t; ttime = 0.0; for (i=0; i0.0) ttgmsbhntcod */ int ospeed; /* output speed */ char *message; /* login message */ } itab[] { /* Tables '0'-'6' :: local vdu 300-9600 */ '0', '1', ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+LCASE, B300, B300, "\n\rlogin: ", '1', '2', ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+LCASE, B600, B600, "\n\rlogin: ", '2', '3', ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+LCASE, B1200, B1200, "\n\rlogin: ", '3', '4', ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+LCASE, B1800, B1800, "\n\rlogin: ", '4', '5', ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+f (c>='A' && c<='Z') { upper++; c =+ 'a'-'A'; } else if (c==ERASE) { if (np > name) np--; continue; } else if (c==KILL) { np = name; continue; } *np++ = c; } while (c!='\n' && c!='\r' && np <= &name[16]); *--np = 0; if (c == '\r') { write(1, "\n", 1); crmod++; } else write(1, "\r", 1); return(1); } puts(as) char *as; { register char *s; s = as; while (*s) write(1, s++, 1); } [j]; } if(i < 0) i = -i; for (i=%size; (ip = &tab[i])->name[0]; i = (i+1)%size) { for (j=0; j<8; j++) if (ip->name[j]!=fbuf->fname[j]) goto no; goto yes; no:; } for (j=0; j<8; j++) ip->name[j] = fbuf->fname[j]; yes: return(ip); } tcopy(from, to) int *from, *to; { register i; for (i=2; i<6; i++) to[i] = from[i]; } strip() { register k, c; register struct tab *ip, *jp; jp = enter("**junk**"); for (ip = tab; ip < &tab[size]; ip++) { if (ip->name[0] && ip->count<=thres) { 30, 31, 31, 30, 31, 30, 31 }; char *monasc[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; int fin[131]; main(argc, argv) char **argv; { register c, fl; register i; register char *ip; register f; wtmp = "/usr/adm/wtmp"; while (--argc > 0 && **++argv == '-') switch(*++*argv) { case 'd': byday++; continue; case 'w': if (--argc>0) wtmp = *++argv; continue; case 'p': pflag++; continue; } pcount = argc; pptr = argv; if (fopime =+ t; if (pflag && ubuf[i].utime > 0.0) { printf("\t%-8.8s%6.2f\n", ubuf[i].name, ubuf[i].utime/60.); } } if (ttime > 0.0) { pdate(); printf("\ttotal%9.2f\n", ttime/60.); } } upall(f) { register struct tbuf *tp; for (tp=tbuf; tp < &tbuf[TSIZE]; tp++) update(tp, f); } update(tp, f) struct tbuf *tp; { int i, j; struct ubuf *up; double t, t1; if (f) t = midnight; else t = ibuf.time; if (tp->userp) { t1 = t - tp->ttime; if (t1>0.0 && t1 < 1.5*day) tp->userp->utiar; } days = (midnight-tim-720.)/day; montab[1] = 28; if(yrs%4 == 0) montab[1]++; for (mons=0; montab[mons]<=days; mons++) days =- montab[mons]; mons =% 12; printf("%s %2d", monasc[mons], days+1); } float flt(ip) int *ip; { float x; register i; if ((i = *ip) >= 0) return(x = i); return((i>>1) * 2.0); } LCASE, B2400, B2400, "\n\rlogin: ", '5', '6', ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+LCASE, B4800, B4800, "\n\rlogin: ", '6', '0', ANYP+RAW+NL1+CR1, ANYP+ECHO+XTABS+LCASE, B9600, B9600, "\n\rlogin: ", /* table '-' -- Console TTY 300 */ '-', '-', ANYP+RAW+NL1+CR1, ANYP+ECHO, B300, B300, "\014\n\rlogin: ", }; #define NITAB sizeof itab/sizeof itab[0] char name[16]; int crmod; int upper; int lower; main(argc, argv) char **argv; { register struct tab *tabp; register tname; signal(SIGINT, 1); char mesg[3000]; int msize; struct { char name[8]; char tty[2]; int time[2]; int junk; } utmp[50]; main(argc, argv) char *argv[]; { register i, *p; int f; f = open("/etc/utmp", 0); if(f < 0) { printf("utmp?\n"); exit(); } read(f, utmp, sizeof utmp); close(f); f = 0; if(argc >= 2) { f = open(argv[1], 0); if(f < 0) { printf("%s?\n", argv[1]); exit(); } } while((i = read(f, &mesg[msize], sizeof mesg - msize)) > 0) msize =+ i; close(f); for(i=0; iname); flush(); if ((c=getchar())=='y') { ip->name[0] = '\0'; jp->count =+ ip->count; jp->realt =+ ip->realt; jp->cput =+ ip->cput; jp->syst =+ ip->syst; } while (c && c!='\n') c = getchar(); } } } printdate(tvec) int tvec[2]; { register int *lt; int *localtime(); lt = localtime(tvec); printf("%3d ", lt[7]); pair(lt[2]); pair(lt[1]); pair(lt[0]); printf(" %d", lt[6]); } pair(n) { printf("%c%c", n/10+'0', n%10+'0'); } /*** temporary ltoden(wtmp, fin) < 0) { printf("No %s\n", wtmp); return; } for(;;) { ip = &ibuf; for (i=0; ittime = t; if (f) return; if (ibuf.name[0]=='\0') { tp->userp = 0; return; } for (up=ubuf; up < &ubuf[USIZE]; up++) { if (up->name[0] == '\0') break; for (j=0; j<8 && up->name[j]==ibuf.name[j]; j++); if (j>=8) break; } for (j=0; j<8; j++) up->name[j] = ibuf.name[j]; tp->userp = up; } among(i) { register j, k; register char *p; if (pcount==0) return(1); for (j=0; j 1) tname = *argv[1]; for (;;) { for(tabp = itab; tabp < &itab[NITAB]; tabp++) if(tabp->tname == tname) break; if(tabp >= &itab[NITAB]) tabp = itab; tmode.sgispd = tabp->ispeed; tmode.sgospd = tabp->ospeed; tmode.sgflag = tabp->iflags; tmode.sgispd = tabp->ispeed; tmode.sgospd = tabp->ospeed; stty(0, &tmode); puts(tabp->message); stty(0, &tmode); if(getname()) { tmode.sgerase = ERASE; tmode.sgkill = KILL; tmode.sgflag = i++) { p = &utmp[i]; if(p->tty[0] == 0) continue; sleep(1); sendmes(p->tty[0]); } } sendmes(tty) { register i; register char *s; i = fork(); if(i == -1) { printf("try again\n"); return; } if(i) return; s = "/dev/ttyx"; s[8] = tty; i = open(s, 1); if(i < 0) { printf("cannot open tty%c\n", tty); exit(); } close(1); dup(i); printf("Broadcast message ...\n\n"); write(1, mesg, msize); exit(); } # int buf[128], vbuf[128]; /***/ extern int errno; char *dargv[] { "/dev/df0", "/dev/dr0", "/dev/df1", "/dev/dr1", 0 }; #define NINODE 8*4 #define NB 10 #include "/usr/sys/ino.h" #include "/usr/sys/filsys.h" struct inode inode[NINODE]; struct filsys sblock; int sflg; int fi; int nifiles; int nfile; int nspcl; int nlarg; int nvlarg; int nindir; int nvindir; int ndir; int nused; int nfree; int ino; int ndup; int blist[10] { -1}; int nerror; #define BMSIZE 8192 short bmap[BMSIZE]; /***/ main(argn", nspcl); printf("files %6d\n", nfile); printf("large %6d\n", nlarg); if (nvlarg) printf("huge %6d\n", nvlarg); printf("direc %6d\n", ndir); printf("indir %6d\n", nindir); if (nvindir) printf("indir2%6d\n", nvindir); printf("used %6d\n", nused); printf("free %6d\n", nfree); close(fi); } pass1(aip) struct inode *aip; { /* int buf[128], vbuf[128]; */ register i, j, *ip; ip = aip; if ((ip->i_mode&IALLOC) == 0) return; if ((ip->i_mode&IFCHR&IFBLK) != 0) { nspcl++; return; } if ((x~y#define tabsize 20 #define all p = &itab[0]; p < &itab[20]; p++ #define ever ;; #define single 0173030 #define reboot 0173040 char shell[] "/bin/sh"; char minus[] "-"; char runc[] "/etc/rc"; char init[] "/etc/init"; char ifile[] "/etc/ttys"; char utmp[] "/etc/utmp"; char wtmpf[] "/usr/adm/wtmp"; char ctty[] "/dev/tty"; /***/ int fi; int stat; struct { int flag; int line; char coms[2]; } line; struct tab { int pid; int line; int comn; } itab[tabsize]; struct { char name[8]; char tty; char fill; i dfork(p); } } } termall() { register struct tab *p; for(all) term(p); } term(ap) struct tab *ap; { register struct tab *p; p = ap; if(p->pid != 0) { rmut(p); kill(p->pid, 9); } p->pid = 0; p->line = 0; } rline() { static char c[4]; if(read(fi, c, 4) != 4 || c[3] != '\n') return(0); line.flag = c[0]; line.line = c[1]; line.comn = c[2]; return(1); } dfork(ap) struct tab *ap; { register i; register char *tty; register struct tab *p; p = ap; i = fork(); if(i == 0) { /* chgrp gid file [file...] */ struct { int idev; int ino; int flags; char nlinks; char uid; char gid; char size0; char *size1; int addr[8]; int atime[2]; int mtime[2]; } statbuf; char buff[100]; main(argc, argv) char *argv[]; { register char **filep; register count, owner; register char *p; if ((count = argc-2) <= 0) { printf("Usage: chgrp gid file [file...]\n"); exit(1); } if ((owner = atoi(argv[1])) <= 0 && argv[1][0] != '0') if (getpw(argv[1], buff)) { printf("%s: illegal c, argv) char **argv; { register char **p; register int n, *lp; if (argc == 1) { for (p = dargv; *p;) check(*p++); exit(nerror); /***/ } while (--argc) { argv++; if (**argv=='-') switch ((*argv)[1]) { case 's': sflg++; continue; case 'b': lp = blist; while (lp < &blist[NB-1] && (n = number(argv[1]))) { *lp++ = n; argv++; argc--; } *lp++ = -1; continue; default: printf("Bad flag\n"); } check(*argv); } exit(nerror); /***/ } check(file) char ip->i_mode&IFMT) == IFDIR) ndir++; else nfile++; if ((ip->i_mode&ILARG) != 0) { nlarg++; for(i=0; i<7; i++) if (ip->i_addr[i] != 0) { nindir++; if (chk(ip->i_addr[i], "indirect")) continue; bread(ip->i_addr[i], buf, 512); for(j=0; j<128; j++) /***/ if (buf[j] != 0) chk(buf[j], "data (large)"); } if (ip->i_addr[7]) { nvlarg++; if (chk(ip->i_addr[7], "indirect")) return; bread(ip->i_addr[7], buf, 512); for(i=0; i<128; i++) /***/ if (buf[i] != 0) { _nfree = buf[0]; for(i=0; i<50; i++) /***/ sblock.s_free[i] = buf[i+1]; } return(b); } bread(bno, buff, cnt) int *buff; { register *ip; register err; seek(fi, bno, 3); if ((err=read(fi, buff, cnt)) != cnt) { printf("read error %d\n", bno); printf("err %x count %d\n", errno, err); if (sflg) { printf("No update\n"); /* sflg = 0; */ } for (ip = buff; ip < &buff[128];) /***/ *ip++ = 0; } } free(in) { register i; /* int buf[128]; */ if (sblock.s_nfree >= 50) { /***/ buf[nt time[2]; int wfill; } wtmp; main() { register i; register struct tab *p, *q; int reset(); /* * if not single user, * run shell sequence */ if(getcsw() != single) { i = fork(); if(i == 0) { open("/", 0); dup(0); dup(0); execl(shell, shell, runc, 0); exit(); } while(wait(&stat) != i); close(creat(utmp, 0644)); if ((i = open(wtmpf, 1)) >= 0) { seek(i, 0, 2); wtmp.tty = '~'; time(wtmp.time); write(i, &wtmp, sizeof wtmp); close(i); } } /* * main signal(1, 0); tty = "/dev/ttyx"; tty[8] = p->line; chown(tty, 0); chmod(tty, 0622); open(tty, 2); dup(0); execl("etc/getty", minus, p->coms, 0); exit(); } p->pid = i; } rmut(p) struct tab *p; { register i, f; static char zero[sizeof wtmp]; f = open(utmp, 1); if(f >= 0) { i = p->line; if(i >= 'a') i =+ '0' + 10 - 'a'; seek(f, (i-'0')*sizeof wtmp, 0); write(f, zero, sizeof wtmp); close(f); } f = open(wtmpf, 1); if (f >= 0) { wtmp.tty = p->line; time(wtmp.time); segroup name\n", argv[1]); exit(1); } else { p = buff; while (*p++ != ':') ; while (*p++ != ':') ; owner = atoi(p); } owner =& 255; for (filep = &argv[2]; count--; filep++) { if (stat(*filep, &statbuf) < 0) { printf("%s: can't find\n", *filep); continue; } if (chown(*filep, owner<<8 | statbuf.uid) < 0) perror("Chown"); } } getpw(name, buf) char *name, *buf; { static int pwbuff[131]; register r, c; register char *gnp, *rnp; r = 1; if((pwbuff[0] = open("/etc/*file; { register *ip, i, j; fi = open(file, sflg?2:0); if (fi < 0) { printf("cannot open %s\n", file); nerror =| 04; return; } printf("%s:\n", file); nfile = 0; nspcl = 0; nlarg = 0; nvlarg = 0; nindir = 0; nvindir = 0; ndir = 0; nused = 0; nfree = 0; ndup = 0; for (ip = bmap; ip < &bmap[BMSIZE];) /***/ *ip++ = 0; sync(); bread(1, &sblock, 512); nifiles = sblock.s_isize*8; /***/ for(i=0; ino < nifiles; i =+ NINODE/8) { /***/ bread(i+2, inode, sizeof inode); for (j=0; j nvindir++; if (chk(buf[i], "2nd indirect")) continue; bread(buf[i], vbuf, 512); for(j=0; j<128; j++) /***/ if (vbuf[j]) chk(vbuf[j], "data (very large)"); } } return; } for(i=0; i<8; i++) { if (ip->i_addr[i] != 0) chk(ip->i_addr[i], "data (small)"); } } chk(ab, s) char *ab; { register char *b; register n, m; b = ab; if (ino) nused++; if (b=sblock.s_fsize) { printf("%d bad; inode=%d, class=%s\n", b, ino, s); return(1); } m = 1 0] = sblock.s_nfree; for(i=0; i<50; i++) /***/ buf[i+1] = sblock.s_free[i]; sblock.s_nfree = 0; bwrite(in, buf); } sblock.s_free[sblock.s_nfree++] = in; } bwrite(bno, buff) { register err; seek(fi, bno, 3); if ((err=write(fi, buff, 512)) != 512) { printf("write error %d\n", bno); printf("err %x count %d\n", errno, err); } } number(as) char *as; { register n, c; register char *s; s = as; n = 0; while ((c = *s++) >= '0' && c <= '9') { n = n*10+c-'0'; } return(n); } makefree()loop for hangup signal * close all files and * check switches for magic values */ setexit(); signal(1, reset); for(i=0; i<10; i++) close(i); switch(getcsw()) { case single: error: termall(); i = fork(); if(i == 0) { open(ctty, 2); dup(0); execl(shell, minus, 0); exit(); } while(wait(&stat) != i); case reboot: termall(); execl(init, minus, 0); reset(); } /* * open and merge in init file */ fi = open(ifile, 0); q = &itab[0]; while(rline()) { if(line.fek(f, 0, 2); write(f, &wtmp, sizeof wtmp); close(f); } } getcsw() { return(csw()); } group", 0)) < 0) return(1); loop: gnp = name; rnp = buf; while((c=getc(pwbuff)) != '\n') { if(c <= 0) goto ret; *rnp++ = c; } *rnp++ = '\0'; rnp = buf; while (*gnp++ == *rnp++); if (*--gnp != '\0' || *--rnp != ':') goto loop; r = 0; ret: close(pwbuff[0]); pwbuff[1] = 0; pwbuff[2] = 0; return(r); } >4) & (BMSIZE-1); if (bmap[n]&m) { printf("%d dup; inode=%d, class=%s\n", b, ino, s); ndup++; } bmap[n] =| m; for (n=0; blist[n] != -1; n++) if (b == blist[n]) printf("%d arg; inode=%d, class=%s\n", b, ino, s); return(0); } alloc() { register b, i; /* int buf[128]; */ i = --sblock.s_nfree; if (i<0 || i>=50) { /***/ printf("bad freeblock\n"); return(0); } b = sblock.s_free[i]; if (b == 0) return(0); if (sblock.s_nfree <= 0) { bread(b, buf, 512); sblock.s { register i; sblock.s_nfree = 0; sblock.s_ninode = 0; sblock.s_flock = 0; sblock.s_ilock = 0; sblock.s_fmod = 0; free(0); for(i=sblock.s_fsize-1; i>=sblock.s_isize+2; i--) { if ((bmap[(i>>4)&(BMSIZE-1)] & (1<<(i&017)))==0) free(i); } bwrite(1, &sblock); close(fi); sync(); return; } lag == '0') continue; for(all) if(p->line==line.line || p->line==0) { if(p >= q) { i = p->pid; p->pid = q->pid; q->pid = i; p->line = q->line; p->comn = q->comn; q->line = line.line; q->coms[0] = line.comn; q++; } break; } } close(fi); if(q == &itab[0]) goto error; for(; q < &itab[tabsize]; q++) term(q); for(all) if(p->line != 0 && p->pid == 0) dfork(p); for(ever) { i = wait(&stat); for(all) if(p->pid == i) { rmut(p); Level 6 maintenance commands - install in /etc /* chown uid file [file...] */ struct { int idev; int ino; int flags; char nlinks; char uid; char gid; char size0; char *size1; int addr[8]; int atime[2]; int mtime[2]; } statbuf; char buff[100]; main(argc, argv) char *argv[]; { register char **filep; register count, owner; register char *p; if ((count = argc-2) <= 0) { printf("Usage: chown uid file [file...]\n"); exit(1); } if ((owner = atoi(argv[1])) <= 0 && argv[1][0] != '0') { if (getpw(argv[1], buff)) { printf("%s: illegal user name\n", argv[1]); exit(1); } else { p = buff; while (*p++ != ':') ; while (*p++ != ':') ; owner = atoi(p); } } owner =& 255; for (filep = &argv[2]; count--; filep++) { if (stat(*filep, &statbuf) < 0) { printf("%s: can't find\n", *filep); continue; } if (chown(*filep, statbuf.gid<<8 | owner) < 0) perror("Chown"); } } getpw(name, buf) char *name, *buf; { static int pwbuff[131]; int r, c; register char *gnp, *rnp; r = 1; if((pwbuff[0] = open("/etc/p; register struct inode *ip; int ino; ofile = "/dev/mt0"; time(date); if(argc == 1) { argv = dargv; for(argc = 1; dargv[argc]; argc++); } argc--; argv++; key = *argv; while(*key) switch(*key++) { default: printf("bad character in key\n"); exit(); case 'a': /* dump all (even large) */ aflg++; continue; case '-': continue; case 'c': /* increment file name */ cflg++; continue; case 'f': /* file name from arg list */ argc--; argv++; ofile = *argv; continue; cas continue; } if(ip->i_mtime[0] < ddate[0]) goto no; if(ip->i_mtime[0] == ddate[0] && ip->i_mtime[1] < ddate[1]) goto no; s = size(ip->i_size0&0377, ip->i_size1) + 1; if (s>MAXSIZE && aflg==0 && iflg!=0) { printf("%l big; not dumped.\n", ino); goto no; } nfil++; nblk =+ s; *tap++ = s; continue; no: *tap++ = 0; } } printf("%l files\n%l blocks\n", nfil, nblk); i = ldiv(0, nblk, ldiv(0, tsize, 10)); printf("%l.%l tapes\n", i/10, i%10); tap = bek(f, 0, 0); write(f, dtab, sizeof dtab); printf("date updated\n"); pdate(date); } pdate(d) int *d; { if(d[0] == 0 && d[1] == 0) printf("the epoch\n"); else printf(ctime(d)); } dump(ip, sz) struct inode *ip; { register *p, *q, *r; p = dbuf; q = ip; clrbuf(p); while(q < &ip->i_mtime[2]) *p++ = *q++; swrite(dbuf); if(ip->i_mode & (IFBLK&IFCHR)) { if(sz != 0) printf("special\n"); return; } for(p = &ip->i_addr[0]; p < &ip->i_addr[8]; p++) if(*p) { if(ip->i_mode&ILARG) { bread { register char *p; fo = creat(ofile, 0666); if(fo < 0) { printf("can not open %s\n", ofile); exit(); } if(!cflg) return; p = ofile; while(*p++) ; p[-2]++; } equal(a, b) char *a, *b; { while(*a++ == *b) if(*b++ == 0) return(1); return(0); } ++; if(sz == 0 || sz == -1) { if(com == 0) continue; if(i == com) { printf("%l", i); l =+ 5; } else { printf("%l-%l", com, i); l =+ 10; } if(l > 60) { printf("\n"); l = 0; } else printf(","); com = 0; } else if(com == 0) com = i+1; } if(com) printf("%l-\n", com); printf("\n"); exit(); case 'r': if(argc <= 1) { printf("no filesystem name\n"); exit(); } ofile = argv[1]; fo = open(ofile, 2); if(fo < 0) { printf("can not open %s\n",asswd", 0)) < 0) return(1); loop: gnp = name; rnp = buf; while((c=getc(pwbuff)) != '\n') { if(c <= 0) goto ret; *rnp++ = c; } *rnp++ = '\0'; rnp = buf; while (*gnp++ == *rnp++); if (*--gnp != '\0' || *--rnp != ':') goto loop; r = 0; ret: close(pwbuff[0]); pwbuff[1] = 0; pwbuff[2] = 0; return(r); } e 'i': /* date from date file */ iflg++; continue; case 's': /* tape size */ tsize = number(argv[1]) * 9; argv++; argc--; continue; case 'b': /* tape size */ tsize = number(argv[1]); argv++; argc--; continue; case 'u': /* rewrite date */ dflg++; continue; case '0': /* dump all */ ddate[0] = ddate[1] = 0; continue; case 'd': /* dump some number of days */ i = 21600; goto sd; case 'h': /* dump some number of hours */ i = 900; goto sd; sd: ddate[0] = date[0];uf; clrbuf(tap); *tap++ = sblock.s_isize; *tap++ = sblock.s_fsize; *tap++ = date[0]; *tap++ = date[1]; *tap++ = ddate[0]; *tap++ = ddate[1]; *tap++ = tsize; swrite(buf); i = size(0, sblock.s_isize*XCINODE); tap = talist; while(i--) { bwrite(tap); tap =+ XCBLKINT; } tap = talist; for(i=0; ii_addr[7]) { bread(*q, vbuf); for(r = &vbuf[0]; r < &vbuf[XCBLKINT]; r++) if(*r) { if(--sz < 0) goto pe; bread(*r, dbuf); bwrite(dbuf); } continue; } if(--sz < 0) goto pe; bread(*q, dbuf); bwrite(dbuf); } } else { if(--sz < 0) goto pe; bread(*p, dbuf); bwrite(dbuf); } } if(sz) goto pe; return; pe: clrbuf(dbuf); while(--sz ># /* * restore from incremental dumps */ char *dargv[] { 0, "t", 0 }; char *ifile; char *ofile; #include "/usr/sys/ino.h" #include "/usr/sys/filsys.h" #define XCBLKINT (512/sizeof(int)) #define XCINODE (512/sizeof(struct inode)*sizeof(int)) struct filsys sblock; int isize; int *talist; int fi; int buf[XCBLKINT]; int dbuf[XCBLKINT]; int ccbuf[XCBLKINT]; char *date[2]; char *ddate[2]; int fo; int inumber; int pher; char *tsize 15000; int iflg; int wflg; int cflg; char file[10]; int ilist[100]; main( ofile); exit(); } printf("last chance before scribbling on %s\n", ofile); getchar(); dread(1, &sblock); tap = talist; inumber = 0; for(i=0; i= isize) break; dread(i+2, buf); for(ip = &buf[0]; ip < &buf[XCBLKINT]; ip++) { sz = *tap++; inumber++; if(sz == 0) continue; dealoc(ip); if(sz == -1) { for(p = ip; p < &ip->i_mtime[2]; ) *p++ = 0; continue; } sread(dbuf, 0); q = dbuf; for(p = ip; p < &ip->i_mtime[2]; ) *p+# /* * incremental dump * dump fisbuodh filesystem * f take output tape from arglist * i from date in /etc/dtab * s specify tape size in feet (feet = blocks/9) * b specify tape size in blocks * u update /etc/dtab to current date * 0 dump from the epoch * d dump specified number of days * h dump specified number of hours * a on incremental dump, dump files even >= MAXSIZE */ char *dargv[] { 0, "i", "/dev/dfix", 0 }; #include "/usr/sys/ino.h" #include "/usr/sys/filsys.h" #define MAXSIZE 100 ddate[1] = date[1]; s = number(argv[1])*4; argv++; argc--; while(s) { if(i > ddate[1]) ddate[0]--; ddate[1] =- i; s--; } continue; } if(argc <= 1) { printf("no file system specified\n"); exit(); } if(iflg) { f = open(dfile, 0); if(f >= 0) { read(f, dtab, sizeof dtab); close(f); for(i=0; i<10; i++) if(equal(dtab[i].name, argv[1])) { ddate[0] = dtab[i].date[0]; ddate[1] = dtab[i].date[1]; } } } printf("%s:\n", argv[1]); fi = open(argv[1],= 0) bwrite(dbuf); pher++; } bread(bno, b) { seek(fi, bno, 3); if(read(fi, b, 512) != 512) { printf("read error %l\n", bno); } } clrbuf(b) int *b; { register i, *p; p = b; i = XCBLKINT; while(i--) *p++ = 0; } swrite(b) int *b; { register i, s, *p; i = XCBLKINT-2; s = taddr; p = b; while(i--) s =+ *p++; *p++ = taddr; *p = 031415 - s; bwrite(b); } bwrite(b) { if(taddr == 0) { if(fo != -1) { printf("change tapes\n"); close(fo); rdline(); } otape(); } wloop: if(argc, argv) char **argv; { char *key; register *tap, *p; register struct inode *ip; int i, com, sz, *q, l; ifile = "/dev/mt0"; if(argc == 1) { argv = dargv; for(argc = 1; dargv[argc]; argc++); } argc--; argv++; key = *argv; while(*key) switch(*key++) { default: printf("bad character in key\n"); exit(); case 't': case 'r': case 'x': com = key[-1]; continue; case 'i': iflg++; continue; case '-': continue; case 'c': cflg++; continue; case 'f': argv++; argc--+ = *q++; restor(ip, sz-1); } dwrite(i+2, buf); } dwrite(1, &sblock); com = 0; for(; i < isize; i++) for(l = 0; l < 512/sizeof (struct inode); l++) { sz = *tap++; if(sz != 0 && sz != -1) com++; } if(com) printf("%l files not restored - small ilist\n", com); exit(); case 'x': i = 0; tap = ilist; while(argc > 1) { i++; sz = number(argv[1]); argv++; argc--; if(sz <= 0 || sz >=isize*512/sizeof (struct inode)) { printf("%l not in range\n", sz); continue; } if(0 #define XCBLKINT (512/sizeof(int)) #define XCINODE (512/sizeof(struct inode)*sizeof(int)) struct filsys sblock; struct { char name[16]; int date[2]; } dtab[10]; char *dfile "/etc/dtab"; char *ofile; int *talist; int fi; int buf[XCBLKINT]; int dbuf[XCBLKINT]; int ibuf[XCBLKINT]; int vbuf[XCBLKINT]; char *date[2]; char *ddate[2]; int fo -1; int pher; int dflg; int iflg; int cflg; int aflg; char *tsize 19000; char *taddr; main(argc, argv) char **argv; { char *key; int s, i, nfil, nblk, f; register *tap 0); if(fi < 0) { printf("cannot open %s\n", argv[1]); exit(); } printf("incremental dump from\n"); pdate(ddate); sync(); bread(1, &sblock); talist = sbrk(size(0, sblock.s_isize*XCINODE) * 512); tap = talist; if(tap == -1) { printf("No memory\n"); exit(); } nfil = 0; nblk = size(0, sblock.s_isize*XCINODE); ino = 0; for(i=0; ii_mode == 0 || ip->i_nlink == 0) { *tap++ = -1; exit(); for(i=0; i<10; i++) dtab[i].name[0] = 0; f = open(dfile, 2); if(f < 0) { f = creat(dfile, 0666); if(f < 0) { printf("cannot create %s\n", dfile); exit(); } } else read(f, dtab, sizeof dtab); for(i=0; i<10; i++) if(dtab[i].name[0] == 0 || equal(dtab[i].name, argv[1])) goto found; printf("%s full\n", dfile); exit(); found: for(s=0; s<15; s++) { dtab[i].name[s] = argv[1][s]; if(argv[1][s] == 0) break; } dtab[i].date[0] = date[0]; dtab[i].date[1] = date[1]; sewrite(fo, b, 512) != 512) { printf("write error\n"); rdline(); seek(fo, taddr, 3); goto wloop; } taddr++; if(taddr >= tsize) taddr = 0; } rdline() { char c; /***/ loop: c = 0; read(0, &c, 1); if(c == 0) exit(); if(c != '\n') goto loop; } number(s) char *s; { register n, c; n = 0; while(c = *s++) { if(c<'0' || c>'9') continue; n = n*10+c-'0'; } return(n); } size(s0, s1) { register s; extern ldivr; s = ldiv(s0&0377, s1, 512); if(ldivr) s++; return(s); } otape(); ifile = *argv; continue; case 'w': wflg++; continue; } otape(); sread(buf, 0); tap = buf; isize = *tap++; *tap++; /* fsize */ date[0] = *tap++; date[1] = *tap++; ddate[0] = *tap++; ddate[1] = *tap++; tsize = *tap++; i = size(0, isize*XCINODE); talist = sbrk(i*512); tap = talist; while(i--) { tread(tap, 0); tap =+ XCBLKINT; } switch(com) { case 't': l = 0; com = 0; pdate(ddate); pdate(date); tap = talist; for(i=0; ii_size0 == 0 && ip->i_size1 < 512) com = ip->i_size1; write(fo, dbuf, com); if(com > ip->i_size1) ip->i_size0--; ip->i_size1 =- com; } close(fo); chmod(file, ip->i_mode); chown(file, ip->i_uid); } exit(); } } dealoc(p) struct inode *p; { register struct inode *ip; register i, j; int k; int xbuf[XCBLKINT],j] = alloc(); if(j >= 7) xbuf[j-7] = alloc(); for(i=0; ii_addr[j], dbuf); else dwrite(xbuf[j-7], dbuf); } if(j >= 7) dwrite(ip->i_addr[7], xbuf); ip->i_mode =| ILARG; } rcop() { register b; b = alloc(); tread(ccbuf, 0); dwrite(b, ccbuf); return(b); } pdate(d) int *d; { if(d[0] == 0 && d[1] == 0) printf("the epoch\n"); else printf(ctime(d)); } dread(bno, b) { seek(fo, bno, 3); ifster i; dconv(ino, file); loop: if(wflg) { printf("%s ", file); i = getchar(); if(i == 'x') exit(); if(i == '\n') return(-1); if(i != 'y') goto flush; i = getchar(); if(i != '\n') { flush: while((i=getchar()) != '\n') if(i == '\0') exit(); goto loop; } } i = creat(file, 0666); return(i); } dconv(n, p) char *p; { register i; if(i = ldiv(0, n, 10)) p = dconv(i, p); *p++ = lrem(0, n, 10) + '0'; *p = '\0'; return(p); } alloc() { register b, i; i = --s/* * Line printer daemon */ /* File names */ char lpd[] "/usr/lpd"; char lock[] "/usr/lpd/lock"; char printer[] "/dev/pr"; /* * control sequence to set unix default tabs on hydra */ char stabs[] { "\033G008016024032040048056064072080088096104112120128\n" }; /* Buffers */ int cmdbuf[131]; /* for reading command file */ char prbuf[512]; /* for copying file to printer */ char lbuf[64]; /* for assembling lines from command file */ char dbuf[17]; /* for reading directory */ /* Tty modes for printer */ /* EOF or unknown command */ default: close(cmdbuf[0]); return; /* Unsupported commands */ case 'S': case 'L': case 'M': getline(); continue; /* Copy file in binary ('F' means prepend a form feed */ case 'F': case 'B': getline(); if ((in = open(lbuf, 0)) < 0) continue; while ((len = read(in, prbuf, 512)) > 0 && write(1, prbuf, len) == len) ; if (c == 'F') write(1, "\014", 1); continue; /* Delete file after copying */ case 'U': gete E2BIG 7 #define ENOEXEC 8 #define ENOENT 2 #define STRSIZ 522 char ab[STRSIZ]; /* generated characters */ char *ava[200]; /* generated arguments */ char **av; char *string ab; int errno; int ncoll; main(argc, argv) char *argv[]; { register char *cp; av = &ava[1]; /*** this cannot be initialized statically *** because offsets from externs are illegal *** with Interdata assembler. ***/ if (argc < 3) { write(2, "Arg count\n", 10); return; } argv++; *av++ = *argv; while (--argc(read(fo, b, 512) != 512) { printf("disk read error %l ino=%l\n", bno, inumber); exit(); } } dwrite(bno, b) { seek(fo, bno, 3); if(write(fo, b, 512) != 512) { printf("disk write error %l ino=%l\n", bno, inumber); exit(); } } sread(b, flag) int *b; { register i, s, *p; tread(b, flag); if(flag) return; i = XCBLKINT; s = 0; p = b; while(i--) s =+ *p++; if(s != 031415) { printf("checksum error ino=%l\n", inumber); if(!iflg) exit(); } } tread(b, flag) int *b; { register c; block.s_nfree; /***/ if(i<0 || i>=50) { printf("bad freeblock\n"); exit(); } b = sblock.s_free[i]; if(b == 0) { printf("out of freelist\n"); exit(); } if(sblock.s_nfree <= 0) { dread(b, ccbuf); sblock.s_nfree = ccbuf[0]; /***/ for(i=0; i<50; i++) sblock.s_free[i] = ccbuf[i+1]; } return(b); } free(in) { register i; /***/ if(sblock.s_nfree >= 50) { ccbuf[0] = sblock.s_nfree; /***/ for(i=0; i<50; i++) ccbuf[i+1] = sblock.s_free[i]; sblock.s_nfree = 0; dwrite(in, ccbuf); } int ttymode[3] { (10<<8) | 10, /* 1800 baud */ 0, 020 /* CRMOD */ }; main() { register flag; /* Ignore quit, interrupt, hangup */ signal(1, 1); signal(2, 1); signal(3, 1); /* Use lock to prevent multiple active daemons */ if (creat(lock, 0) < 0) exit(0); /* Fork and exit, thus spawning the daemon */ if (fork()) exit(0); /* Before opening the printer, make sure there's something to print */ close(0); close(1); close(2); if (open(lpd, 0) != 0) dexit(); flag = 0; while (read(0line(); unlink(lbuf); continue; } } close(cmdbuf[0]); } /* * Read rest of line from command file */ getline() { register char *p; register c; for (p = lbuf; (*p = c = getc(cmdbuf)) != '\n' && c > 0; p++) ; *p = '\0'; } >= 2) expand(*++argv); if (ncoll==0) { write(2, "No match\n", 9); return; } execute(ava[1], &ava[1]); cp = cat("/usr/bin/", ava[1]); execute(cp+4, &ava[1]); execute(cp, &ava[1]); write(2, "Command not found.\n", 19); } expand(as) char *as; { register char *s, *cs; register int dirf; char **oav; static struct { int ino; char name[16]; } entry; s = cs = as; while (*cs!='*' && *cs!='?' && *cs!='[') { if (*cs++ == 0) { *av++ = cat(s, ""); return; } } for (;;) { if (cs==s ybuf[XCBLKINT]; ip = p; if(ip->i_mode & (IFCHR&IFBLK)) return; for(i=7; i>=0; i--) if(ip->i_addr[i]) { if(ip->i_mode&ILARG) { dread(ip->i_addr[i], xbuf); for(j=XCBLKINT-1; j>=0; j--) if(xbuf[j]) { if(i == 7) { dread(xbuf[j], ybuf); for(k=XCBLKINT-1; k>=0; k--) if(ybuf[k]) free(ybuf[k]); } free(xbuf[j]); } } free(ip->i_addr[i]); } } restor(p, sz) struct inode *p; { register struct inode *ip; register i, j; int xbuf[XCBLKINT]; ip = p; if(ip->istatic char *pta, *ata, ctflg; if(pta++ >= tsize) { pta = 1; ata = 0; close(fi); otape(); ctflg++; } if(flag) return; if(ctflg) { printf("change tapes\n"); if(ctflg > 1) printf("skip %d tapes\n", ctflg-1); while((c = getchar()) != '\n') if(c == 0) exit(); ctflg = 0; } ata++; if(iflg) for(; pta != ata; ata++) read(fi, b, 512); if(pta != ata) { seek(fi, pta-ata, 4); ata = pta; } if(read(fi, b, 512) != 512) { printf("tape read error %l ino=%l\n", ata-1, inumbersblock.s_free[sblock.s_nfree++] = in; } , dbuf, 16) == 16) if ((dbuf[0] | dbuf[1]) != 0 && dbuf[2] == 'd' && dbuf[3] == 'f') flag++; if (!flag) dexit(); /* Open the printer, and set proper tty modes */ if (open(printer, 1) != 1) dexit(); stty(1, ttymode); /* set hydra tabs */ write(1, stabs, sizeof stabs); /*** hydra ***/ /* Search lpd directory for work to do */ if (chdir(lpd) < 0) dexit(); seek(0, 0, 0); while (read(0, dbuf, 16) == 16) { if ((dbuf[0] | dbuf[1]) == 0 || dbuf[2] != 'd' || dbuf[3] != 'f') cocc -o ac -s ac.c cc -o chgrp -s chgrp.c cc -o chown -s chown.c cc -o clri -s clri.c cc -o cron -s cron.c cc -o dcheck -s dcheck.c cc -o dump -s dump.c cc -o getty -s getty.c cc -o glob -s -n glob.c cc -o icheck -s icheck.c cc -o init -s init.c cc -o mkfs -s mkfs.c cc -o mknod -s mknod.c cc -o mount -s mount.c cc -o ncheck -s ncheck.c cc -o restor -s restor.c cc -o sa -s sa.c cc -o umount -s umount.c cc -o update -s update.c cc -o wall -s wall.c ) { dirf = open(".", 0); s = ""; break; } if (*--cs == '/') { *cs = 0; dirf = open(s==cs? "/": s, 0); *cs++ = 0200; break; } } if (dirf<0) { write(2, "No directory\n", 13); exit(); } oav = av; while (read(dirf, &entry.name[-2], 16) == 16) { /***/ if (entry.ino==0) continue; if (match(entry.name, cs)) { *av++ = cat(s, entry.name); ncoll++; } } close(dirf); sort(oav); } sort(oav) char **oav; { register char **p1, **p2, **c; p1 = oav; while (p1 < av-1_mode & (IFCHR&IFBLK)) return; for(i=0; i<8; i++) ip->i_addr[i] = 0; if(sz <= 8) { for(i=0; ii_addr[i] = rcop(); ip->i_mode =& ~ILARG; return; } for(i=0; i= XCBLKINT; j++) { if(j <= 7) ip->i_addr[j] = alloc(); if(j >= 7) xbuf[j-7] = alloc(); for(i=0; ii_addr[j], dbuf); else dwrite(xbuf[j-7], dbuf); sz =- XCBLKINT; } if(sz) { if(j <= 7) ip->i_addr[); if(!iflg) exit(); for(c=0; c'9') continue; n = n*10+c-'0'; } return(n); } size(s0, s1) { register s; extern ldivr; s = ldiv(s0&0377, s1, 512); if(ldivr) s++; return(s); } otape() { register char *p; fi = open(ifile, 0); if(fi < 0) { printf("can not open %s\n", ifile); exit(); } if(!cflg) return; p = ifile; while(*p++) ; p[-2]++; } dwait(ino) { regicpall \ ac \ chgrp \ chown \ clri \ cron \ dcheck \ dump \ getty \ glob \ icheck \ init \ mkfs \ mknod \ mount \ ncheck \ restor \ sa \ umount \ update \ wall \ /etc rm \ ac \ chgrp \ chown \ clri \ cron \ dcheck \ dump \ getty \ glob \ icheck \ init \ mkfs \ mknod \ mount \ ncheck \ restor \ sa \ umount \ update \ wall ntinue; /* Process one command file */ spool(&dbuf[2]); unlink(&dbuf[2]); /* Reread directory in case it changed while we were spooling */ seek(0, 0, 0); } /*** write(1, "\014", 1); /* extra form feed to waste paper */ dexit(); } /* * Remove lock and terminate */ dexit() { unlink(lock); exit(0); } /* * Read and obey a file of spooling commands */ spool(dfname) char *dfname; { register in, len, c; if (fopen(dfname, cmdbuf) < 0) return; for(;;) { switch (c = getc(cmdbuf)) { # /* global command -- glob params "*" in params matches r.e ".*" "?" in params matches r.e. "." "[...]" in params matches character class "[...a-z...]" in params matches a through z. perform command with argument list constructed as follows: if param does not contain "*", "[", or "?", use it as is if it does, find all files in current directory which match the param, sort them, and use them prepend the command name with "/bin" or "/usr/bin" as required. */ #defin) { p2 = p1; while(++p2 < av) { if (compar(*p1, *p2) > 0) { c = *p1; *p1 = *p2; *p2 = c; } } p1++; } } execute(afile, aarg) char *afile; char **aarg; { register char *file, **arg; arg = aarg; file = afile; execv(file, arg); if (errno==ENOEXEC) { arg[0] = file; *--arg = "/bin/sh"; execv(*arg, arg); } if (errno==E2BIG) toolong(); } toolong() { write(2, "Arg list too long\n", 18); exit(); } match(s, p) char *s, *p; { if (*s=='.' && *p!='.') return(0); return(amatch(s, p)); } amatch(as, ap) char *as, *ap; { register char *s, *p; register scc; int c, cc, ok, lc; s = as; p = ap; if (scc = *s++) if ((scc =& 0177) == 0) scc = 0200; switch (c = *p++) { case '[': ok = 0; lc = 077777; while (cc = *p++) { if (cc==']') { if (ok) return(amatch(s, p)); else return(0); } else if (cc=='-') { if (lc<=scc && scc<=(c = *p++)) ok++; } else if (scc == (lc=cc)) ok++; } return(0); default: if (c!=scc) ret#include "sno.h" /* * Snobol III */ int freesize; struct node *freespace &end; struct node *freelist 0; int *fault -1; mes(s) { sysput(strstr(s)); } init(s, t) { register struct node *a, *b; a = strstr(s); b = look(a); delete(a); b->typ = t; return(b); } main(argc, argv) char *argv[]; { extern fin, fout; register struct node *a, *b, *c; if(argc > 1) { fin = open(argv[1], 0); if(fin < 0) { mes("cannot open input"); exit(); } } /* fout = dup(1); */ lookf = init("f", 0); loster struct node *f; register int i; extern fout; if (freelist==0) { if (--freesize < 20) { if ((i=sbrk(200*sizeof *f)) == -1) { /***/ flush(); write (fout, "Out of free space\n", 18); exit(); } freesize =+ 200; } return(freespace++); } f = freelist; freelist = freelist->p1; return(f); } free(pointer) struct node *pointer; { pointer->p1 = freelist; freelist = pointer; } nfree() { register int i; register struct node *a; i = freesize; a = freelist; while(a) { a  = dcat(c, d); sysput(cat(e, b->p1)); delete(e); if (b->typ==1) { c = strstr(" "); sysput(cat(c, b->p2)); delete(c); } base = base->p2; } } writes(s) { sysput(dcat(binstr(lc),dcat(strstr("\t"),strstr(s)))); flush(); if (cfail) { dump(); flush(); exit(); } while(agetc()); while (compile()); flush(); exit(); } agetc() { register struct node *a; static struct node *line; static linflg; while (line==0) { line = syspit(); if(rfail) { cfail++; writes("eof on i>ch == c) { free(schar); a->typ = 15; a->p1 = 0; return(a); } b->p1 = a; for(;;) { schar = agetc(); if (schar == 0) lerr: writes("illegal literal string"); if(schar->ch == c) break; a->p1 = schar; a = schar; } b->p2 = a; schar->typ = 15; schar->p1 = b; return(schar); case 10: schar->typ = 3; return(schar); case 11: schar->typ = 4; return(schar); } b = alloc(); b->p1 = a = schar; schar = agetc(); while(schar!=0 & !class(schar->ch)) { aurn(0); case '?': if (scc) return(amatch(s, p)); return(0); case '*': return(umatch(--s, p)); case '\0': return(!scc); } } umatch(s, p) char *s, *p; { if(*p==0) return(1); while(*s) if (amatch(s++,p)) return(1); return(0); } compar(as1, as2) char *as1, *as2; { register char *s1, *s2; s1 = as1; s2 = as2; while (*s1++ == *s2) if (*s2++ == 0) return(0); return (*--s1 - *s2); } cat(as1, as2) char *as1, *as2; { register char *s1, *s2; register int c; s2 = string; soks = init("s", 0); lookend = init("end", 0); lookstart = init("start", 0); lookdef = init("define", 0); lookret = init("return", 0); lookfret = init("freturn", 0); init("syspit", 3); init("syspot", 4); a = c = compile(); while (lookend->typ != 2) { a->p1 = b = compile(); a = b; } cfail = 1; a->p1 = 0; if (lookstart->typ == 2) c = lookstart->p2; while (c=execute(c)); flush(); } syspit() { extern fin; register struct node *b, *c, *d; int a; if ((a=getchar())=='\n') return(0); b = a->p1; i++; } return(i); } look(string) struct node *string; { register struct node *i, *j, *k; k = 0; i = namelist; while (i) { j = i->p1; if (equal(j->p1, string) == 0) return(j); i = (k=i)->p2; } i = alloc(); i->p2 = 0; if (k) k->p2 = i; else namelist = i; j = alloc(); i->p1 = j; j->p1 = copy(string); j->p2 = 0; j->typ = 0; return(j); } copy(string) struct node *string; { register struct node *j, *l, *m; struct node *i, *k; if (string == 0) return(0); i = l = aloop; } binstr(binary) { int n, sign; register struct node *m, *p, *q; n = binary; p = alloc(); q = alloc(); sign = 1; if (binary<0) { sign = -1; n = -binary; } p->p2 = q; loop: q->ch = n%10+'0'; n = n / 10; if (n==0) { if (sign<0) { m = alloc(); m->p1 = q; q = m; q->ch = '-'; } p->p1 = q; return(p); } m = alloc(); m->p1 = q; q = m; goto loop; } add(string1, string2) { return(binstr(strbin(string1) + strbin(string2))); } sub(string1, string2) { return(binstr(stnput"); } lc++; } if (linflg) { line = 0; linflg = 0; return(0); } a = line->p1; if (a==line->p2) { free(line); linflg++; } else line->p1 = a->p1; return(a); } ->p1 = schar; a = schar; schar = agetc(); } b->p2 = a; next = 1; a = look(b); delete(b); b = alloc(); b->typ = 14; b->p1 = a; return(b); } nscomp() { register struct node *c; while((c=compon())->typ == 7) free(c); return(c); } push(stack) { register struct node *a; (a=alloc())->p2 = stack; return(a); } pop(stack) struct node *stack; { register struct node *a, *s; s = stack; if (s == 0) writes("pop"); a = s->p2; free(s); return(a); } expr(start, eof, e) struct node *e; { 1 = as1; while (c = *s1++) { if (s2 > &ab[STRSIZ]) toolong(); c =& 0177; if (c==0) { *s2++ = '/'; break; } *s2++ = c; } s1 = as2; do { if (s2 > &ab[STRSIZ]) toolong(); *s2++ = c = *s1++; } while (c); s1 = string; string = s2; return(s1); } = c = alloc(); while(a != '\n') { c->p1 = d = alloc(); c = d; l: c->ch = a; if(a == '\0') { if(fin) { close(fin); fin = 0; a = getchar(); goto l; } rfail = 1; break; } a = getchar(); } b->p2 = c; if(rfail) { delete(b); b = 0; } return(b); } syspot(string) struct node *string; { register struct node *a, *b, *s; s = string; if (s!=0) { a = s; b = s->p2; while(a != b) { a = a->p1; putchar(a->ch); } } putchar('\n'); } strstr(s) char s[]; {lloc(); j = string; k = string->p2; while(j != k) { m = alloc(); m->ch = (j=j->p1)->ch; l->p1 = m; l = m; } i->p2 = l; return(i); } equal(string1, string2) struct node *string1, *string2; { register struct node *i, *j, *k; struct node *l; int n, m; if (string1==0) { if (string2==0) return(0); return(-1); } if (string2==0) return(1); i = string1; j = string1->p2; k = string2; l = string2->p2; for(;;) { m = (i=i->p1)->ch; n = (k=k->p1)->ch; if (m>n) return(1); ifrbin(string1) - strbin(string2))); } mult(string1, string2) { return(binstr(strbin(string1) * strbin(string2))); } div(string1, string2) { return(binstr(strbin(string1) / strbin(string2))); } cat(string1, string2) struct node *string1, *string2; { register struct node *a, *b; if (string1==0) return(copy(string2)); if (string2==0) return(copy(string1)); a = copy(string1); b = copy(string2); a->p2->p1 = b->p1; a->p2 = b->p2; free(b); return(a); } dcat(a,b) struct node *a, *b; { register #include "sno.h" compon() { register struct node *a, *b; register int c; static next; if (next == 0) schar = agetc(); else next = 0; if (schar == 0) { (a=alloc())->typ = 0; return(a); } switch (class(schar->ch)) { case 1: schar->typ = 5; return(schar); case 2: schar->typ = 16; return(schar); case 3: a = schar; for(;;) { schar = agetc(); if (schar == 0) { a->typ = 0; return(a); } if (class(schar->ch) != 3) break; free(schar); } next = 1; a-register struct node *stack, *list, *comp; int operand, op, space, op1; struct node *a, *b, *c; int d; list = alloc(); e->p2 = list; stack = push(0); stack->typ = eof; operand = 0; space = start; l1: if (space) { comp = space; space = 0; } else comp = compon(); l3: op = comp->typ; switch (op) { case 7: space = 1; free(comp); comp = compon(); goto l3; case 10: if (space == 0) { comp->typ = 1; goto l3; } case 11: if (space == 0) { comp->typ = 2; goto l3; struct node { struct node *p1; struct node *p2; char typ; char ch; }; struct node *lookf; struct node *looks; struct node *lookend; struct node *lookstart; struct node *lookdef; struct node *lookret; struct node *lookfret; int cfail; int rfail; struct node *namelist; int lc; struct node *schar; int c; register struct node *e, *f, *d; d = f = alloc(); while ((c = *s++)!='\0') { (e=alloc())->ch = c; f->p1 = e; f = e; } d->p2 = e; return(d); } class(c) { switch (c) { case ')': return(1); case '(': return(2); case '\t': case ' ': return(3); case '+': return(4); case '-': return(5); case '*': return(6); case '/': return(7); case '$': return(8); case '"': case '\'': return(9); case '=': return(10); case ',': return(11); } return(0); } alloc() { regi (mp1; q = s->p2; sign = 1; if (class(p->ch)==5) { /* minus */ sign = -1; if (p==q) return(0); p = p->p1; } loop: m = p->ch - '0'; if (m>9 | m<0) writes("bad integer string"); n = n * 10 + m; if (p==q) return(n*sign); p = p->p1; goto struct node *c; c = cat(a,b); delete(a); delete(b); return(c); } delete(string) struct node *string; { register struct node *a, *b, *c; if (string==0) return; a = string; b = string->p2; while(a != b) { c = a->p1; free(a); a = c; } free(a); } sysput(string) { syspot(string); delete(string); } dump() { dump1(namelist); } dump1(base) struct node *base; { register struct node *b, *c, *e; struct node *d; while (base) { b = base->p1; c = binstr(b->typ); d = strstr(" "); e>typ = 7; return(a); case 4: schar->typ = 8; return(schar); case 5: schar->typ = 9; return(schar); case 6: a = schar; schar = agetc(); if (class(schar->ch) == 3) a->typ = 10; else a->typ = 1; next = 1; return(a); case 7: a = schar; schar = agetc(); if (class(schar->ch) == 3) a->typ = 11; else a->typ = 2; next = 1; return(a); case 8: schar->typ = 12; return(schar); case 9: c = schar->ch; a = agetc(); if(a == 0) goto lerr; b = schar; if(a-} case 8: case 9: if (operand == 0) writes("no operand preceding operator"); operand = 0; goto l5; case 14: case 15: if (operand == 0) { operand = 1; goto l5; } if (space == 0) goto l7; goto l4; case 12: if (operand == 0) goto l5; if (space) goto l4; l7: writes("illegal juxtaposition of operands"); case 16: if (operand == 0) goto l5; if (space) goto l4; b = compon(); op = comp->typ = 13; if (b->typ == 5) { comp->p1 = 0; goto l10; } comp->p1 = a = alloc(); b = expr(b, 6, a); while((d=b->typ) == 4) { a->p1 = b; a = b; b = expr(0, 6, a); } if (d != 5) writes("error in function"); a->p1 = 0; l10: free(b); goto l6; l4: space = comp; op = 7; operand = 0; goto l6; } if (operand==0) writes("no operand at end of expression"); l5: space = 0; l6: op1 = stack->typ; if (op > op1) { stack = push(stack); if (op == 16) op = 6; stack->typ = op; stack->p1 = comp; goto l1; } c = stack->p1; stacke(comp); comp = expr(0, 6, a); } if (bal) { if (comp->typ != 5) goto merr; free(comp); comp = compon(); } b = comp->typ; if (b != 1 & b != 10) goto merr; list->p2 = a; list->typ = 2; a->typ = bal; free(comp); comp = compon(); if(bal) term = 0; else term = list; goto l3; } if(term) term->typ = 3; list->typ = 0; return(comp); merr: writes("unrecognized component in match"); } compile() { register struct node *b, *comp; struct node *r, *l, *xs, *xf, *f=alloc()); if (comp->typ != 5) goto xerr; goto xfer; asmble: if(l) { if (l->typ) writes("name doubly defined"); l->p2 = comp; l->typ = 2; /* type label;*/ } comp->p2 = r; if (m) { t++; r->p1 = m; r = m; } if (as) { t =+ 2; r->p1 = as; r = as; } (g=alloc())->p1 = 0; if (xs) { g->p1 = xs->p2; free(xs); } g->p2 = 0; if (xf) { g->p2 = xf->p2; free(xf); } r->p1 = g; comp->typ = t; comp->ch = lc; return(comp); def: r = nscomp(); if (r->typ != 14) goto derr;); } ubextend(str, last) struct node *str, *last; { register struct node *a, *b, *s; s = str; a = s->p1; if(a == 0) goto bad; b = s->p2; if(b == 0) goto good; if (b == last) goto bad; a = b->p1; good: s->p2 = a; return(1); bad: return(0); } search(arg, r) struct node *arg, *r; { struct node *list, *back, *str, *etc, *next, *last, *base, *e; register struct node *a, *b, *var; int c, d; a = arg->p2; list = base = alloc(); last = next = 0; goto badv1; badvanc: a = a->p1; if (a-> e = var->p2; while(1) { if (a->ch != b->ch) goto retard; if (b == e) goto adv01; if (a == last) goto retard; a = a->p1; b = b->p1; } } str = var->p1; etc = var->p2; str->p1 = next; str->p2 = 0; c = etc->p2; if (var->typ == 1) { d = bextend(str, last); if (d == 0) goto retard; if (c == 0) goto adv0; while(1) { c =- d; if (c == 0) goto adv0; if (c < 0) goto retard; d = bextend(str, last); if (d == 0) goto retard; } } if (c == register struct node *a1, *stack, *op; if (rfail == 1) return(0); stack = 0; list = e; goto l1; advanc: list = list->p1; l1: op = list->typ; switch (op) { default: case 0: if (t == 1) { a1 = and(stack); goto e1; } if (stack->typ == 1) writes("attempt to store in a value"); a1 = stack->p1; e1: stack = pop(stack); if (stack) writes("phase error"); return(a1); case 12: a1 = and(stack); stack->p1 = look(a1); delete(a1); stack->typ = 0; goto advanc; case 13: = pop(stack); if (stack == 0) { list->typ = 0; return(comp); } if (op1 == 6) { if (op != 5) writes("too many ('s"); goto l1; } if (op1 == 7) c = alloc(); list->typ = op1; list->p2 = c->p1; list->p1 = c; list = c; goto l6; } match(start, m) struct node *m; { register struct node *list, *comp, *term; struct node *a; int b, bal; term = bal = 0; list = alloc(); m->p2 = list; comp = start; if (!comp) comp = compon(); goto l2; l3: list->p1 = a = alloc(); list = a; l2: switg; register int a; int m, t, as; m = l = as = xs = xf = t = 0; comp = compon(); a = comp->typ; if (a == 14) { l = comp->p1; free(comp); comp = compon(); a = comp->typ; } if (a != 7) writes("no space beginning statement"); free(comp); if (l == lookdef) goto def; comp = expr(0, 11, r=alloc()); a = comp->typ; if (a == 0) goto asmble; if (a == 2) goto xfer; if (a == 3) goto assig; m = alloc(); comp = match(comp, m); a = comp->typ; if (a == 0) goto asmble; if (a == 2) g l = r->p1; if (l->typ) writes("name doubly defined"); l->typ = 5; /*type function;*/ a = r; l->p2 = a; r = nscomp(); l = r; a->p1 = l; if (r->typ == 0) goto d4; if (r->typ != 16) goto derr; d2: r = nscomp(); if (r->typ != 14) goto derr; a->p2 = r; r->typ = 0; a = r; r = nscomp(); if (r->typ == 4) { free(r); goto d2; } if (r->typ != 5) goto derr; free(r); if ((r=compon())->typ != 0) goto derr; free(r); d4: r = compile(); a->p2 = 0; l->p1 = r; l->p2 = 0; return(r)typ == 0) { list->p1 = 0; if (rfail == 1) { a = 0; goto fail; } list = base; if (r == 0) next = last = 0; else { next = r->p1; last = r->p2; } goto adv1; } b = alloc(); list->p1 = b; list = b; badv1: list->p2 = back = alloc(); back->p1 = last; b = a->p2; c = a->typ; list->typ = c; if (c < 2) { back->p2 = eval(b, 1); goto badvanc; } last = list; str = alloc(); etc = alloc(); back->p2 = var = alloc(); var->typ = b->typ; var->p1 = str; var->p2 = etc; e = b->p0) { if(d==3 & next!=0) { str->p2 = last; goto adv0; } goto advanc; } while(c--) if (ubextend(str, last) == 0) goto retard; goto adv0; fail: list = base; goto f1; fadv: free(back); b = list->p1; free(list); if (b == 0) return(a); list = b; f1: back = list->p2; var = back->p2; if (list->typ < 2) { delete(var); goto fadv; } str = var->p1; etc = var->p2; if (a != 0 & etc->p1 != 0) { if (str->p2 == 0) { free(str); str = 0; } assign(etc->p1, copy(str)); } if if (stack->typ) writes("illegal function"); a1 = stack->p1; if (a1->typ!=5) writes("illegal function"); a1 = a1->p2; op = a1->p1; a3base = a3 = alloc(); a3->p2 = op->p2; op->p2 = 0; a1 = a1->p2; a2 = list->p2; f1: if (a1!=0 & a2!=0) goto f2; if (a1!=a2) writes("parameters do not match"); op = op->p1; goto f3; f2: a3->p1 = a4 = alloc(); a3 = a4; a3->p2 = and(a1); assign(a1->p1, eval(a2->p2, 1));/* recursive */ a1 = a1->p2; a2 = a2->p1; goto f1; f3: ooto xfer; if (a == 3) goto assig; writes("unrecognized component in match"); assig: free(comp); comp = expr(0, 6, as=alloc()); a = comp->typ; if (a == 0) goto asmble; if (a == 2) goto xfer; writes("unrecognized component in assignment"); xfer: free(comp); comp = compon(); a = comp->typ; if (a == 16) goto xboth; if (a == 0) { if (xs!=0 | xf!=0) goto asmble; goto xerr; } if (a != 14) goto xerr; b = comp->p1; free(comp); if (b == looks) goto xsuc; if (b == lookf) goto ; derr: writes("illegal component in define"); } 1; if (e == 0) etc->p1 = 0; else etc->p1 = eval(e, 0); e = b->p2; if (e == 0) etc->p2 = 0; else { e = eval(e, 1); etc->p2 = strbin(e); delete(e); } goto badvanc; retard: a = back->p1; if (a == 0) { rfail = 1; goto fail; } list = a; back = list->p2; var = back->p2; str = var->p1; etc = var->p2; if (etc->p2) goto retard; if (var->typ == 1) { if (bextend(str, last) == 0) goto retard; goto adv0; } if (ubextend(str, last) == 0) goto retard; adv0: a = str->p2; adv01: (str) free(str); free(etc); free(var); goto fadv; } p = execute(op); /* recursive */ if (op) goto f3; a1 = stack->p1->p2; op = a1->p1; a3 = a3base; stack->p1 = op->p2; stack->typ = 1; op->p2 = a3->p2; f4: a4 = a3->p1; free(a3); a3 = a4; a1 = a1->p2; if (a1 == 0) goto advanc; assign(a1->p1, a3->p2); goto f4; case 11: case 10: case 9: case 8: case 7: a1 = and(stack); stack = pop(stack); a2 = and(stack); a3 = doop(op, a2, a1); delete(a1); delete(a2); stack->p1 = a3; stack->typ = 1; goto advanc; case 15:ch (comp->typ) { case 7: free(comp); comp = compon(); goto l2; case 12: case 14: case 15: case 16: term = 0; comp = expr(comp, 6, list); list->typ = 1; goto l3; case 1: free(comp); comp = compon(); bal = 0; if (comp->typ == 16) { bal = 1; free(comp); comp = compon(); } a = alloc(); b = comp->typ; if (b == 2 | b == 5 | b == 10 | b == 1) a->p1 = 0; else { comp = expr(comp, 11, a); a->p1 = a->p2; } if (comp->typ != 2) { a->p2 = 0; } else { frexfail; xerr: writes("unrecognized component in goto"); xboth: free(comp); xs = alloc(); xf = alloc(); comp = expr(0, 6, xs); if (comp->typ != 5) goto xerr; xf->p2 = xs->p2; comp = compon(); if (comp->typ != 0) goto xerr; goto asmble; xsuc: if(xs) goto xerr; comp = compon(); if (comp->typ != 16) goto xerr; comp = expr(0, 6, xs=alloc()); if (comp->typ != 5) goto xerr; goto xfer; xfail: if (xf) goto xerr; comp = compon(); if (comp->typ != 16) goto xerr; comp = expr(0, 6, x#include "sno.h" /* * sno3 */ bextend(str, last) struct node *str, *last; { register struct node *a, *s; register int b; int c, d; s = str; if ((c = s->p1) == 0) goto bad; b = d = 0; a = s->p2; if(a == 0) { a = c; goto eb2; } eb1: if (a==last) goto bad; a = a->p1; eb2: d++; c = class(a->ch); if (c == 1) { /* rp */ if (b == 0) goto bad; b--; goto eb3; } if (c == 2) { /* lp */ b++; goto eb1; } eb3: if (b == 0) { s->p2= a; return(d); } goto eb1; bad: return(0 if (a == last) next = 0; else next = a->p1; advanc: a = list->p1; if (a == 0) { a = alloc(); if (r == 0) { a->p1 = a->p2 = 0; goto fail; } b = r->p1; a->p1 = b; if (next == 0) { a->p2 = r->p2; goto fail; } while(1) { e = b->p1; if (e == next) { a->p2 = b; goto fail; } b = e; } } list = a; adv1: back = list->p2; var = back->p2; d = list->typ; if(d < 2) { if (var == 0) goto advanc; if (next == 0) goto retard; a = next; b = var->p1; #include "sno.h" /* * sno4 */ and(ptr) struct node *ptr; { register struct node *a, *p; p = ptr; a = p->p1; if (p->typ == 0) { switch (a->typ) { case0: case 0: a->typ = 1; case 1: goto l1; case 3: flush(); return(syspit()); case 5: a = a->p2->p1; goto l1; case 6: return(binstr(nfree())); } writes("attempt to take an illegal value"); goto case0; l1: a = copy(a->p2); } return(a); } eval(e, t) struct node *e; { struct node *list, *a2, *a3, *a4, *a3base; a1 = copy(list->p2); a2 = 1; goto l3; case 14: a1 = list->p2; a2 = 0; l3: stack = push(stack); stack->p1 = a1; stack->typ = a2; goto advanc; } } doop(op, arg1, arg2) { register int a1, a2; a1 = arg1; a2 = arg2; switch (op) { case 11: return(div(a1, a2)); case 10: return(mult(a1, a2)); case 8: return(add(a1, a2)); case 9: return(sub(a1, a2)); case 7: return(cat(a1, a2)); } return(0); } execute(e) struct node *e; { register struct node *r, *b, *c; struct node *m, *ca, *d, *a; r = e->p2; lc = e->ch; switch (e->typ) { case 0: /* r g */ a = r->p1; delete(eval(r->p2, 1)); goto xsuc; case 1: /* r m g */ m = r->p1; a = m->p1; b = eval(r->p2, 1); c = search(m, b); delete(b); if (c == 0) goto xfail; free(c); goto xsuc; case 2: /* r a g */ ca = r->p1; a = ca->p1; b = eval(r->p2, 0); assign(b, eval(ca->p2, 1)); goto xsuc; case 3: /* r m a g */ m = r->p1; ca = m->p1; a = ca->p1; b = eval(r->p2, 0); d = search(m, b->p2; case 5: a = addr->p2->p1; delete(a->p2); a->p2 = value; return; } } cp sno /usr/bin rm sno *.o imal point, and * signed exponent to a floating-point value */ double atof(str) char *str; { double f; register char *s, c; register n, exp, neg; int expsign; /* check leading sign */ neg = 0; if ((c = *(s = str)) == '-') { neg = 1; str++; } else if (c == '+') str++; /* scan digits before decimal pt */ f = 0.0; while ((c = *str++) <= '9' && c >= '0') { f =* 10.0; f =+ c - '0'; } /* scan digits after decimal pt */ exp = 0; if (c == '.') while ((c = *str++) <= '9' && c >= '0') ]; static int warr5[38]; static int warr6[34]; static int *wheel1 warr1; static int *wheel2 warr2; static int *wheel3 warr3; static int *wheel4 warr4; static int *wheel5 warr5; static int *wheel6 warr6; static char key[130]; static int biti; static int bitj; /* subroutine to manufacture a wheel */ static setup(list,n) int list[]; {int *lp; lp = list; while(--n){ *lp = lp+2; lp[1] = getbit(); lp = lp + 2; } *lp = list; lp[1] = getbit(); } /* subroutine to return the next bit from the mainel lugs. */ for (ii=0; ii<=7; ii++) { temp = 040*wheel1[1] + 020*wheel2[1] + 010*wheel3[1] + 004*wheel4[1] + 002*wheel5[1] + 001*wheel6[1]; wheel1 = *wheel1; wheel2 = *wheel2; wheel3 = *wheel3; wheel4 = *wheel4; wheel5 = *wheel5; wheel6 = *wheel6; random = 0; i = 27; while (i--){ random = random + ((temp & cage[i]) != 0); } random =% 26; word[ii] = random + 'a'; } return(word); } icsignal.s- title csignal -- interface to c signal routines entry csignal r0 equ 0); if (d == 0) goto xfail; c = eval(ca->p2, 1); if (d->p1 == 0) { free(d); assign(b, cat(c, b->p2)); delete(c); goto xsuc; } if (d->p2 == b->p2->p2) { assign(b, c); free(d); goto xsuc; } (r=alloc())->p1 = d->p2->p1; r->p2 = b->p2->p2; assign(b, cat(c, r)); free(d); free(r); delete(c); goto xsuc; } xsuc: if (rfail) goto xfail; b = a->p1; goto xboth; xfail: rfail = 0; b = a->p2; xboth: if (b == 0) { return(e->p1); } b = eval(b, 0); if (b == lookrstruct node { struct node *p1; struct node *p2; char typ; char ch; }; extern int freesize; extern struct node *lookf; extern struct node *looks; extern struct node *lookend; extern struct node *lookstart; extern struct node *lookdef; extern struct node *lookret; extern struct node *lookfret; extern int cfail; extern int rfail; extern struct node *freelist; extern struct node *namelist; extern int lc; extern struct node *schar; eabort.sn* abort - force an illegal instruction fault entry abort pure abort equ * dc h'0' illegal instruction end alloc.c/* c storage allocator * circular first fit strategy */ #define BLOK 512 #define BUSY 01 static char *allocs[2] { (int)&allocs[1]+BUSY, (int)&allocs[0]+BUSY }; struct { int word; }; static char **allocp &allocs[1]; /* current search pointer */ static char **alloct &allocs[1]; /* top of arena (last cell) */ alloc(nbytes) { register in{ f =* 10.0; f =+ c - '0'; exp--; } /* scan exponent */ if (c == 'e' || c == 'E') { expsign = 1; if ((c = *str) == '-') { expsign = -1; str++; } else if (c == '+') str++; n = 0; while ((c = *str++) <= '9' && c >= '0') { n =* 10; n =+ c - '0'; } exp =+ expsign*n; } /* combine no. & exponent by inefficient repeated multiplication */ if (exp) { if (exp < 0) do f =/ 10.0; while (++exp); else do f =* 10.0; while (--exp); } return(neg? -f : f); } 'at      &,2!'-3"(.4#)/5$*06%+1 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 sp equ 7 rf equ 15 * * csignal(sig, func) * * note: this routine is *not* strictly reentrant. if csignal() is * interrupted by a signal routine which itself calls csignal(), * the svc may be called incorrectly. * nsig equ 13 * add to brtab if this constant changes * einval equ 22 pure csignal equ * * * save previous signal value * l r1,0(sp) sig bnp illsig must be +ve chi r1,nsig check range bp illsig too high lr r0,r1 save sig number slls r1,2 et) return(0); if (b == lookfret) { rfail = 1; return(0); } if (b->typ!=2) writes("attempt to transfer to non-label"); return(b->p2); } assign(adr, val) struct node *adr, *val; { register struct node *a, *addr, *value; addr = adr; value = val; if (rfail == 1) { delete(value); return; } switch (addr->typ) { default: writes("attempt to make an illegal assignment"); case 0: addr->typ = 1; case 1: delete(addr->p2); addr->p2 = value; return; case 4: sysput(value); returnSnobol 3 interpreter - see SNO(VI) t nwords; register char **p, **q; register char **t; nwords = (nbytes+(2*sizeof(p)-1))/sizeof(p); for(p=allocp;;) { do { if((p->word&BUSY)==0) { /* combine adjancent free blocks */ while(((q = *p)->word&BUSY)==0) *p = *q; /* q -> end of current free block */ if(q >= &p[nwords]) goto found; } q = p; p = p->word & ~BUSY; } while(q>=allocp || p= '0') { n =* 10; n =+ c - '0'; p++; } return(neg? -n : n); } crt0.s>Wcrt0 title unix c library -- runtime initialization extrn main extrn exit entry _exit r0 equ 0 sp equ 7 rf equ 15 pure * rearrange args on stack & call main routine sis sp,8 l r0,8(sp) routines argument */ static getbit(){ /* static i,j; */ int b; b = (key[bitj] >> biti) & 1; if (biti++ > 5) { bitj++; biti = 0; } return (b); } crypt(inkey) char *inkey; { static char word[9]; char *ip, *jp; int temp; int random; int i,j; int precious; int cage[27]; int ii; biti = 0; bitj = 0; wheel1 = warr1; wheel2 = warr2; wheel3 = warr3; wheel4 = warr4; wheel5 = warr5; wheel6 = warr6; /* copy input key and pad with clever junk */ jp = key; *jp++ = 004; offset in sig table l r5,sigtab-adc(r1) previous value * * if func is nonzero and even, it's a function address * l r2,adc(sp) func st r2,sigtab-adc(r1) set into sig table bz nofunc zero - not an address lis r3,1 check low bit nr r3,r2 bnz nofunc odd - not an address * * replace function by branch table address so regs can be saved * lr r3,r1 signo * 4 slls r3,2 offset in branch table la r2,brtab-16(r3) branch table address nofunc equ * * * call signal svc * st r0,svc.no set signal number cc -s -o sno sno?.c if(t!=alloct+1) /* only on 1st storage request */ alloct->word =| BUSY; alloct = (*t = &t[BLOK]-1); *alloct = allocs; alloct->word =| BUSY; } found: allocp = &p[nwords]; if(q>allocp) *allocp = *p; /*ie if only part of a free block reqd*/ *p = allocp.word|BUSY; return(p+1); } free(p) char **p; { allocp = p-1; allocp->word =& ~BUSY; /* set pointer not busy */ } oatof.ci_/* * Quick-and-dirty floating-poi scanner: * converts a string of digits with optional sign, dec st r0,0(sp) la r0,12(sp) st r0,4(sp) bal rf,main * if main routine returns, exit st r0,0(sp) bal rf,exit * _exit equ * l r0,0(sp) svc 14,1 end =crypt.c U/* This routine is an exact implementation of Boris Hagelin's cryptographic machine. See U. S. Patent #2,089,603. */ static int cagetable[] { 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 8, 8, 9, 10, 12, 16, 16, 17, 18, 20, 24, 32, 32, 33, 34, 36, 40, 48}; static int warr1[52]; static int warr2[50]; static int warr3[46]; static int warr4[42 *jp++ = 034; while (*jp++ = *inkey++); jp--; ip = key; while (jp < key+128) { *jp = jp[-1] ^ *ip++; jp++; } /* manufacture six wheels of various length */ setup(wheel1,26); setup(wheel2,25); setup(wheel3,23); setup(wheel4,21); setup(wheel5,19); setup(wheel6,17); /* set up the cage bars from the key area */ jp = key; i = 27; while (i--){ cage[i] = cagetable[*jp++ % 28]; } /* the internal settings are now complete it's time to turn the crank, running the cage bars against the whest r2,svc.fn set function address svc 14,0 * signal * dc a(svcsig) bc sigerr carry bit -- error * * return previous signal value * lis r3,1 check low bit nr r3,r0 bnzr rf odd - signal previously ignored lr r0,r5 return actual func address br rf * * error exits * illsig equ * lhi r0,einval invalid argument sigerr equ * st r0,errno set error number lcs r0,1 error return br rf * * branch table -- save regs & transfer to actual function address * note: entries must be 16 bytes long! * * align adc brtab equ * nsig entries shi sp,16*adc stm r0,0(sp) lhi r1,0*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,1*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,2*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,3*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,4*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,5*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,6*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,7*ad like Michigan "daylight" must * be initialized to 0 to prevent the conversion * to daylight time. * There is a table which accounts for the peculiarities * undergone by daylight time in 1974-1975. * * The routine does not work * in Saudi Arabia which runs on Solar time. * * asctime(tvec)) * where tvec is produced by localtime * returns a ptr to a character string * that has the ascii time in the form * Thu Jan 01 00:00:00 1970n0\\ * 01234567890123456789012345 * 0 1 2 * * ctime(t) jer the day. */ static sunday(at, ad) int *at; { register int *t, d; t = at; d = ad; if (d >= 58) d =+ dysize(t[YEAR]) - 365; return(d - (d - t[YDAY] + t[WDAY] + 700) % 7); } gmtime(tim) int tim[]; { register int d0, d1; register *tp; static xtime[9]; extern int ldivr; /* * break initial number into * multiples of 8 hours. * (28800 = 60*60*8) */ d0 = ldiv(tim[0], tim[1], 28800); d1 = ldivr; tp = &xtime[0]; /* * generate hours:minutes:seconds */ *tp++ = d1%60; d1 =/ 60; *eger long * pure dpadd equ * l r1,0(sp) ptr to first operand l r0,4(sp) second operand bnm dpa.pos negative ? lcs r2,1 yes - propagate sign bit am r2,0(r1) dpa.pos equ * am r0,4(r1) add to low-order part bncr rf no carry - return lis r0,1 add carry to high-order part am r0,0(r1) br rf end errlst.cchar *sys_errlist[] { "Error 0", "Not super-user", "No such file or directory", "No such process", "Interrupted system call", "I/O error", "No such device or address", "A(fflush(&fout)); } ffopen.c*fopen(file, iobuf) char *file; int *iobuf; { register fd; register int *buf; buf = iobuf; buf[0] = fd = open(file, 0); buf[1] = buf[2] = 0; return( fd < 0? -1 : 0); } ftoa.c?/* * Floating-point to ASCII conversion */ int fltused 0; /* forces loading if floating pt used in C program */ ftoa (x, str, prec, format) float x; char *str; { /* converts a floating point number to an ascii string */ /* x is stored into str, which shoul+ '0'; ie = ie%k; } } *str = '\0'; return; } egetc.cߣ#include "iobuf.h" getc(iobuf) struct iobuf *iobuf; /* buffered input: -get a character from the user's buffer -if the buffer is empty, read the next record -returns the character, or -1 for error or end-of-file */ { register struct iobuf *io; register char c; io = iobuf; if (--io->left < 0) { io->left = c = read(io->fildes, io->buff, BLKSIZE)-1; if (c < 0) return(-1); io->next = io->buff; } c(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,8*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,9*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,10*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,11*adc(0) b callfunc(0) * shi sp,16*adc stm r0,0(sp) lhi r1,12*adc(0) * * call c function * callfunc equ * l r0,18*adc(sp) previous sp value st r0,sp*adc(sp) save it l r1,sigtab(r1) function address bal rf,0(r1) call function l r0,sp*adc(sp) possibly chaust calls localtime, then asctime. */ char cbuf[26]; int dmsize[12] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int timezone -8*60*60; /*** Australian EST ***/ int tzname[] { "EST", "EDT", }; int daylight 0; /* No daylight conversion */ /* * The following table is used for 1974 and 1975 and * gives the day number of the first day after the Sunday of the * change. */ static struct { int daylb; int dayle; } daytab[] { 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ 58, 303, /* 19tp++ = d1%60; d1 =/ 60; d1 =+ (d0%3)*8; d0 =/ 3; *tp++ = d1; /* * d0 is the day number. * generate day of the week. */ xtime[WDAY] = (d0+4)%7; /* * year number */ for(d1=70; d0 >= dysize(d1); d1++) d0 =- dysize(d1); xtime[YEAR] = d1; xtime[YDAY] = d0; /* * generate month */ if (dysize(d1)==366) dmsize[1] = 29; for(d1=0; d0 >= dmsize[d1]; d1++) d0 =- dmsize[d1]; dmsize[1] = 28; *tp++ = d0+1; *tp++ = d1; xtime[ISDAY] = 0; return(xtime); } static asctime(t) int *t; {rg list too long", "Exec format error", "Bad file number", "No children", "No more processes", "Not enough core", "Permission denied", "Error 14", "Block device required", "Mount device busy", "File exists", "Cross-device link", "No such device", "Not a directory", "Is a directory", "Invalid argument", "File table overflow", "Too many open files", "Not a typewriter", "Text file busy", "File too large", "No space left on device", "Illegal seek", "Read-only file system", "Too many linkd be at least 30 chars long */ int ie, i, k, ndig, fstyle; double y; ndig= ( prec<=0) ? 7 : (prec > 22 ? 23 : prec+1); if (format == 'f' || format == 'F') fstyle = 1; else fstyle = 0; /* print in eformat unless last arg is 'f' */ ie = 0; /* if x negative, write minus and reverse */ if ( x < 0) { *str++ = '-'; x = -x; } /* put x in range 1 <= x < 10 */ if (x > 0.0) while (x < 1.0) { x =* 10.0; ie--; } while (x >= 10.0) { x = x/10.0; ie++; } /* in f format, number return(*io->next++); } ygetchr.ck#include "iobuf.h" struct iobuf fin; getchar() { register char c; return((c=getc(&fin))<0 ? 0 : c); } bgetpw.c⸆fgetpw(uid, buf) int uid; char buf[]; { static pbuf[131]; /***/ static pwf; register n, c; register char *bp; if(pwf == 0) pwf = open("/etc/passwd", 0); if(pwf < 0) return(1); seek(pwf, 0, 0); pbuf[0] = pwf; pbuf[1] = 0; pbuf[2] = 0; uid =& 0377; for (;;) { bp = buf; while((c=getc(pbuf)) != '\n') { nged sp value st r0,18*adc(sp) restore it st sp,sp*adc(sp) lm r0,0(sp) restore regs ahi sp,16*adc pop stack * * return from interrupt * svc 14,48 * signal 0 * dc 0 impur * * signal svc * svcsig equ * svc 14,48 * signal * svc.no dc 0 signal number svc.fn dc 0 function address * * sig table - func value for each signal * sigtab equ * do nsig dc 0 errno comn das 1 ends end lctime.cxC# /* * This routine converts time as follows. * The epoch is 0000 Jan 1 1970 GMT. * The a75: Last Sun. in Feb - last Sun in Oct */ }; #define SEC 0 #define MIN 1 #define HOUR 2 #define MDAY 3 #define MON 4 #define YEAR 5 #define WDAY 6 #define YDAY 7 #define ISDAY 8 ctime(at) int *at; { return(asctime(localtime(at))); } localtime(tim) int tim[]; { register int *t, *ct, dayno; int daylbegin, daylend; int copyt[2]; t = copyt; t[0] = tim[0]; t[1] = tim[1]; dpadd(t, -timezone); ct = gmtime(t); dayno = ct[YDAY]; daylbegin = 119; /* last Sun in Apr */ daylend = 303; /* Last Sun in Oc register char *cp, *ncp; register int *tp; cp = cbuf; for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;); ncp = &"SunMonTueWedThuFriSat"[3*t[6]]; cp = cbuf; *cp++ = *ncp++; *cp++ = *ncp++; *cp++ = *ncp++; cp++; tp = &t[4]; ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3]; *cp++ = *ncp++; *cp++ = *ncp++; *cp++ = *ncp++; cp = ct_numb(cp, *--tp); cp = ct_numb(cp, *--tp+100); cp = ct_numb(cp, *--tp+100); cp = ct_numb(cp, *--tp+100); cp =+ 2; cp = ct_numb(cp, t[YEAR]); returns", "Broken Pipe", }; int sys_nerr { sizeof sys_errlist/sizeof sys_errlist[0] }; exit.s$Xzexit title unix c svc library -- exit entry exit extrn _exit pure * go to real exit (in crt0) exit equ * b _exit end fcreat.cߢ#include "iobuf.h" fcreat(filename, iobuf) struct iobuf *iobuf; { register fd; if ((fd=creat(filename, 0666)) >= 0) { iobuf->fildes = fd; iobuf->left = iobuf->next = 0; } return(fd); } fflush.c߆3struct iobuf { int fd; i of digits is related to size */ if (fstyle) ndig =+ ie; /* round. x is between 1 and 10 and ndig will be printed to right of decimal point so rounding is ... */ for (y = i = 1; i < ndig; i++) y = y/10.; x =+ y/2.; if (x >= 10.0) {x = 1.0; ie++;} /* repair rounding disasters */ /* now loop. put out a digit (obtain by multiplying by 10, truncating, subtracting) until enough digits out */ /* if fstyle, and leading zeros, they go out special */ if (fstyle && ie<0) { *str++ = '0'; *str++ = if(c <= 0) return(1); *bp++ = c; } *bp++ = '\0'; bp = buf; n = 3; while(--n) while((c = *bp++) != ':') if(c == '\n') return(1); while((c = *bp++) != ':') { if(c<'0' || c>'9') continue; n = n*10+c-'0'; } if(n == uid) return(0); } return(1); } getw.cstruct { char byte[]; }; getw(buf) { int word; register i; for (i=0; idaylbegin || (dayno==daylbegin && ct[HOUR]>=2)) && (dayno=10) *cp++ = (n/10)%10 + '0'; else *cp++ = ' '; *cp++ = n%10 + '0'; return(cp); } tdpadd.s. title unix double-precision integer arithmetic subroutines r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 sp equ 7 re equ 14 rf equ 15 entry dpadd * * dpadd(long, addend) * int long[2], addend; * * - add integer addend to double-intnt left; char *next; char buff[512]; }; fflush(buf) struct iobuf *buf; { register struct iobuf *bp; register len; bp = buf; if ((len = bp->next - bp->buff) > 0 && bp->left >= 0) write(bp->fd, bp->buff, len); bp->next = bp->left = 0; } fftoa.c/* * Fake version of ftoa for programs with no floating pt */ ftoa(x, str, prec, format) float x; char *str; { str[0] = '?'; str[1] = '\0'; } flush.cߢS#include "iobuf.h" extern struct iobuf fout; flush() { return '.'; if (ndig < 0) ie = ie-ndig; /* limit zeros if underflow */ for (i = -1; i > ie; i--) *str++ = '0'; } for (i=0; i < ndig; i++) { k = x; *str++ = k + '0'; if (i == (fstyle ? ie : 0)) /* where is decimal point */ *str++ = '.'; x =- (y=k); x =* 10.0; } /* now, in estyle, put out exponent if not zero */ if (!fstyle && ie!= 0) { *str++ = 'E'; if (ie < 0) { ie = -ie; *str++ = '-'; } for (k=100; k > ie; k =/10); for (; k >0; k =/10) { *str++ = ie/k INTs * * On the X/32 this returns the second int, since LONGs are one word */ long itol(arg) union { long larg; int iarg[2]; } arg; { return(arg.iarg[1]); } ldiv.sldiv prog unix c library -- double-integer division entry ldiv entry ldivr r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 sp equ 7 re equ 14 rf equ 15 * * ldiv (hidividend, lodividend, divisor) * * - divide double integer dividend by signed divisor * pure ldiv equ * l r0,0(sp) high order dividend l r1,adc(sp) low order dividend d r0,2*adc(sp) divide st r0,ldivr save remainder lr r0,r1 return quotient br rf * * remainder from long division * ldivr comn das 1 ends end lrem.sBlrem prog unix c library -- double-integer remainder entry lrem r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 r5 equ 5 r6 equ 6 sp equ 7 re equ 14 rf equ 15 * * lrem (hidividend, lodividend, divisor) * * - divide double integer dividend by signed divisor * - return remainder * pure lrem equ * l r0,0(sis function st r0,countbase st rf,0(r2) set back pointer to function ais r2,4 st r2,0(r1) set forward pointer to count buffer entry mc1 equ * lis r0,1 am r0,0(r2) br rf end tmcrt0.smcrt0 title unix c library -- runtime initialization with monitor entry _exit extrn exit entry countbas extrn main extrn etext,sbrk,monitor * r0 equ 0 r1 equ 1 r2 equ 2 sp equ 7 rf equ 15 * write equ 4 write svc cbufs equ 100 no. of words in call-count buffer * countbas dc 0 next available call-c6); write(o, sbuf, ssiz*(sizeof *sbuf)); close(o); return; } /*** if (nargs() <= 4) cntsiz = 0; ***/ ssiz = bufsiz; buf[0] = lowpc; buf[1] = highpc; buf[2] = cntsiz; sbuf = buf; buf =+ 2*cntsiz + 3; bufsiz =- (2*cntsiz + 3); if (bufsiz<=0) return; o = (highpc - lowpc)/(sizeof *buf); if(bufsiz < o) o = ldiv(bufsiz, 0, (o<<1)); else o = 0x7fffffff; profil(buf, bufsiz*(sizeof *buf), lowpc, o<<1); } perror.cperror(mesg) char *mesg; { extern errno, sys_nerr; extertatic char prfhex[] { "0123456789ABCDEF" }; /* Hexadecimal digits */ static prf1(fmt, arg, left) { register int x, len, c; register char *p, *lastc; static char buff[32]; /* Initialize pointers to first & last+1 char in buffer. */ x = arg; lastc = p = &buff[32]; switch (fmt) { /* Unknown character: just print the format char. */ default: *--p = fmt; fmt = -1; break; /* Single character */ case 'c': case 'C': if (x) *--p = x; break; /* String: set pointers to first & last+1 ch ch = c; if (--io->left < 0) { if (io->next) { len = write(io->fildes, io->buff, io->next-io->buff); if (len <= 0) return(-1); } io->next = io->buff; io->left = BLKSIZE-1; } *io->next++ = ch; return(c); } putchr.cj#include "iobuf.h" struct iobuf fout { 1 /* standard output file */ }; putchar(ch) { char c; /* * if standard output <= 2, output is character-by-character. * otherwise it is buffered using the standard iobuf 'fout'. */ if (fout.fildes <= 2) ; n = qses; ri = i; rj = j; rk = k; do { c = *ri; *ri++ = *rk; *rk++ = *rj; *rj++ = c; } while(--n); } reset.sQreset prog c library -- setexit and reset entry reset,setexit * * setexit() * * - saves current status of stack & registers * * reset() * * - restores saved status, simulating a return from the most * recent setexit() * r0 equ 0 sp equ 7 rf equ 15 pure setexit equ * stm sp,saveregs save current regs lis r0,0 clear ret code br rf * reset equ * lm sp,saveregs p) high order dividend l r1,adc(sp) low order dividend d r0,2*adc(sp) divide br rf remainder is in r0 end tlsub.sKulsub title unix c svc library -- double-integer subtract * * lsub(remainder, subtrahend, minuend) * long *remainder, *subtrahend, *minuend; * entry lsub r0 equ 0 r1 equ 1 r2 equ 2 r3 equ 3 r4 equ 4 sp equ 7 rf equ 15 * lsub equ * l r1,0(sp) &remainder l r2,adc(sp) &subtrahend l r3,2*adc(sp) &minuend * lis r4,0 clear carry l r0,adc(r2) low-order sub s r0,adc(r3) ount buffer entry * pure start equ * * rearrange args on stack sis sp,8 l r0,8(sp) st r0,0(sp) la r0,12(sp) st r0,4(sp) * profile buffer size = program text size / 4 la r1,etext si r1,eprol ais r1,15 srls r1,4 * get storage for profile buffer shi sp,5*adc lhi r2,cbufs st r2,4*adc(sp) slls r2,1 ais r2,3 ar r1,r2 st r1,3*adc(sp) slls r1,2 st r1,0(sp) bal rf,sbrk chi r0,-1 be nocore * start profiling st r0,2*adc(sp) ais r0,3*adc st r0,countbas la r0,etext st r0,1*adc(sp) la r0,eproln char *sys_errlist[]; printf("%s: ", mesg); if (errno > sys_nerr) printf("%d error\n", errno); else printf("%s\n", sys_errlist[errno]); } (printf.cm /* * Printf: * Print formatted data to standard output file. * For external description, see man(iii). * */ static int prfwidth, prfprec; /* Width & precision */ printf(afmt, args) char *afmt; { register char *fmt; register int *argp, left, c, n; /* * argp is used to step along list of arguments, since * the number ofar. */ case 's': case 'S': p = lastc = x; while (*lastc) lastc++; break; /* Octal */ case 'o': case 'O': do *--p = (x & 07) + '0'; while (x =>> 3); break; /* Hexadecimal */ case 'x': case 'X': do *--p = prfhex[x & 017]; while (x =>> 4); break; /* Signed decimal */ case 'd': case 'D': if (x < 0) x = -arg; /* Unsigned decimal */ case 'l': case 'L': do *--p = ((unsigned)x % 10) + '0'; while ((unsigned)x =/ 10); if (arg < 0 && (fmt == 'd' || fmt == 'D')) { if (c = ch&0377) write (fout.fildes, &c, 1); return(c); } return((c=putc(ch, &fout))<0 ? 0 : c); } putw.c;struct { char byte[]; }; putw(word, buf) { register i; for (i=0; i= '0') { n =* 10; n =+ c - '0'; fmt++; } prfwidth = n; /* Convert p*--p = '-'; break; /* Floating point */ case 'f': case 'F': case 'e': case 'E': p = lastc = buff; ftoa(x, p, prfprec, fmt); while (*lastc) lastc++; prfprec = 0; break; } /* Compute len = -(no. of pad chars needed to fill width) */ len = lastc - p; if (prfprec && len > prfprec) { len = prfprec; lastc = p + len; } len =- prfwidth; /* Pad to left if right-justified */ if (!left) while (len++ < 0) putchar(' '); /* * Print converted string -- terminated by lastc. */ int n, c; es = qses; start: if((n=l-a) <= es) return; n = ((n/(2*es))*es) & 077777; hp = lp = a+n; i = a; j = l-es; for(;;) { if(i < lp) { if((c = (*qscmp)(i, lp)) == 0) { qsexc(i, lp =- es); continue; } if(c < 0) { i =+ es; continue; } } loop: if(j > hp) { if((c = (*qscmp)(hp, j)) == 0) { qsexc(hp =+ es, j); goto loop; } if(c > 0) { if(i == lp) { qstexc(i, hp =+ es, j); i = lp =+ es; goto loop; } qsexc(i, j); 18]; register inode, dir; register char *p; if (fstat(fd, buf) < 0 || (dir = open("/dev", 0)) < 0) return('x'); inode = buf[1]; while (read(dir, buf, 16) == 16) { p = buf; if ((p[0]<<8) + p[1] == inode && p[2] == 't' && p[3] == 't' && p[4] == 'y' && p[5] != '\0' && p[6] == '\0') return(p[5]); } return('x'); } qunt buffer * each count buffer entry is two words: a pointer to the function entry * point (actually pointing after the 'bal' to mcount, and initialized * at the first call of mcount), and the count of calls entry mcount r0 equ 0 r1 equ 1 r2 equ 2 rf equ 15 countbase comn next available count buffer entry das 1 ends mcount equ * l r2,0(r1) pointer to count buffer entry bnz mc1 skip if already initialized l r2,countbase bzr rf no buffer - give up lr r0,r2 ais r0,8 allocate buffer entry for thmktemp(name) char *name; { int stbuf[18]; register char *p; register n, c; for (p = name; *p; p++) ; n = getpid(); while ((c = *--p) == 'X') { *p = (n&07)+'0'; n =>> 3; } while (stat(name, stbuf) >= 0) { if (c >= 'z') return(-1); *p = ++c; } return(name); } mon.cklmonitor(lowpc, highpc, buf, bufsiz, cntsiz) char *lowpc, *highpc; int *buf, bufsiz; { register char *o; static *sbuf, ssiz; if (lowpc == 0) { profil(0, 0, 0, 0); o = creat("mon.out", 066recision field if present. */ n = 0; if (c == '.') while ((c = *++fmt) <= '9' && c >= '0') { n =* 10; n =+ c - '0'; } prfprec = n; /* * Print the argument in the requested format. * If prf1() returns <0, an unknown character followed * the '%', so the argument was not used. Otherwise, * step to the next argument. */ if (prf1(c, *argp, left) >= 0) argp++; } } /* * Print a single argument according to the given format character. * Left-justify if left == 1. */ swhile (p < lastc) putchar(*p++); /* Pad to right if left-justified */ while (len++ < 0) putchar(' '); /* Returned value >=0 asks printf to step to next argument. */ return(fmt); } putc.cߣ #include "iobuf.h" putc(c, iobuf) struct iobuf *iobuf; /* buffered output: -put a character into the user's buffer -if the buffer is full, write the record -returns the argument character, or -1 for error */ { register struct iobuf *io; register char ch, len; io = iobuf; j =- es; i =+ es; continue; } j =- es; goto loop; } if(i == lp) { if(lp-a >= l-hp) { qs1(hp+es, l); l = lp; } else { qs1(a, lp); a = hp+es; } goto start; } qstexc(j, lp =- es, i); j = hp =- es; } } static qsexc(i, j) char *i, *j; { register char *ri, *rj, c; int n; n = qses; ri = i; rj = j; do { c = *ri; *ri++ = *rj; *rj++ = c; } while(--n); } static qstexc(i, j, k) char *i, *j, *k; { register char *ri, *rj, *rk; char c; int n#define BLKSIZE 512 struct iobuf { int fildes; int left; char *next; char buff[BLKSIZE]; }; C subroutine library src.a - source for /lib/libc.a routines csignal.s - version of signal() which allows function to return to point of interruption. If signal function doesn't need to return, use smaller signal() in liba.a rti.s - "equivalent" of pdp-11 rti instruction - pops psw status, location counter & stack pointer off stack (see sig.c) - used only by OS SVC interpreter iobuf.h - declaration of i/o buffer used by getc, putc ne DIRSIZE 16 #ifdef AGSM #define NMSIZE 48 #else #define NMSIZE 32 #endif #define tapeblk tpentry #define tapeb tpentry EXTERN struct tent { /* Structure of a tape directory block */ char pathnam[NMSIZE]; char mode[2]; char uid; char gid; char spare; char size0; char size1[2]; char time0[2]; char time1[2]; char tapea[2]; /* tape address */ #ifndef AGSM char unused[16]; #endif char cksum[2]; } tpentry[8]; EXTERN struct dent { /* in core version of tent with "unused" removed * and pathna# /* Dynamic Debugging Tool Bill Allen Naval Postgraduate School March, 1975 Revised for UNIX version 6 October, 1975 Revised for Interdata UNIX, 1977 R Miller University of Wollongong */ #include "/usr/sys/param.h" #include "/usr/sys/user.h" #include "/usr/sys/reg.h" extern pinstr(); int regloc[] { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, RPC, RPS }; struct sfregs { int junk[2]; float sfr[8]; }; struct lfregs { int junk[2]; doudress */ extern getspsym(); extern putspsym(); extern ssval[]; extern char *ssname[]; extern initssv(); #define RUSER 1 #define RIUSER 2 #define WUSER 4 #define RUREGS 3 #define WUREGS 6 #define SETTRC 0 #define CONTIN 7 #define EXIT 8 #define SSR0 0 #define SSR1 1 #define SSR2 2 #define SSR3 3 #define SSR4 4 #define SSR5 5 #define SSR6 6 #define SSR7 7 #define SSR8 8 #define SSR9 9 #define SSR10 10 #define SSR11 11 #define SSR12 12 #define SSR13 13 #define SSR14 14 #define SSR15 15 #define SSSP 7 #defi:@FL;AGMBHN=CIOPV\bQW]cRX^dSY_eT 'e': /* double precision floating point */ printf("%e\t", w); dotinc = sizeof(double); return; case 'i': /* instruction in assembler format */ leffect = 0; pinstr(); /* print instruction symbolically */ return; case '&': c = ssval[SSL]; /* save low symbol address */ ssval[SSL] = 0; /* use all symbols */ psym(w); /* print as symbol and offset */ ssval[SSL] = c; if (errflg) reset(); putchar('\t'); dotinc = sizeof(int *); return; case 'b': /* byte in octaar x src.a cc -c *.[cs] stripsym *.o me replaced by pointer to same in a * packed area (nameblock). */ char *d_namep; int d_mode; char d_uid; char d_gid; char d_spare; char d_size0; int d_size1; int d_time[2]; int d_tapea; } dir[MDIRENT]; EXTERN struct { int s_skip[2]; int s_flags; char s_nlinks; char s_uid; char s_gid; char s_size0; int s_size1; int s_addr[8]; int s_active[2]; int s_modtime[2]; } statb; /* */ EXTERN char map[4096]; EXTERN char catlb[16]; EXTERN char name[NMSIZE]; EXTERN char name1[NMSIZE]; externble lfr[8]; }; extern int locsr5; char *sbrk(); char *symbuf; int *symptr; int fcore -1; int fsym -1; int wcore -1; int wsym -1; int fdout; char *gargv[10]; int pid; int coroffset; int symoff; char *lp; int errflg; int symlen; int symct; char symbol[8]; int symflg; int symval; char ssymbol[8]; int ssymflg; int ssymval; char line[128]; int regbuf[512]; char **uregs; char *rtsize; int dot; int tdot; int dotinc sizeof(int); int lastcom '/'; int lastype 'i'; char *symfil "a.out"; char *corfil "core"; int calline SSPC 16 #define SSPS 17 #define SS8 18 #define SS9 19 #define SSL 20 #define SSM 21 #define SSQ 22 #define SSA 23 #define SSD 24 #define SSRG 25 main(argc, argv) char **argv; { int onintr(); int endit(); register cpid, rpid; int cstatus; gargc = argc; if(gargc > 1) symfil = argv[1]; if(gargc > 2) corfil = argv[2]; if((fsym = open(symfil,0))<0) { printf("Unable to open %s\n",symfil); exit(); } wsym = open(symfil,1); if(gargc != 2) { /* try for core file */ fcore = open(corfil,0); h","-t",0); exit(); } while((rpid=wait(&cstatus)) != cpid && rpid != -1); printf("!\n"); goto loop; } if (*lp++ == '\0') endit(); } lp = line; command(); goto loop; } command() { register n; adrfg = expr(); if (errflg) return; n = getcnt(); if (lastcom=='$') lastcom = '/'; if (*lp == '\n') { lastcom = '/'; if (!adrfg) dot =+ dotinc; } else lastcom = *lp++; if (adrfg) { ldot = dot; dot = tdot; } while(n) { scommand(n); if (*lp != '\n') { printf(l */ printf("%3o\t", xch(w, dot)); dotinc = 1; return; case '\'': /* byte in ASCII */ printc(xch(w, dot)); dotinc = 1; putchar('\t'); return; case '"': /* halfword in ASCII */ printc((w>>24)&0377); /***/ printc((w>>16)&0377); dotinc = 2; putchar('\t'); return; case 's': /* string in ASCII */ w = dot; while(c = xch(cget(w), w)) { printc(c); w++; } putchar('\t'); dotinc = w-dot+1; return; } printf("** unrecognized display mode\n"); cpall crt0.o mcrt0.o /lib ar ru /lib/libc.a rm *.o rm *.[cs] char tc[] ; extern char mt[] ; EXTERN int narg, rnarg; EXTERN char **parg; EXTERN int wseeka,rseeka; EXTERN int tapsiz; EXTERN int fio; EXTERN int ndirent, ndentd8; EXTERN char *edir; EXTERN struct dent *lastd; /* for improvement */ EXTERN int (*command)(); EXTERN char *nameblk; EXTERN char *top; EXTERN char *nptr; EXTERN int flags ; /* default is flu */ #define flc 0001 #define flf 0002 #define fli 0004 #define flm 0010 #define flu 0020 #define flv 0040 #define flw 0100 /* * PDP-11 arse-backwardsst[50]; int *callp callist; int leffect; /* last effective address */ int headsize; /* length of file header */ int tsize; /* length of text segment */ int dsize; /* length of data segment */ int ssize; /* length of bss segment */ int gargc; /* number of arguments from shell */ int sdot; /* symbolic operand temporary dot */ int ldot; int elastype 'o'; /* = display mode */ int signo; /* signal type */ int adrfg; /* set if this command had an address */ int status; #define BREAK 3 /* system call breakwcore = open(corfil,1); } initfsym(); /* init symbolic file sizes */ if((symbuf=sbrk(symlen+4)) == -1) { /***/ printf("Symbol table too large\n"); exit(); } symbuf =& ~03; /* word address */ seek(fsym,symoff,0); if(read(fsym,symbuf,symlen) != symlen) printf("Can't read symbol table\n"); if(fcore>=0 && gargc<=3) /* have a core file */ initfcor(); /* initialize the known symbols */ if(gargc>3) /* file is not a core image */ headsize = 0; initssv(); /* set default special symbol values"** unrecognized command or argument\n"); return; } if (--n){ dot =+ dotinc; putchar('\n'); } } } scommand(n) { register char *p1; register w, c; double fw; struct { int i[4]; }; if(lastcom == '>') { /* follow the path */ dot = leffect; lastcom = '/'; } switch(lastcom) { case '/': psym(dot); /* print address symbolically */ putchar('\t'); w = cget(dot); ssval[SSQ] = w; /* set :q */ leffect = w; /* set default last effective address */ if(*lp != '\n') lastype return; case '=': ssval[SSQ] = tdot; /* set :q value */ dot = ldot; /* restore dot */ lastcom = '/'; /* this was an aside */ if(*lp != '\n') elastype = *lp++; switch(elastype){ /* display mode */ case 'o': /* word octal */ printf("%11o\t",tdot); return; case 'x': /* word hexidecimal */ printf("%8x\t",tdot); return; case 'd': /* word decimal */ printf("%d\t",tdot); return; case 'l': /* word unsigned decimal */ printf("%l\t",tdot); return; case 'b': /* b/* c-version of tp?.s * * M. Ferentz * August 1976 * * Quick & dirty emergency version for Interdata * * Major changes: * - arse-backwards 16-bit integers for PDP-11 compatibility * - 'o' flag: output goes to filename given by next argument * (since Wollongong is too poor to afford a tape drive) * R. Miller * Dec 1977 * For Ian Johnson's AGSM version (48-char pathnames), define * the preprocessor variable: * #define AGSM 0 */ #define MDIRENT 496 /* must be zero mod 8 */ #defi integers */ #define rab(from) (from[1]<<8)|from[0] #define wab(to, from) to[0] = from&0377; to[1] = from>>8; #define NCPW 4 point */ #define BRKLEN 20 #define CONDLEN 82 struct { int value; /* old value of breakpoint */ int addr; /* address of breakpoint */ char cond[CONDLEN]; /* breakpoint condition */ } brktab[BRKLEN]; int brktx -1; /* breakpoint table index */ char *signals[] { "", "Hangup", "Interrupt", "Quit", "Illegal instruction", "Trace/BTP", "IOT", "EMT", "Floating exception", "Killed", "Bus error", "Memory fault", "Bad system call", "", "", "", }; extern int tempbra[]; /* temporary breakpoint ad */ for(dot=0; dot0 && gargc <= 3) setstack(); setexit(); signal(2, onintr); /* rubout */ signal(1,endit); /* hangup (EOT) */ putchar('\n'); /* ready to go */ loop: if (errflg) { printf("?\t"); errflg = 0; } lp = line; while ((*lp = getchar()) != '\n') { if(lp==line && *lp=='!'){ /* call the shell */ if((cpid=fork()) == 0) { execl("/bin/sh","s= *lp++; switch(lastype) { case 'o': /* word octal */ printf("%11o\t", w); dotinc = sizeof(int); return; case 'x': /* word hexidecmal */ printf("%8x\t", w); dotinc = sizeof(int); return; case 'd': /* word decimal */ printf("%d\t", w); dotinc = sizeof(int); return; case 'l': /* word unsigned decimal */ printf("%l\t", w); dotinc = sizeof(unsigned int); return; case 'f': /* floating point */ printf("%e\t", w); dotinc = sizeof(float); return; caseyte decimal */ printf("%3o\t",tdot&0377); return; case '&': /* address */ c = ssval[SSL]; /* save low symbol address */ ssval[SSL] = 0; /* use all symbols */ psym(tdot); /* print as symbol and offset */ ssval[SSL] = c; if (errflg) reset(); putchar('\t'); return; case '\'': /* byte ASCII */ putchar(tdot&0377); putchar('\t'); return; case '"': /* word ASCII */ putchar(tdot>>8); putchar(tdot&0377); putchar('\t'); return; } printf("** unrecognized display mode\n"); return; case '!': /* patch the file */ if(!adrfg){ /* no value to store */ printf("** no address for store\n"); return; } dot = ldot; /* reset dot */ if(*lp == ':'){ /* store value in special symbol */ lp++; putspsym(tdot); /* set sp symbol to value in tdot */ return; } cfput(tdot); /* put tdot in file at address dot */ return; case '$': prtermst(); /* print termination status */ printtrace(); return; case '?': /* display termination statu/* repetition factor */ else w = 1; while(w--){ /* one instruction each time */ stempbpt(0); /* set temp brkpt */ restcore(); ptrace(CONTIN,pid,0,0); bpwait(); rtempbpt(); dot = ssval[SSPC]; scommand(1); /* print the instruction */ if(w) putchar('\n'); } return; case '.': /* set temp bpt and continue */ if(adrfg==0) { printf("*** no address specified\n"); return; } w = dot; setbpt(w); /* set breakpoint */ proceed(); /* ;p */ clbk = lp; while(*lp != '\n') lp++; *lp = '\0'; /* end of string */ if((fdout=creat(p1,0777))<0){ printf("**unable to open output file %s\n",line); return; } if(fcore>0) { w = (headsize+tsize+dsize+ssize+511)/512; seek(fcore,coroffset,3); while(w--) { read(fcore,regbuf,512); write(fdout,regbuf,512); } close(fdout); initfcor(); putchar('\n'); *lp = '\n'; return; } printf("**no core file to copy\n"); return; } } printf("** un if (adr & 03) cfput((old&0xffff0000) | BREAK); else cfput((BREAK<<16) | (old&0xffff)); if(errflg){ printf("**Unable to set breakpoint\n"); brktab[c].addr = -1; /* no breakpoint */ } getcond(c); /* get breakpoint condition */ dot = ldot; /* reset dot */ return; } if(++brktx > BRKLEN){ /* no more breakpoints */ printf("?? too many breakpoints\n"); return; } c = ++brktx; goto bptstr; } /* proceed from a breakpoint */ proceed() { if(pid<=0) { printf("no prab[idx].cond[i++] = '\n'; brktab[idx].cond[i++] = '\0'; } f breakpoint */ int addr; /* address of breakpoint */ char cond[CONDLEN]; /* breakpoint condition */ } brktab[BRKLEN]; extern int brktx; int symadr; extern getspsym(); extern putspsym(); extern ssval[]; extern char *ssname[]; extern initssv(); #define RUSER 1 #define RIUSER 2 #define WUSER 4 #define RUREGS 3 #define WUREGS 6 #define SETTRC 0 #define CONTIN 7 #define EXIT 8 #define SSR0 0 #define SSR1 1 #define SSR2 2 #define SSR3 3 #define SSR4 4 #define SSR5 5 #define SSR6 6 #define SSR7 7 #define SSs */ prtermst(); return; case '^': /* preceeding cell */ dot =- 4; lastcom = '/'; /* display word value */ scommand(n); return; case ';': /* long command */ lastcom = '/'; /* display */ switch(*lp++){ case 'g': /* begin file execution */ w = 1; /* only once */ if(pid>0){ /* have a child at breakpoint */ ptrace(EXIT,pid,0,0); /* kill old child */ pid = 0; } if(fsym<0) { printf("no symbolic file to execute\n"); return; } gargv[0] = symfil; /* first namept(w); /* clear breakpoint */ dot = ssval[SSPC]; return; case '=': /* search equal */ for(dot=ssval[SS8];dot<=ssval[SS9];dot =+ 4){ if((cget(dot)&(ssval[SSM])) == tdot){ scommand(n); /* display it */ putchar('\n'); } } putchar('\n'); return; case '#': /* search not equal */ for(dot=ssval[SS8];dot<=ssval[SS9];dot =+ 4){ if((cget(dot)&(ssval[SSM])) != tdot){ scommand(n); /* display it */ putchar('\n'); } } putchar('\n'); return; case 'recognized command\n"); } /* * extract even or odd character from word returned by cget */ struct { char byte[]; }; xch(word, addr) { return(word.byte[addr & 01]); } rmcore() { close(fcore); close(wcore); fcore = -1; wcore = -1; initfsym(); } /* test for a valid breakpoint address */ notbpt() { register i,j; j=ssval[SSPC]; for(i=0;i<=brktx; i++) if(brktab[i].addr==j) return(0); for(i=0; i<2; i++) if(tempbra[i]==j) return(0); return(1); /* not valid */ } bpwait() { extern inocess to continue\n"); return; } if(stempbpt(1)) {; /* set temporary breakpoint maybe */ restcore(); /* restore special symbol values */ ptrace(CONTIN,pid,0,0); bpwait(); rtempbpt(); /* remove temporary breakpoints */ /*** ssval[SSPC] =+ 2; /* trapped by T bit ***/ } restcore(); /* reset PC */ ptrace(CONTIN,pid,0,0); connotb(); } /* continue not from breakpoint */ connotb() { bpwait(); if(!condbpt()) { /* conditinal? */ proceed(); return; } if(notbpt()){ /* not valid brea# /* Dynamic Debugging Tool Bill Allen Naval Postgraduate School March, 1975 */ #include "/usr/sys/param.h" #include "/usr/sys/user.h" #include "/usr/sys/reg.h" extern pinstr(); extern prtop(); extern int fcore; extern int fsym; extern int wcore; extern int wsym; extern char *gargv[10]; extern int pid; extern int coroffset; extern int symoff; extern char *lp; extern int errflg; extern int symlen; extern int symct; extern char symbol[8]; extern int symflg; extern int symval; char tsym[10]; chR8 8 #define SSR9 9 #define SSR10 10 #define SSR11 11 #define SSR12 12 #define SSR13 13 #define SSR14 14 #define SSR15 15 #define SSSP 7 #define SSPC 16 #define SSPS 17 #define SS8 18 #define SS9 19 #define SSL 20 #define SSM 21 #define SSQ 22 #define SSA 23 #define SSD 24 #define SSRG 25 #define SSF 26 #define SSSL 27 #define NUMSS 28 /* * instruction formats */ #define SF 1 #define RR 2 #define RX1 3 #define RX2 4 #define RX3 5 #define RI1 6 #define RI2 7 #define BT 010 /* branch instruction (true) */ is file name */ w = 1; loop: while(*lp == ' ') *lp++ = '\0'; if(*lp == '\n') { *lp = '\0'; /* end of string */ gargv[w] = 0; /* end of argument list */ } else { gargv[w++] = lp; /* form argument pointers */ while(*lp != ' ' && *lp != '\n') lp++; /* skip over args */ goto loop; } while((pid = fork())<0); if(pid==0){ /* child */ ptrace(SETTRC,0,0,0); /* expect trace */ signal(SIGINT,0); signal(SIGINS,0); execv(symfil,gargv); /* execute the fileb': /* set breakpoint */ if(adrfg) setbpt(dot); else printf("*** no address specfied\n"); return; case 'c': /* clear a breakpoint */ clbkpt(dot); /* clear it or all */ return; case 'd': /* display breakpoints */ if(brktx<0) goto dout; for(c=0;c<=brktx;c++){ if(brktab[c].addr != -1){ /* valid breakpoint */ psym(brktab[c].addr); /* print breakpoint address */ putchar('\t'); if(brktab[c].cond[0] != '\0') /* print conditional */ printf("%s",brktab[ct onintr(); register w; int stat; loop: signal(SIGINT, 1); while ((w = wait(&stat))!=pid && w != -1); signal(SIGINT, onintr); if (w == -1) { ptrace(EXIT, pid, 0, 0); pid = 0; printf("Wait error\n"); reset(); } if ((stat & 0377) != 0177) { if (signo = stat&0177) printf("%s\n", signals[signo]); printf("Process terminated.\n"); if (pid == w) { pid = 0; reset(); } goto loop; } signo = stat>>8; initfmem(); /*** if (signo!=SIGTRC) { ***/ if (signo!=SIGINS || notbpt()) { pkpoint */ printf("breakpoint error %o\n",ssval[SSPC]); endit(); } dot = ssval[SSPC]; /* location of breakpoint */ lastcom = '/'; /* display */ lastype = 'i'; *lp = '\n'; scommand(1); /* display breakpoint instr */ } printfregs() { register i; double f; if(pid) for(i=2; i<18; i++) regbuf[i] = ptrace(RUREGS,pid,4*i,0); /* read fregs */ for (i=0; i<8; i++) { f = regbuf[0].sfr[i]; printf("fr%d %e\n", i*2, f); } } getchar() { char lastc; if(read(0,&lastc,1) <= 0) return(ar fsymbol[10]; extern char ssymbol[8]; extern int ssymflg; extern int ssymval; extern char line[128]; extern int regbuf[512]; extern char **uregs; extern char *rtsize; int loccsv; int locsr5; extern int regloc[]; extern int dot; extern int tdot; extern int dotinc; extern int lastcom; extern int lastype; extern char *symfil; extern char *corfil; extern int callist[50]; int entpt[50]; int callev; extern int *callp; extern int leffect; extern int headsize; /* length of file header */ extern int tsize; /* len #define BF 020 /* branch instruction (false) */ #define BBACK 040 /* branch backwards short */ /* * structure for information about disassembled instruction */ extern struct { int type; /* instruction format */ char op; /* opcode */ char reg[3]; /* registers */ char *disp; /* displacement */ } instr; getcnt() { register t1, t2; if (*lp != ',') return(1); lp++; t1 = tdot; if (expr() == 0) { tdot = t1; return(1); } t2 = tdot; tdot = t1; return(t2); } cget(n) { register w; /*** */ printf("Can't execute %s\n",symfil); exit(); /* just in case */ } else { /* parent */ if(fcore>=0){ /* core file open */ rmcore(); /* close core files */ } } w = 0; connotb(); return; case 'p': /* proceed from breakpoint */ if(adrfg) w = dot; /* repetition factor */ else w = 1; while(w--) { proceed(); } return; case 's': /* single instruction step */ lastcom = '/'; lastype = 'i'; *lp = '\n'; if(adrfg) w = dot; ].cond); else putchar('\n'); ssval[SSQ] = brktab[c].addr; /* set :q */ } } dout: putchar('\n'); return; case 'r': /* display registers in octal and symbollically */ for(c=0;c<=SSPC;c++){ printf("%s\t%11o\t", ssname[c], ssval[c]); psym(ssval[c]); putchar('\n'); } return; case 'e': /* print floating regs */ printfregs(); return; case 'f': /* stop */ endit(); case 'w': /* write copy of breakpointed pgm */ while(*lp==' ') lp++; p1rintf("%s\n", signals[signo]); reset(); } setstack(); } /* set a breakpoint */ setbpt(adr) { register c, old; adr =& ~01; for(c=0;c<=brktx;c++) if(brktab[c].addr==adr){ /* already got it */ getcond(c); /* may want to change conditional */ return; } for(c=0;c<=brktx;c++) if(brktab[c].addr == -1){ /* not used */ bptstr: /* save old value of word containing breakpoint */ dot = adr & ~03; brktab[c].value = old = cget(dot); brktab[c].addr = adr; /* change half the word */ 0); return(lastc&0177); } /* get the condition for this breakpoint */ getcond(aidx) { register idx,i; idx=aidx; /* breakpoint table index */ if(*lp == '\n') { /* unconditional */ brktab[idx].cond[0] = '\0'; return; } while(*lp == 'b') lp++; /* ignore blanks */ i=0; while(*lp!='\n' && i>8); return(w); ***/ w = get(n & ~01); if (errflg) reset(); return(w); } printc(c) { c =& 0377; /***/ if (c<' ' || c>'}') printf("\\%o", c); else printf("%c", c); } expr() { register int i,t1,t2, b; int donef, adrflg, lastop; symadr=0; tdot = 0; adrflg = 0; lastop = '+'; ssymval = 0; donef = 0; loop: fsymbol[0] = 0; if (symchar(0)) { symadr++; adrflg++; symcollect('_'); if (*lp++==':' && symchar(0)) { for (i=0; i<8; i++) fsymbol[i] = tsym[i]; fsymbol[0] = '~'; symcollect(0); } else lp--; if (symlook(tsym) == 0) { printf("*** symbol not found\n"); reset(); } goto loop; } if (*lp>='0' && *lp<='9') { adrflg++; ssymval = 0; if (*lp == '0') { b = 8; if (*++lp == 'x') { b = 16; lp++; } } else b = 10; for (;;) { if ((i = *lp - '0') > 9) if ((i =- 'a'-'9'-1) < 10) break; if (i >= b || goto op; case '&': tdot =& ssymval; goto op; case '-': tdot =- ssymval; op: if (donef) return(adrflg); else lastop = *lp++; } goto loop; case '\t': lp++; goto loop; case '(': /* function argument */ lp++; adrflg++; t1 = tdot; ssymval = getarg(); tdot = t1; goto loop; case '[': lp++; t1 = ssymval; t2 = tdot; if (expr() == 0) tdot = 0; ssymval = get(t1 + (tdot<<2)); if (errflg) reset(); tdot = t2; if (*lp == ']') lp++; goto lp < &callist[50]) *callp++ = trbase; if ((trbase = get(trbase+24)) == 0) break; } } findroutine(apc, arbase) int *arbase; { register callpt, inst, narg; if (findbase(apc, arbase) == 0 && findbase(ssval[SSR15], arbase) == 0) { errflg++; return(0); } callpt = get(*arbase+28); if ((inst=get(callpt-6)) >> 24 == 0101) /* rx3 */ inst = get(callpt-4) & 03777777; else if (((inst>>8) & 0377) == 0101) { /* rx1, rx2 */ inst = get(callpt-4) & 0177777; if (inst & 0100000) { /* rx2 */ ift()) { /* wait for function symbol */ if (symbol[0]!='~' || !eqstr(symbol, fsymbol)) continue; symv = symval; while (symget()&& symbol[0]!='~' &&symflg!=037) if (eqstr(symbol, symstr)) return(localsym(symv)); return(0); } } localsym(s) { register i, xr5; /* label, static */ if (symflg>=2 && symflg<=4) { ssymval = symval; return(1); } /* auto, arg */ if (symflg==1) { for (i=0; i=t in unsigned */ /* 16 bit addresses using signed 16 bit arithmetic. */ if(value>=0){ if(t>0 && value>=t){ /* true */ value =- t; /* convert to symbol table address */ dflag=0; /* D space symbol */ } } else { /* value<0 */ if(t>=0){ value = (value&077777) + (077777-t) + 1; Z`fU[aghtziou{jpv|kqw}lrx~msyoop; } } symcollect(c) { register char *p; p = tsym; if (c && !ssval[SSA]) *p++ = c; while (symchar(1)) { if (p < &tsym[8]) *p++ = *lp; lp++; } while (p < &tsym[8]) *p++ = 0; } symchar(dig) { if (*lp>='a'&&*lp<='z' || *lp>='A'&&*lp<='Z' || *lp=='_') return(1); if (dig && *lp>='0' && *lp<='9') return(1); return(0); } setstack() { register int tpc, i; int trbase; tpc = ssval[SSPC]; trbase = ssval[SSR14]; callev = 0; while (errflg == 0) { findroutine(tpc, &trbase); tpc = (inst & 040000) inst =| ((-1)<<16); else inst =& 037777; inst =+ callpt; } } else { errflg++; /*** printf("*** unable to set stack\n"); ***/ return(0); } inst = vallook(inst); if (inst) { ssymbol[0] = '?'; ssymbol[1] = 0; ssymval = 0; } inst = get(callpt); if ((inst>>20) == 01147) /* ais sp,x */ return(((inst>>16)&15)/4); if ((inst>>20) == 06247) /* ahi sp,x */ return((inst&0177777)/4); if ((inst>>20) == 07647) /* ai sp,x */ return(get(callpt+2)/4); return(0); } (0); } /* register */ if (symflg==20) { for (i=0; i= &symbol[8]) break; if (c >= 'A' && c <= 'Z') *s = (c =+ 'a'-'A'); } ***/ return(1); } savsym(skip) { register int ch; register char *p, *q; p = symbol; q = ssymbol; if(!ssval[SSA] && (*p==skip || (skip=='_' && *p=='~'))) p++; while (p=t){ /* both are negative */ value = (value&077777) - (t&077777); dflag = 0; } } } if(value<0 && value>=ssval[SSSL]) /* on the stack */ return(closeloc(value)); /* local symbol */ tcval=ssval[SSRG]; /* set close symbol range */ symset(); /* beginning of symbol table */ while(symget()) { t = symflg&037; /* symbol type */ if(t != 037 && (t!=1 || ssval[SSA])){ /* no file names not abs or assmebly */ if(ssval[SSD]==0 || (dflag && t!=3 && t!=4) ||i < 0) break; ssymval = ssymval * b + i; lp++; } goto loop; } if(*lp == '.'){ /* dot */ ssymval = dot; over: adrflg++; lp++; goto loop; } if(*lp == '\''){ /* one ASCII char */ ssymval = *++lp; goto over; } if(*lp == '"'){ /* two ASCII chars */ ssymval = (*++lp)<<8; ssymval =| *++lp; /* put in second char */ goto over; } if(*lp == ':'){ /* special symbol */ adrflg++; lp++; ssymval = getspsym(); goto loop; } switch (*lp) { default: donef++; case ' ': get(trbase+28); if (callev >= 50) break; entpt[callev] = ssymval; callist[callev++] = trbase; if ((trbase = get(trbase+24)) == 0) break; } errflg = 0; setfunc(); } getarg() { register level, arg, t1; t1 = tdot; expr(); level = tdot; if (*lp++ != ',') error(); expr(); arg = tdot; if (*lp++ != ')') error(); if (level >= callp-callist) error(); ssymval = callist[level] - 8 - 4*arg; tdot = t1; } error() { printf("** invalid function argument specifier\n"); reset(); } prin /* * Adjust stack base register to point to saved regs */ #define SHI 0xcb #define SI 0xfb #define STM 0xd0 findbase(apc, arbase) int *arbase; { register loc; vallook(apc); /* name of current function */ loc = ssymval; /* entry pt of current function */ loc =+ disasm(loc); /* skip SI */ if (instr.op != SI && instr.op != SHI) return(0); loc =+ disasm(loc); /* check STM */ if (instr.op != STM || apc < loc+2) return(0); *arbase =+ instr.disp; /* adjust stack base by offset in STM */ return(1mget()) if (symflg&040 && value>=symval && value-symval<=diff) { if (symflg==1 && value!=symval) continue; savsym('_'); diff = value-symval; } return(diff); } get(aaddr) char *aaddr; { int w; register a, i; register char *addr; addr = aaddr&~01; if (addr&02) /* not on word boundary */ return((get(addr-2)<<16) | (get(addr+2)>>16)); for(i=0;i<=brktx;i++) if((brktab[i].addr&~03) == addr) return(brktab[i].value); if(pid) { return(ptrace(RUSER,pid,addr,0)); } w = 0; if(garg| ch==4) /* data or bss */ ssymval =+ ssval[SSD]; /* adjust for D space offset */ } onintr() { putchar('\n'); errflg++; reset(); } /* print a local symbol if possible */ plocsym(addr) { register flg; symset(); /* beginning of symbol table */ flg = 0; while(symget()) { if(symbol[0] == '~' ) { if(symval <= dot) continue; else break; } else if((symflg&077) == 1 && symval==addr) { savsym(0); flg++; } } if(flg) printf("%.8s",ssymbol); else printf("%o(r5)",ad (!dflag && (t==3 || t==4))) { /* for system I&D split */ if(value == symval){ /* found it */ savsym('_'); return(0); } /* find the signed difference between the two sixteen bit addresses */ if(value>=0 && symval<0) t = -(symval-value); else t = value-symval; if(t>0 && t= 0) printf("%o", get(trbase+32)); argp = trbase+32; while(--narg >= 0) { printf(",%o", get(argp =+ 4)); } printf(")\n"); tpc = get(trbase+28); if (call); } symlook(symstr) char *symstr; { register i; register symv; symset(); if (fsymbol[0]==0) { while(symget()) { if (eqstr(symbol, symstr)) { savsym(); return(1); } } if(*symstr == '_') { /* look for a local symbol */ symset(); while(symget()) { if(symbol[0]!='~' || symval!=ssval[SSF]) continue; while(symget() && symbol[0]!='~' && symflg!=037) if(eqstr(symbol,symstr+1)) return(localsym(ssval[SSF])); return(0); } } return(0); } while (symgec>3){ /* file is not core image */ seek(fcore,addr,0); if(read(fcore,&w,4) != 4) printf("** unable to read core file\n"); return(w); } if (addr < tsize) { if(fcore>0) goto rdcore; rdsym: seek(fsym, addr+040, 0); if (read(fsym, &w, 4) != 4) printf("** unable to read a.out file\n"); return(w); } if (addr < rtsize+dsize) { if(fcore<0) goto rdsym; /* no core file */ addr =- rtsize; } else if (addr > (14<<16) && addr < (14<<16)+ssize) addr =+ dsize - (14<<16); else printf("**dr); } /* print dot symbolicly if possible */ psym(addr) { register int offset; if(leffect==0) /* need to save effective address */ leffect = addr; if(addr>ssval[SSL] || addr<0) /* lowest address to use as a symbol */ if((offset=closeval(addr))>=0){ /* find a close symbol */ if(offset>0) printf("%.8s+%o",ssymbol,offset); else printf("%.8s",ssymbol); return; } printf("%o",addr); /* no close symbol */ } /* find a symbol whose value is close to the given value */ closeval(tv close to value */ /* return the offset */ closeloc(tvalue) { register value, offset, t; offset = ssval[SSRG]; /* symbol range */ for(t=0; t0 && tu_dsize)<< 8; ssize=(regbuf->u_ssize) << 8; rtsize = (regbuf->u_tsize+0177777) & ~0177777; headsize = 03000; /* core file header */ /* copy user regs to special symbols */ for (i = SSR0; i <= SSPS; i++) ssval[i] = uregs[regloc[i]]; /*** if(pid>0) /* at a breakpoint ** ssval[SSPC] =- 2; /* .-2 is real instr address ** ***/ } /* put special symbol values back in core file */ restcore() { register i; for(i=SSR0; i': if(*lp == '=') { lp++; nextrel = 7; } else nextrel = 6; break; } if(expr()==0 || errflg!=0) goto err; if(symadr) tdot = cget(tdot); switch(nextrel) { case 2: /* == */ condv = (condv == tdot); break; case 3: /* != */ condv = (condv != tdot); SSR0 0 #define SSR1 1 #define SSR2 2 #define SSR3 3 #define SSR4 4 #define SSR5 5 #define SSR6 6 #define SSR7 7 #define SSR8 8 #define SSR9 9 #define SSR10 10 #define SSR11 11 #define SSR12 12 #define SSR13 13 #define SSR14 14 #define SSR15 15 #define SSSP 7 #define SSPC 16 #define SSPS 17 #define SS8 18 #define SS9 19 #define SSL 20 #define SSM 21 #define SSQ 22 #define SSA 23 #define SSD 24 #define SSRG 25 #define SSF 26 #define SSSL 27 #define NUMSS 28 int ssval[NUMSS]; /* special symbol values */ cha */ struct { int type; /* instruction format */ char op; /* opcode */ char reg[3]; /* registers */ char *disp; /* displacement */ } instr; /* * Interdata opcode mnemonics & types */ struct { char *opmnem; int optype; } optab[] { 0, 0, "balr", RR, "btcr", BT+RR, "bfcr", BF+RR, "nr", RR, "clr", RR, "or", RR, "xr", RR, "lr", RR, "cr", RR, "ar", RR, "sr", RR, "mhr", RR, "dhr", RR, 0, 0, 0, 0, "srls", SF, "slls", SF, "chvr", RR, "bfcr", BF+RR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "stme", RX1, "lme", RX1, "lhl", RX1, "tbt", RX1, "sbt", RX1, "rbt", RX1, "cbt", RX1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "srls", SF, "slls", SF, "stbr", RR, "lbr", RR, "exbr", RR, "epsr", RR, "wbr", RR, "rbr", RR, "whr", RR, "rhr", RR, "wdr", RR, "rdr", RR, 0, 0, "ssr", RR, "ocr", RR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, write(wsym,&value,4) != 4) printf("no write access %s\n",symfil); } /* clear one or all breakpoints */ clbkpt(adr) { register int i,found; found=0; if(brktx<0) return; for(i=0;i<=brktx;i++){ /* thru brkpt table */ if((!adrfg || brktab[i].addr==adr) && brktab[i].addr != -1){ dot = brktab[i].addr&~03; /* address to reset */ cfput(brktab[i].value); /* reset value */ brktab[i].value = -1; brktab[i].addr = -1; found++; } } if(found) putchar('\n'); else if(adrfg) printf("?? no bs from symbolic file */ initfsym() { seek(fsym,0,0); /* beginning */ read(fsym, regbuf, 040); if (regbuf[0]!=0410 && regbuf[0]!=0407 && regbuf[0]!=0411) {/* magic */ printf("Not a.out format: %s\n", symfil); gargc = 4; fcore = fsym; wcore = wsym; return; } symoff = regbuf[1] + regbuf[2]; symlen = regbuf[4]; if (regbuf[7] != 1) symoff =<< 1; symoff =+ 040; tsize = regbuf[1]; /* text size */ dsize = regbuf[2]; /* data size */ ssize = 0; /* no bss */ headsize = 040; /* a.out header sibreak; case 4: /* < */ condv = (condv < tdot); break; case 5: /* <= */ condv = (condv <= tdot); break; case 6: /* > */ condv = (condv > tdot); break; case 7: /* >= */ condv = (condv >= tdot); break; } return(condv); } evalcond(bpx) { register lval,rval; lp = &brktab[bpx].cond[0]; lval = relexpr(); while(errflg == 0) { switch(*lp++) { default: if(*lp != '\0') goto err; lp = line; return(lval); case '|': if(*lp != '|') goto err; lp++; r *ssname[] /* special symbol names */ { "r0", /* 0 user reg 0 */ "r1", /* 1 */ "r2", /* 2 */ "r3", /* 3 */ "r4", /* 4 */ "r5", /* 5 */ "r6", /* 6 */ "sp", /* 6 */ "r8", "r9", "ra", "rb", "rc", "rd", "re", "rf", "pc", /* 7 */ "ps", /* 8 users processor status */ "8", /* 9 search lower limit */ "9", /* 10 search upper limit */ "l", /* 11 low address for symbols */ "m", /* 12 search mask value */ "q", /* 13 last value typed to user */ "a", /* 14 have assembler symbol "lpsr", RR, 0, 0, 0, 0, 0, 0, "mr", RR, "dr", RR, 0, 0, 0, 0, "btbs", BT+BBACK+SF, "btfs", BT+SF, "bfbs", BF+BBACK+SF, "bffs", BF+SF, "lis", SF, "lcs", SF, "ais", SF, "sis", SF, "ler", RR, "cer", RR, "aer", RR, "ser", RR, "mer", RR, "der", RR, "fxr", RR, "flr", RR, "btbs", BT+BBACK+SF, "btfs", BT+SF, 0, 0, 0, 0, "exhr", RR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "sth", RX1, "bal", RX1, "btc", BT+RX1, "bfc", BF+RX1, "nh 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bxh", RX1, "bxle", RX1, "lpsw", RX1, "thi", RI1, "nhi", RI1, "clhi", RI1, "ohi", RI1, "xhi", RI1, "lhi", RI1, "chi", RI1, "ahi", RI1, "shi", RI1, "srhl", RI1, "slhl", RI1, "srha", RI1, "slha", RI1, "stm", RX1, "lm", RX1, "stb", RX1, "lb", RX1, "clb", RX1, "al", RX1,reakpoint\n"); dot = ldot; /* reset dot */ return; } /* initialize known symbols from the core file */ initfcor() { register t,i ; if(fcore<0) { printf("cant initialize from fcore\n"); return; } if(seek(fcore,coroffset,3)<0){ /* beginning of core file */ printf("fcore seek error\n"); endit(); } if(read(fcore, regbuf, 03000)<03000) { printf("fcore read error\n"); endit(); } t = regbuf->u_ar0; t =- (14<<16); uregs = ®buf[t/4]; status = (regbuf->u_arg[0]); tsize=(regbuf->u_tsizze */ rtsize = tsize; } /* set the default current function */ setfunc() { /*** symset(); while(symget()) { if(symbol[0] == '~') { if(symval <= ssval[SSPC]) ssval[SSF] = symval; else break; } } ***/ vallook(ssval[SSPC]); ssval[SSF] = ssymval; } /* check for conditional breakpoint */ /* return 0 if no break */ /* !0 if break */ condbpt() { register bpx; for(bpx=0; bpx>24; instr.reg[0] = (ins>>20)&017; instr.reg[1] = (ins>>16)&017; instr.type = optab[instr.op].optype; switch (instr.type & 07) { case SF: case RR: return(2); case RI1: 1] = 0; if (type & BBACK) instr.disp = dot - n; else instr.disp = dot + n; type = RI1; break; } } switch (type & 07) { case RR: printf("%s", ssname[instr.reg[1]]); break; case SF: printf("%o", instr.reg[1]); break; case RI1: case RI2: case RX1: case RX2: psym(instr.disp); if (n = instr.reg[1]) printf("(%s)", ssname[n]); break; case RX3: psym(instr.disp); if (n = instr.reg[1]) { printf("(%s", ssname[n]); if (n = instr.reg[2]) printf(",%s", ssly */ pbkptc = 0; tpc = ssval[SSPC]; for(i=0; i<=brktx; i++) if(brktab[i].addr == tpc){ pbkptc = tpc; /* remember who we cleared */ pbkptv = brktab[i].value; dot = tpc&~03; cfput(pbkptv); } if(pbkptc==0 && flag) /* ;p really desnt need a temp bkpt */ return(0); /*** ssval[SSPS] =| 020; /* turn on T bit ***/ return(1); } /* remove a temporary breakpoint */ rtempbpt() { register int i; if(pbkptc) { /* must reset a permanent one */ dot = pbkptc&~03; if (dot == pbkptc) iINES 24 #define LENGTH 80 #define SPLIT '-' #define PROMPT '>' #define CONFIRM '.' #define SCORE "^" #define FORM 014 #define SIGHUP 1 #define SIGINTR 2 #define SIGQUIT 3 #define FNSIZE 64 #define LBSIZE 512 #define ESIZE 128 #define GBSIZE 256 #define NBRA 5 #define EOF -1 #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 #define STAR 01 #define error errfunc() /*** was 'goto errlab' ***/ #define READ 0 #define WRITE 1 #define UNI globp = "r"; } fendcore = sbrk(0); if (vflag>0) puts("Editor"); init(); if ((signal(SIGINTR, 1) & 01) == 0) signal(SIGINTR, onintr); setexit(); commands(vflag); unlink(tfname); } commands(prompt) { int getfile(), gettty(); register *a1, c; register char *p; char *p1,*p2; int fd, r, n; for (;;) { if (pflag) { pflag = 0; addr1 = addr2 = dot; goto print; } if (prompt>0 && globp == 0) putch(PROMPT); addr1 = 0; addr2 = 0; xflag = 0; do { addr1 = addr2; if ((a1 = address())==/emhelp",0))<0) { puts("/usr/lib/emhelp not found"); continue; } while (n = read( fd, linebuf, 512)) write(1, linebuf, n); close( fd); continue; case 'i': setdot(); nonzero(); newline(); append(gettty, addr2-1); continue; case 'k': if ((c = getchar()) < 'a' || c > 'z') error; newline(); setdot(); nonzero(); names[c-'a'] = *addr2 | 01; continue; case 'm': move(0); continue; case '\n': if (addr2==0) addr2 = dot+1; addr1 = addr2; goto print; instr.disp = ins&0177777; return(4); case RI2: instr.disp = get(loc+2); return(6); case RX1: ins = get(loc+2); switch(ins>>30) { /* RX2 -- negative offset */ case 3: instr.type =+ RX2-RX1; instr.disp = ((-1)<<16) | ins>>16; instr.disp =+ loc + 4; return(4); /* RX2 -- positive offset */ case 2: instr.type =+ RX2-RX1; instr.disp = (ins>>16) & 077777; instr.disp =+ loc + 4; return(4); /* RX1 */ case 0: instr.disp = ins>>16; return(4); /* RX3 */name[n]); putchar(')'); } break; } putchar('\t'); } /* get the value of a special symbol */ getspsym() { return(ssval[spsymidx()]); } /* store a value into a special symbol */ putspsym(value) { register t1,t2; t1 = spsymidx(); if(t1==SSF) { /* current function */ for(t2=0; t212) { printf("Unknown termination status\n"); return; } printf("Termination status: %o %s\n",status,termstr[i]); } XBUFL 100 extern int margin; /* used to set threshold in 'open' */ int elfic 0; /* true if "elfic" (-e) flag */ int firstime 1; /* ugh - used to frigg initial "read" */ int peekc; int lastc; char unixbuffer [UNIXBUFL]; char savedfile[FNSIZE]; char file[FNSIZE]; char linebuf[LBSIZE]; char rhsbuf[LBSIZE/2]; char expbuf[ESIZE+4]; int circfl; int *zero; int *dot; int *dol; int *endcore; int *fendcore; int *addr1; int *addr2; char genbuf[LBSIZE]; int count[2]; char *nextip; char *linebp; int ninbuf; int io; in0) { c = getchar(); break; } addr2 = a1; if ((c=getchar()) == ';') { c = ','; dot = a1; } } while (c==','); if (addr1==0) addr1 = addr2; if (c>= 'A' && c<= 'Z') c =| 040; switch(c) { case 'a': setdot(); newline(); append(gettty, addr2); continue; case 'b': if((c=peekc=getchar())== '+' || c =='-') peekc = 0; else if(c != '\n') error; margin = c == '-' ? LBSIZE - 40 : LENGTH - 20; newline(); continue; case 'c': setdot(); newline(); delete(); case 'l': listf++; case 'p': newline(); print: setdot(); nonzero(); a1 = addr1; do puts(getline(*a1++)); while (a1 <= addr2); dot = addr2; listf = 0; continue; case 'o': setdot(); op(globp); continue; case 'q': setnoaddr(); newline(); if (elfic) { firstime = 1; goto writeout; } quitit: unlink(tfname); exit(); case 'r': caseread: filename(); if ((io = open(file, 0)) < 0) { lastc = '\n'; error; } setall(); ninbuf = 0; append(getfile, a case 1: instr.type =+ RX3-RX1; instr.reg[2] = (ins>>24) & 017; ins =& 077777777; if (ins & 01000000) /* negative offset */ ins =| (0377<<24); instr.disp = ins; return(6); } default: return(0); } } /* print an instruction in assembler format */ pinstr() { register n; register type; if ((dotinc = disasm(dot)) == 0) { /* illegal opcode */ printf(" ??\t"); dotinc = 2; sdot = dot + 2; return; } sdot = dot + dotinc; type = instr.type; n = instr.reg[0]; if ((typpecial symbol. */ /* the special symbol name is pointed to by lp */ spsymidx() { register int i; register char *p,*tlp; for(i=0;i called from ;s */ /* flag == 1 => called from ;p */ stempbpt(flag) { register int tpc,i,j; /* if pc points to a permanent breakpoint, clear it temporariext input with local editing via control keys 'b' to set a threshold for automatic line breaks in 'o' mode. 'h' displays a screen full of help with editor commands (the help is in /usr/lib/emhelp) * Minor changes for Interdata UNIX version, 1977 R Miller University of Wollongong bugs: should not use printf in substitute() (for space reasons). */ /* this file contains all of the code except that used in the 'o' command. that is in a second segment called em2.c */ /* screen dimensions */ #define L onintr(); onquit = signal(SIGQUIT, 1); onhup = signal(SIGHUP, 1); if(*(*argv+1) == 'm') vflag = 1; argv++; if (argc > 1 && **argv=='-') { p1 = *argv+1; while (*p1) { switch (*p1++) { case 'q': signal(SIGQUIT, 0); break; case 'e': elfic = 1; break; case 'p': vflag = 0; break; case 's': vflag = -1; break; } } if (!(*argv)[1]) vflag = -1; argv++; argc--; } if (argc>1) { p1 = *argv; p2 = savedfile; while (*p2++ = *p1++); breaks(p1-3); append(gettty, addr1-1); continue; case 'd': setdot(); newline(); delete(); continue; case 'e': if (elfic) error; setnoaddr(); if ((peekc = getchar()) != ' ') error; savedfile[0] = 0; init(); addr2 = zero; goto caseread; case 'f': if (elfic) error; setnoaddr(); if ((c = getchar()) != '\n') { peekc = c; savedfile[0] = 0; filename(); } puts(savedfile); continue; case 'g': global(1); continue; case 'h': newline(); if((fd = open("/usr/libntinue; case '"': setdot(); newline(); /*** nonzero(); ***/ dot = addr1; if (dot >= dol) error; addr1 = dot+1; addr2 = dot +LINES-1; if (addr2 > dol) addr2 = dol; outlines: putchar(FORM); a1 = addr1-1; while (++a1 <= addr2) puts(getline(*a1)); dot = addr2; continue; case '&': setdot(); newline(); nonzero(); dot = addr1; addr1 = dot - (LINES-2); addr2 = dot; addr1 = addr1>zero? addr1: zero+1; goto outlines; case '%': newline(); setdot(); nonzero(); dot = addr1; addr1 = dot - (LINES/2 - 2); addr2 = dot + (LINES/2 - 2); if (addr1 <= zero) addr1 = zero + 1; if (addr2 > dol) addr2 = dol; a1 = addr1 - 1; putchar(FORM); while(++a1 <= addr2) { if (a1 == dot) screensplit(); puts(getline(*a1)); if (a1 == dot) screensplit(); } continue; case '>': vflag = vflag>0? 0: vflag; reset(); case '<': vflag = 1; reset(); case '=': setall(); newline(); count[1] = (addr2-zero)&077777; putd(); putchar('\n'); continue; case = zero+1; addr2 = dol; if (dol==zero) addr1 = zero; } setdot(); } setnoaddr() { if (addr2) error; } nonzero() { if (addr1<=zero || addr2>dol) error; } newline() { register c; if ((c = getchar()) == '\n') return; c = c >= 'A' && c <= 'Z' ? c + 32 : c; if (c=='p' || c=='l') { pflag++; if (c=='l') listf++; if (getchar() == '\n') return; } error; } filename() { register char *p1, *p2; register c; count[1] = 0; c = getchar(); if (c=='\n' || c==EOF) { if (elfic && *lp, *fp; lp = linebuf; fp = nextip; do { if (--ninbuf < 0) { if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) return(EOF); fp = genbuf; } if (lp >= &linebuf[LBSIZE]) error; if ((*lp++ = c = *fp++ & 0177) == 0) { lp--; continue; } if (++count[1] == 0) ++count[0]; } while (c != '\n'); *--lp = 0; nextip = fp; return(0); } putfile() { int *a1; register char *fp, *lp; register nib; nib = 512; fp = genbuf; a1 = addr1; do { lp = getline(*a1++); for (;;) { i > dol) a1 = dol; dot = a1; } getline(tl) { register char *bp, *lp; register nl; lp = linebuf; bp = getblock(tl, READ); nl = nleft; tl =& ~0377; while (*lp++ = *bp++) if (--nl == 0) { bp = getblock(tl=+0400, READ); nl = nleft; } return(linebuf); } putline() { register char *bp, *lp; register nl; int tl; lp = linebuf; tl = tline; bp = getblock(tl, WRITE); nl = nleft; tl =& ~0377; while (*bp = *lp++) { if (*bp++ == '\n') { *--bp = 0; linebp = lp; break; } if (- } *gp++ = '\n'; *gp++ = 0; for (a1=zero; a1<=dol; a1++) { *a1 =& ~01; if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k) *a1 =| 01; } for (a1=zero; a1<=dol; a1++) { if (*a1 & 01) { *a1 =& ~01; dot = a1; globp = globuf; commands(-2); a1 = zero; } } } substitute(inglob) { register gsubf, *a1, nl; int nflag, nn, getsub(); gsubf = compsub(); nflag = gsubf > 1 ? 1 : 0; nn = 0; gsubf =& 01; gsubf =| xflag; for (a1 = addr1; a1 <= addr2; a1++) { if (execute(0, a1)==0) cuf[LBSIZE/2]) error; } *p++ = 0; if(((peekc = getchar())| 040) == 'g') { peekc = 0; gsubf =| 1; } if (((peekc = getchar())| 040) == 'n') { peekc = 0; gsubf =| 2; } newline(); return(gsubf); } getsub() { register char *p1, *p2; p1 = linebuf; if ((p2 = linebp) == 0) return(EOF); while (*p1++ = *p2++); linebp = 0; return(0); } dosub() { register char *lp, *sp, *rp; int c; lp = linebuf; sp = genbuf; rp = rhsbuf; while (lp < loc1) *sp++ = *lp++; while (c = *rp++) { if ('!': unix(); continue; case EOF: if(prompt == -2 || ttyn(0) == 'x') return; continue; } error; } } address() { register *a1, minus, c; int n, relerr; minus = 0; a1 = 0; for (;;) { c = getchar(); if ('0'<=c && c<='9') { n = 0; do { n = n * 10; n =+ c - '0'; } while ((c = getchar())>='0' && c<='9'); peekc = c; if (a1==0) a1 = zero; if (minus<0) n = -n; a1 =+ n; minus = 0; continue; } relerr = 0; if (a1 || minus) relerr++; switch(c)!firstime) error; else firstime = 0; p1 = savedfile; if (*p1==0) error; p2 = file; while (*p2++ = *p1++); return; } if (c!=' ') error; while ((c = getchar()) == ' '); if (c=='\n') error; p1 = file; do { *p1++ = c; } while ((c = getchar()) != '\n'); *p1++ = 0; if (savedfile[0]==0) { p1 = savedfile; p2 = file; while (*p1++ = *p2++); breaks(p1 - 3); } } breaks(p) char *p; { if(*p++ == '.') if(*p == 'r' || *p == 'n') margin = LENGTH -20; } exfile() { close(io)f (--nib < 0) { if(write(io, genbuf, fp-genbuf)!=(fp-genbuf)) error; nib = 511; fp = genbuf; } if (++count[1] == 0) ++count[0]; if ((*fp++ = *lp++) == 0) { fp[-1] = '\n'; break; } } } while (a1 <= addr2); if(write(io, genbuf, fp-genbuf)!=(fp-genbuf)) error; } append(f, a) int (*f)(); { register *a1, *a2, *rdot; int nline, tl; struct { int integer; }; nline = 0; dot = a; while ((*f)() == 0) { if (dol >= endcore) { if (sbrk(1024) == -1) error; endcor-nl == 0) { bp = getblock(tl=+0400, WRITE); nl = nleft; } } nl = tline; tline =+ (((lp-linebuf)+03)>>1)&077776; return(nl); } getblock(atl, iof) { extern read(), write(); register bno, off; bno = (atl>>8); off = (atl<<1)&0774; /*** if (bno >= 255) { puts(TMPERR); error; } ***/ nleft = 512 - off; if (bno==iblock) { ichanged =| iof; return(ibuff+off); } if (bno==oblock) return(obuff+off); if (iof==READ) { if (ichanged) blkio(iblock, ibuff, write); ichanged = 0; ibloontinue; inglob =| 01; if (confirmed()) { dosub(); nn++; } else donothing(); if (gsubf) { while (*loc2) { if (execute(1)==0) break; if(confirmed()) { dosub(); nn++; } else donothing(); } } *a1 = putline(); nl = append(getsub, a1); a1 =+ nl; addr2 =+ nl; } if (inglob==0) {putchar('?'); error; } /* two queries distinguish failed match */ /* should use putd() and count here */ if (nflag) printf( " %d \n", nn); } donothing() { char t1,t2; t1 = rhsbuf[0]; t2 =c=='&') { sp = place(sp, loc1, loc2); continue; } else if ((c&0200) && (c =& 0177) >='1' && c < NBRA+'1') { sp = place(sp, braslist[c-'1'], braelist[c-'1']); continue; } *sp++ = c&0177; if (sp >= &genbuf[LBSIZE]) error; } lp = loc2; loc2 = sp + linebuf - genbuf; while (*sp++ = *lp++) if (sp >= &genbuf[LBSIZE]) error; lp = linebuf; sp = genbuf; while (*lp++ = *sp++); } place(asp, al1, al2) { register char *sp, *l1, *l2; sp = asp; l1 = al1; l2 = al2; while (l1 < l2) { { case ' ': case '\t': continue; case '+': minus++; if (a1==0) a1 = dot; continue; case '-': case '^': minus--; if (a1==0) a1 = dot; continue; case '?': case '/': compile(c); a1 = dot; for (;;) { if (c=='/') { a1++; if (a1 > dol) a1 = zero; } else { a1--; if (a1 < zero) a1 = dol; } if (execute(0, a1)) break; if (a1==dot) {putchar('?'); error;} /* two '?'s for failed search */ } ; io = -1; if (vflag>=0) { putd(); putchar('\n'); } } onintr() { signal(SIGINTR, onintr); putchar('\n'); lastc = '\n'; error; } errfunc() { register c; listf = 0; puts("?"); count[0] = 0; seek(0, 0, 2); pflag = 0; if (globp) lastc = '\n'; globp = 0; peekc = lastc; while ((c = getchar()) != '\n' && c != EOF); if (io > 0) { close(io); io = -1; } reset(); } getchar() { char ch; if (lastc=peekc) { peekc = 0; return(lastc); } if (globp) { if ((lastc = *globp++) != 0) e.integer =+ 1024; } tl = putline(); nline++; a1 = ++dol; a2 = a1+1; rdot = ++dot; while (a1 > rdot) *--a2 = *--a1; *rdot = tl; } return(nline); } unix() { register savint, pid, rpid; int retcode; char c,*lp,*fp; pid = 0; if ((c=getchar ()) != '!') { lp = unixbuffer; do { if (c != '%') *lp++ = c; else { pid = 1; fp = savedfile; while ((*lp++ = *fp++)); lp--; } c = getchar(); } while (c != '\n'); *lp = '\0'; } else { pid = 1; while (getchack = bno; blkio(bno, ibuff, read); return(ibuff+off); } if (oblock>=0) blkio(oblock, obuff, write); oblock = bno; return(obuff+off); } blkio(b, buf, iofcn) int (*iofcn)(); { seek(tfile, b, 3); if ((*iofcn)(tfile, buf, 512) != 512) { puts(TMPERR); error; } } init() { register char *p; register pid; close(tfile); tline = 0; iblock = -1; oblock = -1; tfname = "/tmp/exxxxx"; ichanged = 0; pid = getpid(); for (p = &tfname[11]; p > &tfname[6];) { *--p = (pid&07) + '0'; pid =>> 3; rhsbuf[1]; rhsbuf[0] = '&'; rhsbuf[1] = 0; dosub(); rhsbuf[0] = t1; rhsbuf[1] = t2; } confirmed() { int ch; if(xflag) { puts(linebuf); underline(linebuf, loc1, loc2, SCORE); ch = getchar(); if ( ch != '\n') { while (getchar() != '\n'); if ( ch != CONFIRM ) puts("? '.' to confirm"); } return (ch == CONFIRM ? 1: 0); } return 1; } underline (line, l1, l2, score) char *line, *l1, *l2, *score; { char *ch, *ll; int i; register char *p; p = line; ch = " "; ll = l1; i = *sp++ = *l1++; if (sp >= &genbuf[LBSIZE]) error; } return(sp); } move(cflag) { register int *adt, *ad1, *ad2; int getcopy(); setdot(); nonzero(); if ((adt = address())==0) error; newline(); ad1 = addr1; ad2 = addr2; if (cflag) { ad1 = dol; append(getcopy, ad1++); ad2 = dol; } ad2++; if (adt= ad2) { dot = adt++; reverse(ad1, ad2); break; case '$': a1 = dol; break; case '.': a1 = dot; break; case '\'': if ((c = getchar()) < 'a' || c > 'z') error; for (a1=zero; a1<=dol; a1++) if (names[c-'a'] == (*a1|01)) break; break; default: peekc = c; if (a1==0) return(0); a1 =+ minus; if (a1dol) error; return(a1); } if (relerr) error; } } setdot() { if (addr2 == 0) addr1 = addr2 = dot; if (addr1 > addr2) error; } setall() { if (addr2==0) { addr1 return(lastc); globp = 0; return(EOF); } if (read(0, &ch, 1) <= 0) return(lastc = EOF); return(lastc = (ch&0177)); } gettty() { register c, gf; register char *p; p = linebuf; gf = globp; while ((c = getchar()) != '\n') { if (c==EOF) { if (gf) peekc = c; return(c); } if ((c =& 0177) == 0) continue; *p++ = c; if (p >= &linebuf[LBSIZE-2]) error; } *p++ = 0; if (linebuf[0]=='.' && linebuf[1]==0) return(EOF); return(0); } getfile() { register c; register charr () != '\n');} if(pid) { putchar('!'); puts(unixbuffer); } setnoaddr(); if ((pid = fork()) == 0) { signal(SIGHUP, onhup); signal(SIGQUIT, onquit); execl ("/bin/sh", "sh", "-c", unixbuffer, 0); exit(); } savint = signal(SIGINTR, 1); while ((rpid = wait(&retcode)) != pid && rpid != -1); signal(SIGINTR, savint); puts("!"); } delete() { register *a1, *a2, *a3; nonzero(); a1 = addr1; a2 = addr2+1; a3 = dol; dol =- a2 - a1; do *a1++ = *a2++; while (a2 <= a3); a1 = addr1; if (a1 } close(creat(tfname, 0600)); tfile = open(tfname, 2); brk(fendcore); dot = zero = dol = fendcore; endcore = fendcore - 2; } global(k) { register char *gp; register c; register int *a1; char globuf[GBSIZE]; if (globp) error; setall(); nonzero(); if ((c=getchar())=='\n') error; compile(c); gp = globuf; while ((c = getchar()) != '\n') { if (c==EOF) error; if (c=='\\') { c = getchar(); if (c!='\n') *gp++ = '\\'; } *gp++ = c; if (gp >= &globuf[GBSIZE-2]) error; 2; while (i--) { while (*p && p < ll) { write (1, (*p == '\t' ? p : ch),1); p++; } ch = score; ll = l2; } } screensplit() { register a; a = LENGTH; while(a--) putchar(SPLIT); putchar('\n'); } compsub() { register seof, c; register char *p; int gsubf; gsubf = 0; if ((seof = getchar()) == '\n') error; compile(seof); p = rhsbuf; for (;;) { c = getchar(); if (c=='\\') c = getchar() | 0200; if (c=='\n') error; if (c==seof) break; *p++ = c; if (p >= &rhsb reverse(ad2, adt); reverse(ad1, adt); } else error; } reverse(aa1, aa2) { register int *a1, *a2, t; a1 = aa1; a2 = aa2; for (;;) { t = *--a2; if (a2 <= a1) return; *a2 = *a1; *a1++ = t; } } getcopy() { if (addr1 > addr2) return(EOF); getline(*addr1++); return(0); } compile(aeof) { register eof, c; register char *ep; char *lastep; char bracket[NBRA], *bracketp; int nbra; int cclcnt; ep = expbuf; eof = aeof; bracketp = bracket; nbra = 0; if ((c = getchar()) == eof) { if (*ep==0) error; return; } circfl = 0; if (c=='^') { c = getchar(); circfl++; } if (c=='*') goto cerror; peekc = c; for (;;) { if (ep >= &expbuf[ESIZE]) goto cerror; c = getchar(); if (c==eof) { *ep++ = CEOF; return; } if (c!='*') lastep = ep; switch (c) { case '\\': if ((c = getchar())=='(') { if (nbra >= NBRA) goto cerror; *bracketp++ = nbra; *ep++ = CBRA; *ep++ = nbra++; continue; } if (c == ')') { if (bracketp <= brlp, *ep, *curlp; char *nextep; lp = alp; ep = aep; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CDOL: if (*lp==0) continue; return(0); case CEOF: loc2 = lp; return(1); case CCL: if (cclass(ep, *lp++, 1)) { ep =+ *ep; continue; } return(0); case NCCL: if (cclass(ep, *lp++, 0)) { ep =+ *ep; continue; } return(0); case CBRA: braslist[*ep++] = lp; continue; c call is unavailable. getpid() { register f; int b[1]; f = open("/dev/kmem", 0); if(f < 0) return(-1); seek(f, 0140074, 0); read(f, b, 2); seek(f, b[0]+8, 0); read(f, b, 2); close(f); return(b[0]); } */ r1 == zero) error; if ((seof = getchar()) == '\n') { loc2 = linebuf-1; seof = 0;} else compile(seof); setraw(); /* terminal into raw mode*/ for ( a1 = addr1; a1 <= addr2; a1++) { if (seof) {if (execute(0,a1) == 0) continue;} else getline(*a1); puts("\\\r"); lp = linebuf; sp = genbuf; inglob =| 01; while (lp < loc2){ putch(*lp); *sp++ = *lp++; } lnp = lp; gnp = sp; oflag = gopen(); /* open the current line */ *a1 = putline(); /* write revised line */ nl = append( getop *(--sp)))) if(sp < genbuf) goto out; if(*sp == SPACE) while((*(--lp) = *(--sp)) == SPACE) if(sp < genbuf) goto out; } else while(sp >= genbuf && !inword(*sp)) if((*lp-- = *sp--) == CTRLI) tabs =- TABSET; out: sp++; lp++; goto verify; case CTRLC: case CTRLQ: /* forward one char */ if(*lp == 0) goto backquery; putch(*lp); forward: if(*lp == SPACE && sp + tabs > threshold) { putch('\r'); ch = '\n'; putch(ch); lp++; *sp execl("/bin/spell", "spell", pr, 0); ***/ puts("sorry, can't spell today"); /*** exit(); } savint = signal(SIGINTR,1); while((rpid = wait(&retcode)) != pid && rpid != -1); signal(SIGINTR, savint); setraw(); puts("!!"); ***/ goto verify; case CTRLW: /* forward one word */ if(*lp == '\0') goto backquery; while(*lp == SPACE) putch(*sp++ = *lp++); if(inword(*lp)) { while(inword(*lp)) { putch(*sp++ = *lp++); if(sp+tabs==thacket) goto cerror; *ep++ = CKET; *ep++ = *--bracketp; continue; } *ep++ = CCHR; if (c=='\n') goto cerror; *ep++ = c; continue; case '.': *ep++ = CDOT; continue; case '\n': goto cerror; case '*': if (*lastep==CBRA || *lastep==CKET) error; *lastep =| STAR; continue; case '$': if ((peekc=getchar()) != eof) goto defchar; *ep++ = CDOL; continue; case '[': *ep++ = CCL; *ep++ = 0; cclcnt = 1; if ((c=getchar()) == '^'ase CKET: braelist[*ep++] = lp; continue; case CDOT|STAR: curlp = lp; while (*lp++); goto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep); ep++; goto star; case CCL|STAR: case NCCL|STAR: curlp = lp; while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); ep =+ *ep; goto star; star: do { lp--; if (lp==locs) break; if (advance(lp, ep)) return(1); } while (lp > curlp); return(0); default: error; } } cclass(aset, ac, af) { register char *set, c; re# /* This is the second and final segment of the QMC Unix Editor - em */ #define EOF -1 #define LBSIZE 512 #define SIGHUP 1 #define SIGINTR 2 #define SIGQUIT 3 #define UNIXBUFL 100 #define error errfunc() /*** was 'goto errlab' ***/ #define TABSET 7 /* this should be determined dynamically */ #define RAW 040 #define ECHO 010 #define OPEN '/' #define BELL 07 #define ESCAPE 033 #define SPACE 040 #define BACKSL 0134 #define RUBOUT 0177 #define CTRLA 01 #define CTRLB 02 #define CTRLC 03 #define CTRLD 04 #defien,a1); a1 =+ nl; addr2 =+ nl; } setcook(); /* terminal in cook mode */ putchar('\n'); if (inglob == 0) { putchar('?'); error;} } getnil() { if(oflag == EOF) return EOF; linebuf[0] = '\0'; oflag = EOF; return 0; } setraw() { if(gtty(0,tty) == -1) error; savetty = tty[2]; tty[2] =| RAW; stty(0, tty); } setcook() { tty[2] = savetty; stty(0, tty); } inword(c) { if (c < '0') return(0); if (c <= '9') return(1); c =& 0137; if (c < 'A') return(0); if (c <= 'Z') return(1); return(0); }reshold) putch(BELL); } if(*lp == SPACE) { if(sp+tabs>threshold) { ch = '\n'; lp++; *sp++ = ch; br = sp; putch('\r'); putch('\n'); } if(*lp == SPACE) while(*(lp+1) == SPACE) putch(*sp++ = *lp++); } } else while(*lp && !inword(*lp)) { if(*lp == CTRLI) tabs =+ TABSET; putch(*sp++ = *lp++); if(sp+tabs==threshold) putch(BELL); } break; case CTRLZ: /* delete a word */ if(sp == genbu) { c = getchar(); ep[-2] = NCCL; } do { if (c=='\n') goto cerror; *ep++ = c; cclcnt++; if (ep >= &expbuf[ESIZE]) goto cerror; } while ((c = getchar()) != ']'); lastep[1] = cclcnt; continue; defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: expbuf[0] = 0; error; } execute(gf, addr) int *addr; { register char *p1, *p2, c; if (gf) { if (circfl) return(0); p1 = linebuf; p2 = genbuf; while (*p1++ = *p2++); locs = p1 = loc2gister n; set = aset; if ((c = ac) == 0) return(0); n = *set++; while (--n) if (*set++ == c) return(af); return(!af); } putd() { register r; extern ldivr; count[1] = ldiv(count[0], count[1], 10); count[0] = 0; r = ldivr; if (count[1]) putd(); putchar(r + '0'); } puts(as) char *as; { register char *sp; sp = as; col = 0; while (*sp) putchar(*sp++); putchar('\n'); } char line[70]; char *linp line; putchar(ac) { register char *lp; register c; lp = linp; c = ac; if (listfne CTRLE 05 #define CTRLF 06 #define CTRLH 010 #define CTRLI 011 #define CTRLQ 021 #define CTRLR 022 #define CTRLS 023 #define CTRLV 026 #define CTRLW 027 #define CTRLX 030 #define CTRLZ 032 #define ITT 0100000 extern char *linebp, *loc2, linebuf[LBSIZE], genbuf[LBSIZE], unixbuffer[UNIXBUFL]; extern int onquit,onhup, peekc; extern int *zero, *addr1, *addr2; extern int *errlab; extern int lastc; int margin LBSIZE - 40; int oflag; char *threshold, *savethresh; char *lnp,*gnp,*brp; int savetty, tty[3]; rescan() { register char *lp, *sp; if(savethresh) { threshold = savethresh; savethresh = 0; } lp = linebuf; sp = genbuf; while(*lp++ = *sp++) if(lp>linebuf+LBSIZE) { *(--lp) = 0; return 0; } } gopen() /*leaves revised line in linebuf, returns 0 if more to follow, EOF if last line */ { register char *lp, *sp, *rp; register char *br, *pr; int ch, tabs; int retcode, savint, pid, rpid; lp = lnp; sp = gnp; tabs = 0; for (rp = genbuf; rp < sp; rp++) if (*rp == CTRLI) tabs =+ TABSET;++ = ch; br = sp; break; } if(*lp == CTRLI) tabs =+ TABSET; *sp++ = *lp++; /* one character */ if(sp + tabs == threshold) putch(BELL); continue; case CTRLF: /* delete forward */ while(*lp++); lp--; goto verify; case CTRLE: putb(lp); goto verify; case CTRLH: help(); goto verify; case CTRLR: /* margin release */ if(threshold-genbuf= genbuf && !inword(*sp)) if(*sp-- == CTRLI) tabs =- TABSET; zout: sp++; goto verify; case '@': /*delete displayed line */ /* delete backward */ sp = genbuf; tabs = 0; goto verify; case RUBOUT: lastc = ; } else { if (addr==zero) return(0); p1 = getline(*addr); locs = 0; } p2 = expbuf; if (circfl) { loc1 = p1; return(advance(p1, p2)); } /* fast check for first character */ if (*p2==CCHR) { c = p2[1]; do { if (*p1!=c) continue; if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } /* regular algorithm */ do { if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } advance(alp, aep) { register char *) { col++; if (col >= 72) { col = 0; *lp++ = '\\'; *lp++ = '\n'; } if (c=='\t') { c = '>'; goto esc; } if (c=='\b') { c = '<'; esc: *lp++ = '-'; *lp++ = '\b'; *lp++ = c; goto out; } if (c<' ' && c!= '\n') { *lp++ = '\\'; *lp++ = (c>>3)+'0'; *lp++ = (c&07)+'0'; col =+ 2; goto out; } } *lp++ = c; out: if(c == '\n' || lp >= &line[64]) { linp = line; write(1, line, lp-line); return; } linp = lp; } /* * Get process ID routine if systemop(inglob) { register *a1; register char *lp, *sp; int seof, ch; int t, nl; extern getopen(), getnil(); threshold = genbuf + margin; savethresh = 0; switch (ch = peekc = getchar()) { case BACKSL: t = 1; delete(); addr2 = addr1; break; case ';': case '+': t = 0; break; case '-': t =1; break; default: goto normal; } peekc = 0; if(addr1 != addr2) error; oflag = 0; append(getnil, addr2 - t); addr1 = addr2 =- (t-1); setdot(); nonzero(); normal: if(add for(;;){ switch (ch = getchar()) { case CTRLD: case ESCAPE: /* close the line (see case '\n' also) */ close: putb(lp); while(*sp++ = *lp++); rescan(); return(EOF); case CTRLA: /* verify line */ verify: puts("\\\r"); putch('\r'); *sp = '\0'; putb(genbuf); continue; case CTRLB: /* back a word */ if(sp == genbuf) goto backquery; while((*(--lp) = *(--sp)) == SPACE) if(sp < genbuf) goto out; if(inword(*sp)) { while(inword((*(--lp) =y; continue; case CTRLS: /* re-set to start of line */ while(*sp++ = *lp++); rescan(); lp = linebuf; sp = genbuf; tabs = 0; goto verify; case CTRLV: /* verify spelling */ /*** rp = sp; pr = unixbuffer+UNIXBUFL-2; *pr = 0; while(*(--rp) == SPACE); while(inword(*rp) && rp >= genbuf) *(--pr) = *rp--; if(*pr == 0) goto backquery; puts("!!"); setcook(); if((pid = fork()) == 0) {signal(SIGHUP, onhup); signal(SIGQUIT, onquit); ('\n'); puts("\\\r"); setcook(); error; case CTRLX: putch('#'); case '#': if( sp == genbuf) goto backquery; if(*(--sp) == CTRLI) tabs =- TABSET; if( ch == CTRLX) goto verify; continue; case '\n': case '\r': /* split line, actually handled at end of switch block */ ch = '\n'; *sp++ = ch; br = sp; break; case BACKSL: /* special symbols */ switch (ch = peekc = getchar()) { case '(': ch = '{'; peekc = 0; break; case ')': ch = '}'; peekc = 0; break; case '!': ch = '|'; peekc = 0; break; case '^': ch = '~'; peekc = 0; break; case '\'': ch = '`'; peekc = 0; break; case BACKSL: case '#': case '@': peekc = 0; break; default: if(ch >= 'a' && ch <= 'z') { peekc = 0; ch =- 040;} else { *(--lp) = BACKSL; goto forward; } } default: *(--lp) = ch; goto forward; } if (ch == '\n') { /* split line */ if(*(br-1) != '\n') puts("!!"); /*debugging only */ lnp = #define EXTERN #include "tp.h" char tc[] "/dev/tapx"; char mt[] "/dev/mt0"; int oflag; main(argc,argv) char **argv; { register char c,*ptr; extern cmd(), cmr(),cmx(), cmt(); command = &cmr; flags = 020; /* default is flu */ if ((narg = rnarg = argc) < 2) narg = 2; else { ptr = argv[1]; /* get first argument */ parg = &argv[2]; /* pointer to second argument */ while (c = *ptr++) switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7'lf)) useerr(); if (narg <= 2) useerr(); rddir(); gettape(&delete); wrdir(); check(); } cmr() { if (flags & (flc|flm)) clrdir(); else rddir(); getfiles(); update(); check(); } cmt() { extern taboc(); if (flags & (flc|flf|flw)) useerr(); rddir(); if (flags & flv) printf(" mode uid gid tapa size date time name\n"); gettape(&taboc); check(); } cmx() { extern extract(); if (flags & (flc|flf)) useerr(); rddir(); gettape(&extract); done(); } check() { usage(); done bootstrap block */ #ifndef AGSM if (((reg = rab(tpentry[7].cksum)) != 0) && (flags & flm)) { ndirent = reg; ndentd8 = ndirent>>3; } #endif dptr = &dir[0]; count = ndirent; do { if ((count & 07) == 0) { /* next block */ tread(); tptr = &tpentry[0]; } /*** tp = tptr; p1 = tp + (sizeof tpentry[0])/2; reg = 0; do reg =+ *tp++; while (tpcksum, reg); tp =+ sizeof tpentry[0]/NCPW; } else { reg = sizeof tpentry[0]/NCPW; do *tp++ = 0; /* clear entry */ while (--reg); } } while (--count & 07); } } /* */ tread() { register j, *ptr; if (read(fio,tapeb,512) != 512) { printf("Tape read error\n"); if ((flags & fli) == 0) done(); ptr = tapeb; j = 512/NCPW; do *ptr = 0; { ptr1 = *parg++; ptr2 = &name; while (*ptr2++ = *ptr1++); callout(); } } /* */ expand() { register char *p0, *p1, *save0; int n, fid; if ((fid = open(name,0)) < 0) fserr(); for (;;) { if ((n = read(fid,catlb,16)) != 16){ if (n == 0) { close(fid); return; } fserr(); } if ((catlb[0] | catlb[1]) == 0) /* null entry */ continue; p0 = &name; p1 = &catlb[2]; if (*p1 == '.') /* don't save .xxxx */ continue; while (*p0++); save0 = --p0; /* save loc of \0 sp; while(*sp++ = *lp++); /*move the rest over */ brp = linebuf +(br - genbuf); lnp = linebuf + (lnp - br); rescan(); *(brp-1) ='\0'; return(0); } else continue; backquery: putch(BELL); /***/ } /* end of forloop block */ } /* end of gopen */ getopen() /* calls gopen, deals with multiple lines etc. */ { register char *lp, *sp; if (oflag == EOF) return EOF; /* otherwise, multiple lines */ lp = linebuf; sp = brp; while(*lp++ = *sp++); /*move it down */ sp = genbuf; lp = l: tc[8] = c; mt[7] = c; continue; case 'c': flags =| flc; continue; case 'd': setcom(&cmd); continue; case 'f': flags =| flf; continue; case 'i': flags =| fli; continue; case 'm': flags =| flm; continue; case 'o': oflag++; continue; case 'r': flags =& ~flu; setcom(&cmr); continue; case 't': setcom(&cmt); continue; case 'u': flags =| flu; setcom(&cmr); continue; case 'v': flags =| flv; continue; case 'w': flage(); } done() { printf("End\n"); exit(); } encode(pname,dptr) /* pname points to the pathname * nptr points to next location in nameblk * dptr points to the dir entry */ { register char *np, *sp; sp = pname; dptr->d_namep = np = nptr; if (np > top - NMSIZE) { printf("Out of core\n"); done(); } while (*np++ = *sp++); if (np <= nptr + NMSIZE) nptr = np; else { printf("Pathname too long - %s\nFile ignored\n",nptr); clrent(dptr); } } decode(pname,dptr) /* dptr points to tp,p1); /*** tp = &(tp->mode); ++p1; reg = (sizeof dir[0]/2) - 1; do *p1++ = *tp++; while (--reg); ***/ p1->d_mode = rab(tp->mode); p1->d_uid = tp->uid; p1->d_gid = tp->gid; p1->d_size0 = tp->size0; p1->d_size1 = rab(tp->size1); p1->d_time[0] = 0; p1->d_time[1] = ((rab(tp->time0))<<16) | rab(tp->time1); p1->d_tapea = rab(tp->tapea); } } ++tptr; /* bump to next tent */ reg = dptr; reg->d_mode =& ~0100000; /* mark previous */ dptr = (reg while (--j); } rseeka++; } twrite() { if (write(fio,tapeb,512) != 512) { printf("Tape write error\n"); done(); } ++wseeka; } rseek(blk) { rseeka = blk; if (seek(fio,blk,3) < 0) seekerr(); } wseek(blk) { register amt, b; amt = b = blk; if ((amt =- wseeka) < 0) amt = -amt; if (amt > 25 && b) { seek(fio, b-1, 3); /* seek previous block */ read(fio, &wseeka, 1); /* read next block */ } wseeka = b; if (seek(fio, b, 3) < 0) seekerr(); } seekerr() { printf("Tape seek error\n"); done*/ if (p0[-1] != '/') *p0++ = '/'; while (*p0++ = *p1++); callout(); *save0 = 0; /* restore */ } } fserr() { printf("%s -- Cannot open file\n", name); done(); } callout() { register struct dent *d; register char *ptr1, *ptr0; char *empty; if (stat(name,&statb) < 0) fserr(3); ptr0 = statb.s_flags; if ((ptr0 =& 060000) != 0) { if (ptr0 == 040000) /* directory */ expand(); return; } /* when we reach here we have recursed until we found * an ordinary file. Now we look for inebuf; while (lp < lnp) *sp++ = *lp++; gnp = sp; /* should check whether empty line returned */ oflag = gopen(); return 0; } struct { char byte[]; }; putch(ch) { write(1, &ch.byte[3], 1); } putb(ptr) char *ptr; /*display string */ { register char *p; p = ptr; if(*p == '\0') return; while(*(++p)); write(1,ptr,p-ptr); } help() { puts("\n"); puts(" ^A display Again ^Q next character"); puts(" ^B backup word ^R Release margin"); puts(" ESCAPE ^S re-scan from Start"); puts(" or ^D close s =| flw; continue; case 'x': setcom(&cmx); continue; default: useerr(); } } /* */ optap(); nameblk = nptr = sbrk(0); /* establish top */ top = nameblk+NMSIZE*1024; brk(top); (*command)(); } optap() { extern cmr(); if (oflag) { /* disc file */ tapsiz = 32767; ndirent = MDIRENT; if (narg <= 2) fio = -1; else { if (flags & flc) fio = creat(*parg++, 0666); else fio = open(*parg++, 2); narg--; rnarg--; } } else if ((flags & flm) == 0) { /* DECTAPhe dir entry * name is placed in pname[] */ { register char *p1, *p2; p1 = pname; p2 = dptr->d_namep; while (*p1++ = *p2++); } =+ sizeof dir[0]); } while (--count); if (sum != 0) { printf("Directory checksum\n"); if ((flags & fli) == 0) done(); } bitmap(); } /* */ wrdir() { register reg, *tp,*dp; struct dent *dptr; struct tent *tptr; int count; wseek(0); if (flags & flm) reg = open("/tpboot",0); else reg = open("/usr/mdec/tboot",0); if (reg >= 0) { read(reg,tapeb,512); close(reg); } wab(tpentry[7].cksum, ndirent); dptr = &dir[0]; count = ndirent; for (;;) { twrite(); if (count == 0) return; tp (); } /* */ verify(key) { register c; if ((flags & (flw | flv)) == 0) return(0); repeat: printf("%c %s ", key, name); if ((flags & flw) == 0) { printf("\n"); return(0); } c = getchar(); if (c == 'n' && getchar() == '\n') done(); if (c == '\n') return(-1); if (c == 'y' && getchar() == '\n') return(0); while (getchar() != '\n'); goto repeat; } getfiles() { register char *ptr1, *ptr2; if ((narg =- 2) == 0) { name[0] = '.'; name[1] = '\0'; callout(); } else while (--narg >= 0)it in "dir". */ empty = 0; d = &dir[0]; do { if (d->d_namep == 0) { /* empty directory slot */ if (empty == 0) /* remember the first one */ empty = d; continue; } decode(name1,d); ptr0 = &name; ptr1 = &name1; do if (*ptr0++ != *ptr1) goto cont; while (*ptr1++); /* veritably the same name */ if (flags & flu) { /* check the times */ if (d->d_time[0] > statb.s_modtime[0]) return; if (d->d_time[0] == statb.s_modtime[0] && d->d_time[1] >= statb.s_modtime[line and exit ^V verify spelling"); puts(" ^E display to End ^W next Word"); puts(" ^F delete line Forward ^Z delete word"); puts(" ^H Help # or ^X delete character"); puts(" RUBOUT exit unchanged @ delete line backward\n"); puts(" Other characters (including RETURN) inserted as typed"); } E */ tapsiz = 578; ndirent = 192; fio =open(tc,2); } else { /* MAGTAPE */ tapsiz = 32767; ndirent = MDIRENT; if (command == &cmr) fio = open(mt,1); else fio = open(mt,0); } if (fio < 0) { printf("Tape open error\n"); done(); } ndentd8 = ndirent>>3; edir = &dir[ndirent]; } setcom(newcom) { extern cmr(); if (command != &cmr) useerr(); command = newcom; } useerr() { printf("Bad usage\n"); done(); } /* /* COMMANDS */ cmd() { extern delete(); if (flags & (flm|flc|f#define EXTERN extern #include "tp.h" clrdir() { register j, *p; j = ndirent * (DIRSIZE/NCPW); p = &dir; do (*p++ = 0); while (--j); lastd = 0; } clrent(ptr) { register *p, j; p = ptr; j = DIRSIZE/NCPW; do *p++ = 0; while (--j); if (p == lastd) do { if (--lastd < &dir) { lastd = 0; return; } } while (lastd->d_namep == 0); } /* */ rddir() { register *p1, *tp, reg; struct dent *dptr; struct tent *tptr; int count, sum; sum = 0; clrdir(); rseek(0); tread(); /* Read th= &tpentry[0]; do { tptr = tp; dp = dptr++; /* dptr set to next entry */ if (dp->d_namep) { decode(tp,dp); /*** tp = &(tp->mode); ++dp; do *tp++ = *dp++; while (dp < dptr); ***/ wab(tp->mode, dp->d_mode); tp->uid = dp->d_uid; tp->gid = dp->d_gid; tp->size0 = dp->d_size0; wab(tp->size1, dp->d_size1); reg = dp->d_time[1]>>16; wab(tp->time0, reg); reg = dp->d_time[1]&0xffff; wab(tp->time1, reg); wab(tp->tapea, dp->d_tapea); /*** tp =1]) return; } if (verify('r') < 0) return; goto copydir; cont: continue; } while (++d <= lastd); /* name not found in directory */ if ((d = empty) == 0) { d = lastd +1; if (d >= edir) { printf("Directory overflow\n"); done(); } } if (verify('a') < 0) return; if (d > lastd) lastd = d; encode(name,d); copydir: d->d_mode = statb.s_flags | 0100000; d->d_uid = statb.s_uid; d->d_gid = statb.s_gid; if (flags &flf) { /* fake entry */ statb.s_size0 = 0; statb.s_size1 = 0; } d->d_size0 = statb.s_size1>>16; d->d_size1 = statb.s_size1&0xffff; d->d_time[0] = statb.s_modtime[0]; d->d_time[1] = statb.s_modtime[1]; } /* * checksum calculation */ checksum(string, count) char *string; { register char *p; register c, sum; register halfword; c = count; p = string; sum = 0; while (count--) { halfword = *p++; halfword =| (*p++)<<8; if (count == 32) sum =+ halfword; else sum =- halfword; sum =& 0xffff; } return(sum); } == 0 || (d->d_mode&0100000) == 0) continue; if (d->d_tapea < index) { index = d->d_tapea; id = d; } } while (++d <= lastd); if ((d = id) == 0) return; d->d_mode =& ~0100000; /* change from new to old */ if (d->d_size1 == 0 && d->d_size0 == 0) continue; decode(name,d); wseek(index); if ((id = open(name,0)) < 0) { printf("Can't open %s\n", name); continue; } for (index = BSIZE; index != 0; --index) { if (read(id,tapeb,512) != 512) phserr(); twrite(); } if } while (--count); nused = d; printf("%4d entries\n%4d used\n", nentr, nused); if ((flags & flm)==0) printf("%4d free\n", nfree); printf("%4d last\n", lused); } /* */ taboc(dd) { register mode; register *m; register char *s; int count; if (flags & flv) { mode = dd->d_mode; s = &catlb[9]; *s = 0; for (count = 3; count; --count) { if (mode&1) *--s = 'x'; else *--s = '-'; if (mode&2) *--s = 'w'; else *--s = '-'; if (mode&4) *--s = 'r'; else *--s = '-'; moSelected commands from Chicago distribution ddt - debugging tool (adapted for Interdata) - not thoroughly debugged, but highly useful em - QMC's editor for mortals tp - translation of Level 6 tp by M. Ferentz mc - multicolumn-output filter from Toronto line_width = number( &arg[1] ); continue; case '+': blank_count = number( &arg[1] ); continue; } close( 0 ); if( open(arg,0) < 0 ) error("Can't open '%s'\n",arg); } if( (output=falloc( proto )) < 0 ) error("Can't get temp file\n"); signal(2,&interrupt); lw = biggest = 0; while( buffer_size = read(0,iobuf,512) ){ be = &iobuf[buffer_size]; bp = &iobuf[0]; while( bpd_size0&0377)<<7) | (((d->d_size1)>>9)&0177) gettape(how) int (*how)(); { register char *ptr0, *ptr1; register struct dent *d; int count; do { d = &dir[0]; count = 0; do { if (d->d_namep == 0) continue; decode(name,d); if (rnarg > 2) { ptr0 = &name; ptr1 = *parg; while (*ptr1) if (*ptr0++ != *ptr1++) goto cont; if (*ptr0 && *ptr0 != '/') goto cont; } (*how)(d); /* delete, extract, or taboc */ (index = d->d_size1 & 511) { if (read(id,tapeb,index) != index) phserr(); twrite(); } if (read(id,tapeb,1) != 0) phserr(); close(id); } } phserr() { printf("%s -- Phase error \n", name); } /* */ bitmap() /* place old files in the map */ { register *m, count; register struct dent *d; m = ↦ count = sizeof map/NCPW; do *m++ = 0; while (--count); count = ndirent; d = &dir[-1]; do { d++; if (d->d_namep == 0 || (d->d_mode & 0100000)) continue; if (d->d_size1 || d->d   cc -o ddt -s -n ddt?.c cc -o em -s -n em?.c cc -o mc -s mc.c cc -o tp -s tp?.c : AGSM version of tp: 48-char filenames cc -o tpij -s -DAGSM tp?.c output,iobuf,buffer_size); } n_a_line = ( line_width-1 ) / ( biggest=+blank_count ); blank = sbrk(biggest); be = &blank[biggest]; bp = &blank[0]; while( bp= n_a_line ){ putchar('\n'); cp = 0; } else write(1,blank,bigg /*int mbuf[1024]; /*INSTR*/ int psw 1; int initf 1; main(argc, argv) char *argv[]; { auto f,fct,file; if(argc < 2) { printf("Usage: cpost [-d] file1 file2 ...\n"); exit(); } if(*argv[1] == '-') { fct = argv[1][1] - '0'; if((fct < 1) || (fct > 9)) { printf("-d: 0 < d < 10\n"); exit(); } argv++; argc--; } else { fct = 1; } f = 0; while(++f < argc) { file = open(argv[f], 0); edl(file, fct); close(file); psw = 0; } flsh(0); exit(); } int lno 1; edl(file) { a ++count; cont: continue; } while (++d <= lastd); if (count == 0 && rnarg > 2) printf("%s not found\n", *parg); ++parg; } while (--narg > 2); } delete(dd) { if (verify('d') >= 0) clrent(dd); } /* */ update() { register struct dent *d; register b, last; int first, size; bitmap(); d = &dir[0]; do { if (d->d_namep == 0 || (d->d_mode & 0100000) == 0) continue; if (d->d_size1 == 0 && d->d_size0 == 0) continue; /* find a place on the tape for this file */ size = BSIZE; if _size0) setmap(d); } while (--count); } setmap(dd) { register char *c, *block, *d; char bit; d = dd; /* used for dent pointer then as map index */ c = BSIZE; if (d->d_size1 & 511) c++; block = d->d_tapea; if ((c =+ block) >= tapsiz) maperr(); do { bit = 1 << (block & 7); d = (block>>3) & ~0160000; if (bit & map[d]) maperr(); map[d] =| bit; } while (++block < c); } maperr(nnnnn) { printf("Tape overflow\n"); done(); } /* */ usage() { register reg,count,d; int nused, nentr, nde =>> 3; } if (mode&4) s[2] = 's'; if (mode&2) s[5] = 's'; m = (dd->d_size0<<16)|dd->d_size1; printf("%s%4d%4d%5d%9d ",s,dd->d_uid, dd->d_gid,dd->d_tapea,m); m = localtime(dd->d_time); printf("%2d/%2d/%2d %2d:%2d ",m[5],m[4]+1,m[3],m[2],m[1]); } printf("%s\n", name); } /* */ extract(dd) { register *d, count, id; d = dd; if (d->d_size0==0 && d->d_size1==0) return; if (verify('x') < 0) return; rseek(d->d_tapea); unlink(name); if ((id = creat(name,d->d_mode)) < 0) printf("%s --cpall ddt em mc tp tpij /usr/bin rm ddt em mc tp tpij rm *.o est-(bp-lc+lw)); lw = 0; lc = bp+1; } bp++; } if( be-lc ){ write(1,lc,be-lc); lw =+ be-lc; } } if( cp ) putchar('\n'); unlink(proto); } max( a,b ) { if( bd_size1 & 511) ++size; first = ndentd8; toosmall: ++first; if ((last = first + size) >= tapsiz) maperr(); for (b = first; b < last; ++b) if (map[(b>>3) & ~0160000] & (1<<(b&7))) { first = b; goto toosmall; }; d->d_tapea = first; setmap(d); } while (++d <= lastd); wrdir(); update1(); } /* */ update1() { register struct dent *d; register index, id; for (;;) { d = &dir[0]; index = 32767; id = 0; do { /* find new dent with lowest tape address */ if (d->d_namep free; static lused; bitmap(); d = &dir[0]; count = ndirent; reg = 0; do { if (d->d_namep !=0) reg++; d =+ sizeof dir[0]; } while (--count); nentr = reg; d = 0; /* used to count nused */ reg = ndentd8; ++reg; /* address of first non-directory tape block */ count = tapsiz - reg; do { if (reg >= tapsiz) { printf("Tape overflow\n"); done(); } if (map[(reg>>3) & ~0160000] & (1 << (reg&7))) { d++; lused = reg; } else { if (flags & flm) break; nfree++; } reg++; create error\n", name); count = BSIZE; while (count--) { tread(); if (write(id,tapeb,512) != 512) goto ng; } if (count = d->d_size1 & 511) { tread(); if (write(id,tapeb,count) != count) { /*** smdate(name,"\0,\0"); ??? ***/ ng: printf("%s -- write error\n", name); close(id); return; } } close(id); count = (d->d_gid<<8) | (d->d_uid & 511); chown(name,count); smdate(name,d->d_time); } /* * mc [-line width] [+blank count] [filename] */ /* * Much of the complications in this program * comes from trying to optimize the I/O. */ char proto[] { "/tmp/lf??" }; char iobuf[512]; main( argc,argv ) char *argv[]; { extern interrupt(); register char *bp, *be; register lw; int line_width, blank_count, biggest, n_a_line; int input, output, cp, lc, buffer_size; char *arg, *blank; line_width = 80; blank_count = 2; while( argc-- > 1 ){ arg = argv[argc]; switch( *arg ){ case '-':10 + '0'; u =/ 10; } while( working[p] ) if( working[p++] == '?' ) working[p-1] = '0'; if( (u=creat(working,0444)) >= 0){ copy(working,file); return(u); } } return( -1 ); } copy( in,out ) char *in, *out; { register char *i, *o; i = in; o = out; while( *o++ = *i++ ); return( out ); } interrupt(){ unlink(proto); exit(); } number( s ) char *s; { register c; register char *sp; c = 0; sp = s; while( *sp>='0' && *sp<='9' ) c = c*10 + *sp++ - '0'; if( *sp!='\0' ) goto field; junk: while((*line = get(file)) != '\n') if(*line == '\0') goto done; goto field; done: if(lno == 0) put(0,line,++l); lno = 1; return(0); } gfld(file, buf) char *buf; { char c; buf--; while(*++buf = get(file)) { if((*buf == '\t') || (*buf == '\n')) { c = *buf; *buf = '\0'; return(c); } else { continue; } } return('\0'); } copy(a, b) char *a,*b; { char *c; b--; c = --a; while(*++b = *++a); return(a - c); } comp(a, b) char *a, *b; { /* printf("comp: %s %s\n",a,b); /*DEBUG*/ a--; b--; while(*++a == *++b) { if(*a == '\0') return(1); } return(0); } char buf[512]; int nread 1; get(ifile) int ifile; { char static *ibuf; if(--nread){ return(*ibuf++); } if(nread = read(ifile,buf,512)){ if(nread < 0)goto err; ibuf = buf; return(*ibuf++); } nread = 1; return(0); err: nread = 1; printf("read error\n"); return(0); } int tp[1] 1; int optr[4]; char bsp[512]; char *obuf[1] bsp; int nflush; put(fil,string,n) char *strin0 < d < 10\n"); exit(); } if(argv[1][2] == 'x') { ig = fct-1; } on: argv++; argc--; } else { fct = 3; } f = 0; while(++f < argc) { file = open(argv[f], 0); edf(file, fct); close(file); } flsh(0); exit(); } int lno 1; edf(file, fct) { auto i,j,l; extern lno,etext; char brk,*buf,bufsp[150],line[150]; char extern *sym[]; /* monitor(&main,&etext,&mbuf,1024); /*INSTR*/ for(i = 0; i < fct; i++) *sym[i] = 0200; fields: l = -1; buf = &bufsp; for(i = 0; i < fct; ++i) --nread){ return(*ibuf++); } if(nread = read(ifile,buf,512)){ if(nread < 0)goto err; ibuf = buf; return(*ibuf++); } nread = 1; return(0); err: nread = 1; printf("read error\n"); return(0); } int tp[1] 1; int optr[4]; char bsp[512]; char *obuf[1] bsp; int nflush; put(fil,string,n) char *string; { int i; char *o; /*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ string--; if((i = optr[fil] + n - 512) >= 0) { n =- i; o = &obuf[fil][optr[fil]] -1; while(--n >= 0) *++o = *!= 0 && curfl <= 8) if(curf[curfl++] == '/') curfl = 1; curf[curfl++] = '\t'; if(curfl == 10) curf[9] = -1; /* printf("%s %d\n",curf,curfl);/*DEBUG*/ lno = 1; driver(); close(file); } for(j = 0; j < 4;) { flsh(j,0); close(tp[j++]); } /* monitor(0); /*INSTR*/ /* dexit(); /*INSTR*/ /* times(tbuf); /*INSTR*/ /* tm1 = tbuf[15]/6; /*INSTR*/ /* tm2 = tbuf[19]/6; /*INSTR*/ /* tm3 = tbuf[23]/6; /*INSTR*/ /* printf("Prep: %d %d %d\n",tm1,tm2,tm3); /*INSTR*/ if(utmp) exit(); fn = "/bin.nsym = 0; xtab.curb = 1; itab.hptr = &ipsp; itab.symt = &issp; itab.hsiz = PTRI; itab.ssiz = CHARI; itab.nsym = 0; itab.curb = 1; if((fi = open(gtab,0)) < 0) { printf("Cannot open grammar table; see lem\n"); dexit(); } i = -1; while(++i < NUMS) if(read(fi,tab[i].cl,512) < 512) { printf("Bad grammar table.\n"); dexit(); } close(fi); if((fi = open(ignonl,0)) < 0) { printf("Cannot open ignore/only file: %s\n",ignonl); dexit(); } if((read(fi,b,6) == 6) && (b[0] == 0100200ror(a) { printf("Error %d\n",a); dexit(); } dexit() { extern nflush; /* printf("nflush = %d\n",nflush); /*DEBUG*/ if(tp[0] > 0 && utmp == 0) { unlink(tmp[0]); unlink(tmp[1]); unlink(tmp[2]); unlink(tmp[3]); unlink(tmp[4]); } exit(); } callsys(f,v) char f[],*v[]; { int t,status,i; if((t = fork()) == 0) { execv(f,v); printf("Can't find %s\n",f); exit(1); } else { if(t == -1) { printf("Try again\n"); return(1); } } while(t != wait(&status)); /* printf("Status = %o, %sg; { int i; char *o; /*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ string--; if((i = optr[fil] + n - 512) >= 0) { n =- i; o = &obuf[fil][optr[fil]] -1; while(--n >= 0) *++o = *++string; optr[fil] = 512; flsh(fil); n = i; } o = &obuf[fil][optr[fil]] - 1; optr[fil] =+ n; while(--n >= 0) { *++o = *++string; } return(0); } flsh(fil) { extern tp[]; if(optr[fil] <= 0) return(optr[fil]); nflush++; if(write(tp[fil],obuf[fil],optr[fil]) != optr[fil]) return(-1); optr[fil] ={ buf--; swt: switch(*++buf = get(file)) { default: if(esw && *buf >= 'A' && *buf <= 'Z' && i == 0) *buf =| 040; goto swt; case -1: *buf = ' '; case '\t': if(i == ig) continue; brk = *buf; *buf = '\0'; buf = &bufsp; if(comp(buf, sym[i])) { if(esw && i == 0) { line[0] = line[1] = '\t'; l = 1; goto rest; } line[++l] = '\t'; continue; } else { copy(buf, sym[i]); l =+ copy(buf, &line[++l]); line[-++string; optr[fil] = 512; flsh(fil); n = i; } o = &obuf[fil][optr[fil]] - 1; optr[fil] =+ n; while(--n >= 0) { *++o = *++string; } return(0); } flsh(fil) { extern tp[]; if(optr[fil] <= 0) return(optr[fil]); nflush++; if(write(tp[fil],obuf[fil],optr[fil]) != optr[fil]) return(-1); optr[fil] = 0; return(0); } /sort"; av[0] = "sort"; av[1] = "-a"; av[3] = "-o"; av[5] = 0; for(i = 0; i < 4; i++) { av[4] = av[2] = tmp[i]; callsys(fn,av); if(utmp) break; } /* times(tbuf); /*INSTR*/ /* tm1 = tbuf[27]/6; /*INSTR*/ /* tm2 = tbuf[31]/6; /*INSTR*/ /* tm3 = tbuf[35]/6; /*INSTR*/ /* printf("Sort: %d %d %d\n",tm1,tm2,tm3); /*INSTR*/ if(usw) { fn = "/usr/bin/upost"; av[0] = "upost"; i = 0; } else { fn = "/usr/bin/crpost"; av[0] = "crpost"; av[1] = cross? "-4x": "-3"; i = 1; } j = -1; while()) { if(read(fi,itab.hptr,b[1]) < b[1]) { printf("Cannot read ignore/only file: %s\n",ignonl); dexit(); } if(read(fi,itab.symt,b[2]) < b[2]) { printf("Cannot read ignore/only file: %s\n",ignonl); dexit(); } close(fi); } else { close(fi); compile(); } if((signal(1,1) & 1) == 0) signal(1,&dexit); if((signal(2,1) & 1) == 0) signal(2,&dexit); if((signal(3,1) & 1) == 0) signal(3,&dexit); /* signal(4,&dexit); signal(5,&dexit); signal(6,&dexit); signal(7,&dexit); signal(8,&dexit\n",status,f); /*DEBUG*/ if((t = (status & 0377)) != 0) { if(t != 2) { printf("Fatal error in %s\n",f); printf("t = %d\n",t); } dexit(); } return((status>>8) & 0377); } flags(argv) char *argv[]; { int j,xx; char *ap; j = 1; ap = argv[1]; while(*++ap != '\0') { switch(*ap) { default: printf("Unrecognized flag: %c\n",*ap); dexit(); case '1': /* Symbol first */ order = 1; continue; case '2': /* Current file first */ order = 2; continue; case '3': 0; return(0); } -l] = brk; if(l < 8 && esw && i == 0) line[++l] = '\t'; j = i; while(++j < fct) *sym[j] = 0200; continue; } case '\n': lno++; brk = *buf; *buf = '\0'; buf = &bufsp; if(comp(buf, sym[i])) { goto fields; } else { copy(buf, sym[i]); l =+ copy(buf, &line[++l]); line[--l] = '\n'; j = i; while(++j < fct) *sym[j] = 0; goto out; } case '\0': goto fexit; } } rest: while((line[++l] = get(file)) !=# #define EXTERN extern # include "../mcons.h" # include "../ccmn.h" /*int mbuf[1024]; /*INSTR*/ /*int tbuf[36]; /*INSTR*/ int (*acts[])() {0, &coll, &save, &out, &asym, &asw, &csym, &csw, &incl, &decl, &sk2, &sk, &tabs, &semi }; char *tmp[5] {"/tmp/crt0a", "/tmp/crt1a", "/tmp/crt2a", "/tmp/crt3a", "/tmp/crt4a" }; char *ignonl "/usr/lib/aign"; char *gtab "/usr/lib/atab"; main(argc,argv) char *argv[]; { auto i,j,tm1,tm2,tm3; char *fn,*av[8]; /* exter++j < 4) { av[++i] = tmp[j]; if(utmp) break; } av[++i] = 0; callsys(fn,av); /* times(tbuf); /*INSTR*/ /* tm1 = tbuf[27]/6 - tm1; /*INSTR*/ /* tm2 = tbuf[31]/6 - tm2; /*INSTR*/ /* tm3 = tbuf[35]/6 - tm3; /*INSTR*/ /* printf("Post: %d %d %d\n",tm1,tm2,tm3); /*INSTR*/ dexit(); } driver() { auto p; top: l = -1; while((c = line[++l] = getc(ibuf)) != -1) { if(l >= 131) { printf("Line too long: %d %s\n",lno,curf); dexit(); } if(c & 0200) { printf("Illegal character: %o line %d\n",$%&!'(. /* Current symbol first */ order = 3; continue; case 'a': /* Assembler */ cflag = 0; continue; case 'c': /* C */ gtab = "/usr/lib/ctab"; if(!xx) ignonl = "/usr/lib/cign"; cflag = 1; continue; case 'e': /* English */ gtab = "/usr/lib/etab"; if(!xx) ignonl = "/usr/lib/eign"; continue; case 'i': /* Ignore file */ if(!xx) { xx = 1; only = 0; ignonl = argv[++j]; } continue; case 'l': /* Line numbers in col. 3 */ /*int mbuf[1024]; /*INSTR*/ int ig 100; int esw; int initf 1; char ssp[270]; char *sym[] {ssp, ssp + 30, ssp + 60, ssp + 90, ssp + 120, ssp + 150, ssp + 180, ssp + 210, ssp + 240, ssp + 270 }; main(argc, argv) char *argv[]; { auto f,fct,file,i; if(argc < 2) { printf("Usage: crpost [-d] file1 file2 ...\n"); exit(); } if(*argv[1] == '-') { if(argv[1][1] == 'E') { fct = 3; esw = 1; goto on; } fct = argv[1][1] - '0'; if((fct < 1) || (fct > 9)) { printf("-d: '\n') if(line[l] == '\0') goto fexit; lno++; out: if(*line != '\t') { put(0,"\n",1); lno++; } put(0,line,++l); goto fields; fexit: /* monitor(0); /*INSTR*/ return(0); } copy(a, b) char *a,*b; { char *c; b--; c = --a; while(*++b = *++a); return(a - c); } comp(a, b) char *a, *b; { /* printf("comp: %s %s\n",a,b); /*DEBUG*/ a--; b--; while(*++a == *++b) { if(*a == '\0') return(1); } return(0); } char buf[512]; int nread 1; get(ifile) int ifile; { char static *ibuf; if(n etext; /*INSTR*/ /* monitor(&main,&etext,&mbuf,1024); /*INSTR*/ if(argc < 2) { printf("Usage: cref [-aceilosux] file1 ...\n"); exit(); } lbuf[4] = '\t'; if(*argv[1] == '-') { j = flags(argv); argv =+ j; argc =- j; } init(); i = 0; while(++i < argc) { curs[0] = '_'; curs[1] = '\t'; curs[4] = '\t'; cursl = 2; if(fopen(argv[i],ibuf1) < 0) { printf("Can't open %s\n",argv[i]); dexit(); } ibuf = ibuf1; curf[0] = '\t'; curfl = 1; while((curf[curfl] = *argv[i]++) c,lno); dexit(); } if(fl) { if((*flag[fl])()) continue; } /*printf("cs = %d cc = %c ca = %d\n",cs,c,tab[cs].cl[c]); /*DEBUG*/ if(p = tab[cs].cl[c]) (*acts[p])(); continue; } if(ibuf == ibuf1) return; ibuf = ibuf1; goto top; } init() { int b[3]; auto fi,i; extern coll(),save(),out(),asym(),asw(),csym(),csw(); extern incl(),decl(),sk(),sk2(); extern dexit(); ibuf1 = &ib1; ibuf2 = &ib2; xtab.hptr = &xpsp; xtab.symt = &xssp; xtab.hsiz = PTRX; xtab.ssiz = CHARX; xtab); signal(10,&dexit); signal(11,&dexit); signal(12,&dexit); */ if(utmp == 0) { while((tp[4] = creat(tmp[4],0)) < 0) tmp[4][9]++; close(tp[4]); tmp[0][9] = tmp[4][9]; tmp[1][9] = tmp[4][9]; tmp[2][9] = tmp[4][9]; tmp[3][9] = tmp[4][9]; tp[0] = creat(tmp[0],CREATC); tp[1] = creat(tmp[1],CREATC); tp[2] = creat(tmp[2],CREATC); tp[3] = creat(tmp[3],CREATC); } else { if((tp[0] = creat(utmp,CREATC)) < 0) { printf("Can't create user's temp file.\n"); exit(); } } return; } er cross = 0; continue; case 'o': /* Only file */ if(!xx) { xx = 1; only = 1; ignonl = argv[++j]; } continue; case 's': /* Symbols in col. 3 */ cross = 1; continue; case 't': utmp = argv[++j]; tmp[0] = argv[j]; continue; case 'u': /* Unique symbols only */ usw = 1; continue; case 'x': /* C externals */ xsw = 1; gtab = "/usr/lib/ctab"; if(!xx) ignonl = "/usr/lib/cign"; cflag = 1; continue; } } return(j); } compile() { char buf[40],*b; int i,v; fopen(ignonl,ibuf1); b = buf - 1; while((*++b = getc(ibuf1)) != -1) { if(*b == '\n') { *b = '\0'; search(buf,b - buf,&itab,1); b = buf - 1; } else { if(*b == '\t') { v = 0; while((i = getc(ibuf1)) != -1) { if(i == '\n') break; v = v*10 + (i - '0'); } search(buf,b - buf,&itab,v); b = buf - 1; } else { if((b - buf) > 39) { printf("Ignore/only symbol too long"); dexit(); } } } } close= 1; goto no; } } if(hlevel && (val == 4 || val == 3)) type = 1; if(!val == !only) goto yes; no: *(ptr->beg + ptr->ct) = ptr->term; return(0); yes: tt = t1; while(tt) if(comp(ptr->beg,temp[--tt].beg)) goto no; t1++; return(1); } out() { auto i,ct; if(cs == COLLECT) save(); ct = t1; while(ct--) temp[ct].beg[temp[ct].ct] = temp[ct].term; while(t1--) { /*printf("t1 = %d beg = %d ct = %d\n",t1,temp[t1].beg,temp[t1].ct); /* DEBUG */ switch(order) { case 1: if(utmp) ': gch[fl] = '\''; if(c == '\\') { flag[++fl] = &asw; gch[fl] = c; return(1); } return(1); case '<': if(c == '\n') out(); if(c == '\\') { flag[++fl] = &asw; gch[fl] = c; return(1); } if(c != '>') return(1); break; case '/': if(c != '\n') return(1); case '\\': if(c == '\n') out(); } fl--; return(1); } csw() { if(cs == COLLECT) save(); switch(gch[fl]) { case 0: if(c == '*') if(line[l - 1] != '/') return(1); gch[++flsl) curs[i] = *p++; if(cursl < 8) curs[cursl++] = '\t'; else curs[cursl++] = -1; } hlevel = 1; } cs = SKIP; } dfile(a) char *a; { if(*a < 'c') return(0); if(*a < 'h') return(1); if(*a < 'r') return(2); return(3); } sk2() { cs = SKIP2; } sk() { cs = SKIP; } tabs() { if(l == 0) l = -1; } search(symbol,length,params,install) char *symbol; int length; struct htab *params; int install; { char *sp,*p; static int curb,*hptr,hsiz,nsym,ssiz; static char *symt; auto h,i,int bct[4]; int optr[4]; char bsp[2048]; char *obuf[4] {bsp, &bsp[512], &bsp[1024], &bsp[1536] }; int nflush; put(fil,string,n) char *string; { extern utmp; int i; char *o; /*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ string--; if((i = optr[fil] + n - 512) >= 0) { n =- i; o = &obuf[fil][optr[fil]] -1; while(--n >= 0) *++o = *++string; optr[fil] = 512; flsh(fil); n = i; } o = &obuf[fil][optr[fil]] - 1; optr[fil] =+ n; while(--n >= 0) { *++o = *++string; } rellect/1/cont; collect/2/cont; collect/3/cont; collect/4/cont; collect/5/cont; collect/6/cont; collect/7/cont; collect/8/cont; collect/9/cont; collect/0/cont; collect/./cont; collect/_/cont; collect/ /out; skip/'/agobl; skip/"/agobl; skip/= 8) { ct = 8; *curf = -1; } else { *curf = '\t'; } put(i,temp[t1].beg,ct); put(i,curf,curfl); if(cross) put(i,curs,cursl); conf(lno,4,lbuf); put(i,lbuf,5); break; case 2: i = dfile(curf+1); put(i,curf+1,curfl-1); if(cross) put(i,curs,cursl); else { conf(lno,4,lbuf); put(i,lbuf,5); } if((ct = temp[t1].ct) >= 8) { put(i,temp[t1].beg,8); put] = c; flag[fl] = &csw; return(1); case '*': if(c == '\n') out(); if(c == '/' && line[l - 1] == '*') break; return(1); case '\'': case '"': if(c == gch[fl]) break; if(c == '\\') { gch[++fl] = c; flag[fl] = &csw; } return(1); case '\\': break; } fl--; return(1); } incl() { /* printf("incl: l = %d hl = %d dl = %d\n",level,hlevel,dlevel);/*DEBUG*/ if(cs == COLLECT) save(); if(hlevel) { hlevel = 0; level++; } else { dlevel++; } cs = SKIj,k; if(hptr != params->hptr) { hptr = params->hptr; hsiz = params->hsiz; symt = params->symt; ssiz = params->ssiz; curb = params->curb; nsym = params->nsym; } symbol[length] = '\0'; sp = symbol; i = length; h = 1; while(i--) h =* *sp++; if(h == 0100000) { h = 1; } else { h = h<0?(-h)%hsiz:h%hsiz; } if(h == 0) h++; /* printf("%s %d\n",symbol,h); /*DEBUG*/ while((p = &symt[hptr[h]]) > symt) { j = length + 2; sp = symbol; while(--j) { if(*p++ != *sp++) goto no; }turn(0); } flsh(fil) { extern tp[],utmp; if(optr[fil] <= 0) return(optr[fil]); if(bct[fil]++ >= 128 && utmp == 0) { printf("Wraparound temp file %d\n",fil); dexit(); } nflush++; if(write(tp[fil],obuf[fil],optr[fil]) != optr[fil]) return(-1); optr[fil] = 0; return(0); } ip/p/coll; skip/q/coll; skip/r/coll; skip/s/coll; skip/t/coll; skip/u/coll; skip/v/coll; skip/w/coll; skip/x/coll; skip/y/coll; skip/z/coll; skip/A/coll; skip/B/coll; skip/C/coll; skip/D/coll; skip/E/coll; skip/F/coll; skip/G/coll; skip/H/coll; skip/I/coll; skip/J/coll; skip/K/coll; skip/L/coll; skip/M/coll; skip/N/coll; skip/O/coll; skip/P/coll; skip/Q/coll; skip/R/coll; skip/S/coll; skip/T/coll; skip/U/coll; skip/V/coll; skip/W/coll; skip/X/coll; skip/Y/coll; skip/Z/coll; skip/0/sk2; skip/1/sk2; skip/2/sk# # define EXTERN # include "../mcons.h" # include "../ccmn.h" # define SKIP 0 # define COLLECT 1 # define SKIP2 2 int cross 1; int order 1; char mone -1; coll() { cs = COLLECT; temp[t1].beg = &line[l]; return; } save() { extern wspace(); line[l] = '\0'; temp[t1].ct = &line[l] - temp[t1].beg; temp[t1].term = c; if((c == ' ' || c == '\t') && cflag) { gch[++fl] = mone; flag[fl] = &wspace; } else { sav1(); } return; } sav1() { extern only; struct tempent *ptr; int a,tt,val; if(cfla(i,&mone,1); } else { put(i,temp[t1].beg,ct); put(i,"\t",1); } if(cross) { conf(lno,4,lbuf); put(i,lbuf,5); } break; case 3: i = dfile(curs); put(i,curs,cursl); if((ct = temp[t1].ct) >= 8) { put(i,temp[t1].beg,8); *curf = -1; } else { put(i,temp[t1].beg,ct); *curf = '\t'; } put(i,curf,curfl); conf(lno,4,lbuf); put(i,lbuf,5); } put(i,line,l + 1); } t1 = 0; l = -1; lno++; cs = SKIP; return; } asym() {4:)/5;*0<+17= return(*p); no: h = (h + h)%hsiz; } if(install) { if(++nsym >= hsiz) { printf("Too many symbols.\n"); dexit(); } hptr[h] = curb; length++; if((curb + length) >= ssiz) { printf("Too many characters in symbols.\n"); dexit(); } while(length--) symt[curb++] = *symbol++; symt[curb++] = install; params->curb = curb; params->nsym = nsym; } return(0); } conf(n,width,buf) char *buf; { auto i,a; i = width; while(i--) buf[i] = ' '; buf[(a = n/10)?conf(a,--width,buskip collect save skip2 sk cont coll save out asym agobl csym cgobl incl decl sk2 sk collect/'/agobl; collect/"/agobl; collect/beg,ptr->ct,&itab,0); if(xsw) { switch(val) { case 0: if((!level&&!hlevel)||(c == '(')||xtrn || ssw) { search(ptr->beg,ptr->ct,&xtab,1); goto yes; } else { if(search(ptr->beg,ptr->ct,&xtab,0)) goto yes; } goto no; case 1: goto no; case 2: xtrn = 1; goto no; case 3: if(hlevel) type = 1; if(!level&&!hlevel) ssw = 1; goto no; case 4: if(hlevel) type int i; char *p; if(cs == COLLECT) { if(cross) { p = temp[t1].beg; cursl = &line[l] - p; cursl = cursl>8?8:cursl; i = -1; while(++i < cursl) curs[i] = *p++; if(cursl < 8) curs[cursl++] = '\t'; else curs[cursl++] = -1; } save(); } cs = SKIP; } asw() { switch(gch[fl]) { case 0: if(cs == COLLECT) save(); cs = SKIP; flag[++fl] = &asw; gch[fl] = c; return(1); case '\'': if(c == '\\') { gch[fl] = c; return(1); } break; case '"P; } decl() { /* printf("decl: l = %d hl = %d dl = %d\n",level,hlevel,dlevel);/*DEBUG*/ if(cs == COLLECT) save(); cs = SKIP; if(dlevel) { dlevel--; return; } if(--level > 0) return; curs[0] = '_'; curs[1] = '\t'; cursl = 2; level = 0; return; } csym() { int i; char *p; /* printf("csym: l = %d hl = %d dl = %d\n",level,hlevel,dlevel);/*DEBUG*/ p = temp[t1].beg; if(cs == COLLECT && level == 0) { if(cross) { cursl = temp[t1].ct; cursl = cursl>8?8:cursl; i = -1; while(++i < curf):--width] = n%10 + '0'; return(++width); } comp(a,b) char *a; char *b; { a--; b--; while(*++a == *++b) if(*a == '\0') return(1); return(0); } semi() { if(cs == COLLECT) save(); if(only) return; xtrn = 0; if(!level) { ssw = 0; if(!type) { hlevel = 0; curs[0] = '_'; curs[1] = '\t'; cursl = 2; } type = 0; } cs = SKIP; } wspace() { if(c == ' ' || c == '\t') return(1); sav1(); fl--; return(0); } llect/u/cont; collect/v/cont; collect/w/cont; collect/x/cont; collect/y/cont; collect/z/cont; collect/A/cont; collect/B/cont; collect/C/cont; collect/D/cont; collect/E/cont; collect/F/cont; collect/G/cont; collect/H/cont; collect/I/cont; collect/J/cont; collect/K/cont; collect/L/cont; collect/M/cont; collect/N/cont; collect/O/cont; collect/P/cont; collect/Q/cont; collect/R/cont; collect/S/cont; collect/T/cont; collect/U/cont; collect/V/cont; collect/W/cont; collect/X/cont; collect/Y/cont; collect/Z/cont; co/E/cont; skip2/F/cont; skip2/G/cont; skip2/H/cont; skip2/I/cont; skip2/J/cont; skip2/K/cont; skip2/L/cont; skip2/M/cont; skip2/N/cont; skip2/O/cont; skip2/P/cont; skip2/Q/cont; skip2/R/cont; skip2/S/cont; skip2/T/cont; skip2/U/cont; skip2/V/cont; skip2/W/cont; skip2/X/cont; skip2/Y/cont; skip2/Z/cont; skip2/0/cont; skip2/1/cont; skip2/2/cont; skip2/3/cont; skip2/4/cont; skip2/5/cont; skip2/6/cont; skip2/7/cont; skip2/8/cont; skip2/9/cont; skip2/ /out; skip2/\//agobl; skip collect save skip2 cont coll save out egobl hyphen pno skip//pno; skip/ /out; skip/a/coll; skip/b/coll; skip/c/coll; skip/d/coll; skip/e/coll; skip/f/coll; skip/g/coll; skip/h/coll; skip/i/coll; skip/j/coll; skip/k/coll; skip/l/coll; skip/m/coll; skip/n/coll; skip/o/coll; skip/p/coll; skip/q/coll; skip/r/coll; skip/s/coll; skip/t/coll; skip/u/coll; skip/v/coll; skip/w/coll; skip/x/coll; skip/y/coll; skip/z/coll; skip/A/coll; skip/B/coll; skip/C/coll; skip/D/coll; skip/E/coll; skip/F/coll; skip/G/col skip2/D/coll; skip2/E/coll; skip2/F/coll; skip2/G/coll; skip2/H/coll; skip2/I/coll; skip2/J/coll; skip2/K/coll; skip2/L/coll; skip2/M/coll; skip2/N/coll; skip2/O/coll; skip2/P/coll; skip2/Q/coll; skip2/R/coll; skip2/S/coll; skip2/T/coll; skip2/U/coll; skip2/V/coll; skip2/W/coll; skip2/X/coll; skip2/Y/coll; skip2/Z/coll; l; skip/f/coll; skip/g/coll; skip/h/coll; skip/i/coll; skip/j/coll; skip/k/coll; skip/l/coll; skip/m/coll; skip/n/coll; skip/o/coll; skip/p/coll; skip/q/coll; skip/r/coll; skip/s/coll; skip/t/coll; skip/u/coll; skip/v/coll; skip/w/coll; skip/x/coll; skip/y/coll; skip/z/coll; skip/A/coll; skip/B/coll; skip/C/coll; skip/D/coll; skip/E/coll; skip/F/coll; skip/G/coll; skip/H/coll; skip/I/coll; skip/J/coll; skip/K/coll; skip/L/coll; skip/M/coll; skip/N/coll; skip/O/coll; skip/P/coll; skip/Q/coll; skip/R/coll; sk# include "../mcons.h" struct { int cl[NUMC]; }tab[NUMS]; char state[NUMS][SIZS]; char class[NUMC][SIZC]; char act[NUMA][SIZA]; char def[NUMS][SIZA]; char temp[SIZA]; char *st[NUMS]; char *df[NUMS]; char *cl[NUMC]; char *ac[NUMA]; int t1; int t2; main(argc,argv) char **argv; { extern fin; char fl,nlfl,c,bfl,fo,brk; int cs,ca,cc,i,j,cd; if(argc != 3) { printf("Usage: mtab input output\n"); exit(); } if((fo = creat(argv[2],0644)) < 0) { printf("Output file.\n"); exit(); } if((fin = oault: error(1); } case ';': if(fl != 2) error(2); temp[++i] = '\0'; i = -1; ca = find(ac,temp,NUMA); /*printf("%o %o %o\n",cs,cc,ca); /*DEBUG*/ tab[cs].cl[cc] = ca; fl = 0; continue; } } i = -1; while(++i < NUMS) write(fo,tab[i].cl,512); } error(a) { printf("Error %d\n",a); exit(); } find(a,b,c) char (*a[]); /*** was 'char (*a[])[]' ***/ char b[]; int c; { int i,j; /* printf("%s\n",b); /*DEBUG*/ i = -1; while(++i < c) { /* printf(" %s\); close(tp[0]); /* monitor(0); /*INSTR*/ /* dexit(); /*INSTR*/ /* times(tbuf); /*INSTR*/ /* tm1 = tbuf[0]/6; /*INSTR*/ /* tm2 = tbuf[1]/6; /*INSTR*/ /* printf("Prep: %d %d\n", tm1, tm2); /*INSTR*/ /* exit(); /*DEBUG*/ fn = "/bin/sort"; av[0] = "sort"; av[1] = tmp[0]; av[2] = "-o"; av[3] = tmp[0]; av[4] = 0; callsys(fn, av); /* times(tbuf); /*INSTR*/ /* tm1 = tbuf[3]/6; /*INSTR*/ /* tm2 = tbuf[5]/6; /*INSTR*/ /* printf("Sort: %d %d\n", tm1, tm2); /*INSTR*/ if(usw) { fn = "/usr/bin/uposl; skip/H/coll; skip/I/coll; skip/J/coll; skip/K/coll; skip/L/coll; skip/M/coll; skip/N/coll; skip/O/coll; skip/P/coll; skip/Q/coll; skip/R/coll; skip/S/coll; skip/T/coll; skip/U/coll; skip/V/coll; skip/W/coll; skip/X/coll; skip/Y/coll; skip/Z/coll; collect/'/cont; collect/-/hyphen; collect/ /out; collect/a/cont; collect/b/cont; collect/c/cont; collect/d/cont; collect/e/cont; collect/f/cont; collect/g/cont; collect/h/cont; collect/i/cont; collect/j/cont; collect/k/cont; collect/l/cont; collect/m/cont; colleskip collect save skip2 sk cont coll save out asym agobl csym cgobl incl decl sk2 sk tab semi collect/\;/semi; collect/_/cont; collect/{/incl; collect/}/decl; collect/'/cgobl; collect/\\/cgobl; collect/"/cgobl; collect/a/cont; collect/b/cont; collect/c/cont; collect/d/cont; collect/e/cont; collect/f/cont; collect/g/cont; collect/h/cont; collect/i/cont; collect/j/cont; collect/k/cont; collect/l/cont; collect/m/cont; collect/n/cont; collect/o/cont; collect/p/cont; collect/q/cont; collect/r/cont; collect/s/cip/S/coll; skip/T/coll; skip/U/coll; skip/V/coll; skip/W/coll; skip/X/coll; skip/Y/coll; skip/Z/coll; skip2/{/incl; skip2/}/decl; skip2/a/cont; skip2/b/cont; skip2/c/cont; skip2/d/cont; skip2/e/cont; skip2/f/cont; skip2/g/cont; skip2/h/cont; skip2/i/cont; skip2/j/cont; skip2/k/cont; skip2/l/cont; skip2/m/cont; skip2/n/cont; skip2/o/cont; skip2/p/cont; skip2/q/cont; skip2/r/cont; skip2/s/cont; skip2/t/cont; skip2/u/cont; skip2/v/cont; skip2/w/cont; skip2/x/cont; skip2/y/cont; skip2/z/cont; skip2/A/cont; skippen(argv[1],0)) < 0) { printf("Input file.\n"); exit(); } nlfl = 1; i = -1; while(brk = rword()) { switch (brk) { case '\n': if(nlfl) { move(temp,state[++i]); st[i] = &state[i]; } else { move(temp,def[i]); df[i] = &def[i]; nlfl = 1; } continue; case ' ': if(nlfl) { move(temp,state[++i]); st[i] = &state[i]; nlfl = 0; } else { error(7); } continue; } } i = 128; while(--i) { class[i][0] = i; class[i][1] =n",a[i]); /*DEBUG*/ j = 0; /* printf("b = %c\ta = %c\n",b[0],a[i][0]); /*DEBUG*/ while(b[j] == a[i][j]) { if(b[j] == '\0') goto found; j++; } } found: return(i); } rword() { char c; int ct; ct = -1; while(c = getchar()) { switch(c) { default: temp[++ct] = c; continue; case '\n': if(ct == -1) return('\0'); case ' ': temp[++ct] = '\0'; return(c); } } } move(a,b) char *a; char *b; { while((*b++ = *a++) != '\0'); return; } t"; av[0] = "upost"; i = 0; } else if(count) { fn = "count"; av[0] = "count"; i = 0; } else { fn = "/usr/bin/crpost"; av[0] = "crpost"; av[1] = "-E"; i = 1; } av[++i] = tmp[0]; av[++i] = 0; callsys(fn,av); /* times(tbuf); /*INSTR*/ /* tm1 = tbuf[3]/6 - tm1; /*INSTR*/ /* tm2 = tbuf[5]/6 - tm2; /*INSTR*/ /* printf("Post: %d %d\n", tm1, tm2); /*INSTR*/ dexit(); } driver() { auto p; top: l = -1; while((c = line[++l] = getc(ibuf)) != -1) { /* printf("driver: c = %o l = %d\n",c,ct/n/cont; collect/o/cont; collect/p/cont; collect/q/cont; collect/r/cont; collect/s/cont; collect/t/cont; collect/u/cont; collect/v/cont; collect/w/cont; collect/x/cont; collect/y/cont; collect/z/cont; collect/A/cont; collect/B/cont; collect/C/cont; collect/D/cont; collect/E/cont; collect/F/cont; collect/G/cont; collect/H/cont; collect/I/cont; collect/J/cont; collect/K/cont; collect/L/cont; collect/M/cont; collect/N/cont; collect/O/cont; collect/P/cont; collect/Q/cont; collect/R/cont; collect/S/cont; colleont; collect/t/cont; collect/u/cont; collect/v/cont; collect/w/cont; collect/x/cont; collect/y/cont; collect/z/cont; collect/A/cont; collect/B/cont; collect/C/cont; collect/D/cont; collect/E/cont; collect/F/cont; collect/G/cont; collect/H/cont; collect/I/cont; collect/J/cont; collect/K/cont; collect/L/cont; collect/M/cont; collect/N/cont; collect/O/cont; collect/P/cont; collect/Q/cont; collect/R/cont; collect/S/cont; collect/T/cont; collect/U/cont; collect/V/cont; collect/W/cont; collect/X/cont; collect/Y/c2/B/cont; skip2/C/cont; skip2/D/cont; skip2/E/cont; skip2/F/cont; skip2/G/cont; skip2/H/cont; skip2/I/cont; skip2/J/cont; skip2/K/cont; skip2/L/cont; skip2/M/cont; skip2/N/cont; skip2/O/cont; skip2/P/cont; skip2/Q/cont; skip2/R/cont; skip2/S/cont; skip2/T/cont; skip2/U/cont; skip2/V/cont; skip2/W/cont; skip2/X/cont; skip2/Y/cont; skip2/Z/cont; skip2/1/cont; skip2/2/cont; skip2/3/cont; skip2/4/cont; skip2/5/cont; skip2/6/cont; skip2/7/cont; skip2/8/cont; skip2/9/cont; skip2/0/cont; skip2/./cont; skip2/ /out; '\0'; cl[i] = &class[i]; } cl[0] = &class[0]; bfl = nlfl = 0; t1 = 0; t2 = -1; while(c = getchar()) { switch(c) { default: if(t1 >= NUMA) error(4); bfl = nlfl = 0; act[t1][++t2<8?t2:7] = c; continue; case '\n': if(nlfl) break; nlfl = 1; case ' ': if(bfl) continue; bfl = 1; act[t1][++t2<8?t2:7] = '\0'; ac[t1] = &act[t1]; t1++; t2 = -1; continue; } break; } if(c == '\0') exit(); i = -1; while(++i < NUMS) { if(df[i]) { c# #define EXTERN # include "../econs.h" # include "../ecmn.h" /*int mbuf[1024]; /*INSTR*/ /*int tbuf[12]; /*INSTR*/ int (*acts[])() {0, &coll, &save, &out, &error, &hyphen, &pno }; char *tmp[2] {"/tmp/crt0a", "/tmp/crt1a" }; char *ignonl "/usr/lib/eign"; char *gtab "/usr/lib/etab"; char mone -1; main(argc,argv) char *argv[]; { auto i,j,tm1,tm2,tm3; char *fn,*av[8]; /* extern etext; /*INSTR*/ /* monitor(&main,&etext,&mbuf,1024); /*INSTR*/ if(*argv[1] == '-') { j = flags(l); /*DEBUG*/ if(l >= 299) { printf("Line too long: %d.\n",lno); dexit(); } if(c & 0200) { printf("Illegal character: %o line %d\n",c,lno); dexit(); } if(fl) { if((*flag[fl])()) continue; } /*printf("cs = %d cc = %c ca = %d\n",cs,c,tab[cs].cl[c]); /*DEBUG*/ if(p = tab[cs].cl[c]) (*acts[p])(); continue; } if(ibuf == ibuf1) return; ibuf = ibuf1; goto top; } init() { int b[3]; auto fi,i; extern coll(),save(),out(),asym(),asw(),csym(),csw(); extern incl(),declct/T/cont; collect/U/cont; collect/V/cont; collect/W/cont; collect/X/cont; collect/Y/cont; collect/Z/cont; skip2/a/coll; skip2/b/coll; skip2/c/coll; skip2/d/coll; skip2/e/coll; skip2/f/coll; skip2/g/coll; skip2/h/coll; skip2/i/coll; skip2/j/coll; skip2/k/coll; skip2/l/coll; skip2/m/coll; skip2/n/coll; skip2/o/coll; skip2/p/coll; skip2/q/coll; skip2/r/coll; skip2/s/coll; skip2/t/coll; skip2/u/coll; skip2/v/coll; skip2/w/coll; skip2/x/coll; skip2/y/coll; skip2/z/coll; skip2/A/coll; skip2/B/coll; skip2/C/coll;ont; collect/Z/cont; collect/1/cont; collect/2/cont; collect/3/cont; collect/4/cont; collect/5/cont; collect/6/cont; collect/7/cont; collect/8/cont; collect/9/cont; collect/0/cont; collect/ /out; skip/\;/semi; skip/_/coll; skip/ /tab; skip/{/incl; skip/}/decl; skip/*/cgobl; skip/'/cgobl; skip/"/cgobl; skip/\\/cgobl; skip/ /out; skip/1/sk2; skip/2/sk2; skip/3/sk2; skip/4/sk2; skip/5/sk2; skip/6/sk2; skip/7/sk2; skip/8/sk2; skip/9/sk2; skip/0/sk2; skip/a/coll; skip/b/coll; skip/c/coll; skip/d/coll; skip/e/col d = find(ac,df[i],NUMA); j = -1; while(++j < NUMC) tab[i].cl[j] = cd; } } fl = 0; i = -1; while(c = getchar()) { switch(c) { case '\\': temp[++i] = getchar(); continue; case '\n': if(fl != 1) continue; default: temp[++i] = c; continue; case '/': temp[++i] = '\0'; i = -1; switch(fl) { case 0: cs = find(st,temp,NUMS); fl = 1; continue; case 1: cc = find(cl,temp,NUMC); fl = 2; continue; defargv); argv =+ j; argc =- j; } init(); i = 0; if(argc == 1) { *ibuf1 = 0; curfl = 2; curf[0] = '_'; curf[1] = '\t'; goto pipe; } while(++i < argc) { curs[4] = '\t'; if(fopen(argv[i],ibuf1) < 0) { printf("Can't open %s\n",argv[i]); dexit(); } curfl = 0; while((curf[curfl] = *argv[i]++) != 0 && curfl <=8) if(curf[curfl++] == '/') curfl = 0; curf[curfl++] = '\t'; if(curfl == 8) curf[8] = -1; pipe: ibuf = ibuf1; lno = 1; driver(); close(file); } flsh(0(),sk(),sk2(); extern dexit(); ibuf1 = &ib1; if((fi = open(gtab,0)) < 0) { printf("Cannot open grammar table; see lem\n"); dexit(); } i = -1; while(++i < NUMS) if(read(fi,tab[i].cl,512) < 512) { /***/ printf("Bad grammar table; see lem\n"); dexit(); } close(fi); if(signal(1,1) != 1) signal(1,&dexit); if(signal(2,1) != 1) signal(2,&dexit); if(signal(3,1) != 1) signal(3,&dexit); while((tp[1] = creat(tmp[1],0)) < 0) tmp[1][9]++; close(tp[1]); tmp[0][9] = tmp[1][9]; tp[0] = creat(tmp[0],CREATC); if(count) return; itab.hptr = &ipsp; itab.symt = &issp; itab.hsiz = PTRI; itab.ssiz = CHARI; itab.nsym = 0; itab.curb = 1; if((fi = open(ignonl,0)) < 0) { printf("Cannot open ignore/only file.\n"); dexit(); } if((read(fi,b,6) == 6) && (b[0] == 0100200)) { if(read(fi,itab.hptr,b[1]) < b[1]) { printf("Cannot read ignore/only file.\n"); dexit(); } if(read(fi,itab.symt,b[2]) < b[2]) { printf("Cannot read ignor/only file.\n"); dexit(); } close(fi); only = 0; ignonl = argv[++j]; } continue; case 'o': /*only file*/ if(!xx) { xx = 1; only = 1; ignonl = argv[++j]; } continue; case 'p': page = 1; continue; case 't': utmp = argv[++j]; tmp[0] = argv[j]; continue; case 'u': /* Unique symbols only */ usw = 1; continue; case 'w': /* Word list only */ word = 1; continue; } } return(j); } compile() { char buf[40],*b; int i,v; fopen(ignonl,ibuf1); b = bu ct = 15; } put(temp[t1].beg,ct); if(count) { put("\n", 1); continue; } put("\t",1); if(!page) { put(curf,curfl); conf(lno,4,curs); put(curs,4); } else { conf(pn,4,curs); put(curs,4); } if(word == 0) { put("\t",1); if(t1 >= 1) b = temp[t1-1].beg; else b = line; if(t2 > t1) e = temp[t1+1].beg + temp[t1+1].ct; else e = &line[l]; /*printf("e = %o b = %o\n",e,b); /*DEBUG*/ put(b,e-b); } put("\n",1); } t1 = 0; l = -1; lno =+ tlno* printf("hyphen\n"); /*DEBUG*/ if(gch[fl] == 0) flag[++fl] = &hyp1; return(1); } hyp1() { /* printf("hyp1 c = %o\n",c); /*DEBUG*/ if(c != '\n') { fl--; return(0); } else { l =- 2; flag[fl] = &hyp2; hsw = 1; return(1); } } hyp2() { /* printf("hyp2 c = %o l = %d\n",c,l); /*DEBUG*/ if(hsw && (tab[2].cl[c] == 0)) { l--; if(c == 3) pno(); if(c == '\n') tlno++; return(1); } hsw = 0; if(tab[cs].cl[c]) { line[l] = '\n'; out(); fl--; return(0); } return(1); } pno() { ifEXTERN int count; EXTERN int page; EXTERN struct { char *beg; int ct; char term; } temp[30]; EXTERN int pn; EXTERN int word; EXTERN int hsw; EXTERN int t1; EXTERN int level; EXTERN int hlevel; EXTERN int dlevel; EXTERN int xtrn; EXTERN int tp[2]; EXTERN struct { int cl[NUMC]; } tab[NUMS]; EXTERN int coll(); EXTERN int save(); EXTERN int out(); EXTERN int hyphen(); EXTERN int hyp1(); EXTERN int hyp2(); EXTERN int pno(); EXTERN int error(); EXTERN char line[300]; EXTERN int l; EXTERN int lno; # define NUMA 14 # define NUMC 128 # define NUMS 3 # define SIZA 8 # define SIZC 2 # define SIZS 8 # define PTRI 509 # define CHARI 4000 # define PTRX 509 # define CHARX 4000 # define CONT 1 # define COLL 2 # define SAVE 3 # define OUT 4 # define ASYM 5 # define ASW 6 # define CSYM 7 # define CSW 8 # define INCL 9 # define DECL 10 # define SK2 11 # define SK 12 # define TABS 13 # define SEMI 14 # define SHARP 15 # define SKIP 0 # define COLLECT 1 # define SKIP2 2 #define CREATC 0644 } else { close(fi); compile(); } return; } error(a) { printf("Error %d\n",a); dexit(); } dexit() { extern nflush; /* printf("nflush = %d\n",nflush); /*DEBUG*/ if(tp[0] > 0 && utmp == 0) { unlink(tmp[0]); unlink(tmp[1]); } exit(); } callsys(f,v) char f[],*v[]; { int t,status,i; if((t = fork()) == 0) { for(i = 1; i <= 12; i++) signal(i,0); execv(f,v); printf("Can't find %s\n",f); exit(1); } else { if(t == -1) { printf("Try again\n"); return(1); } } while(t != waif - 1; while((*++b = getc(ibuf1)) != -1) { if(*b == '\n') { *b = '\0'; search(buf,b - buf,&itab,1); b = buf - 1; } else { if(*b == '\t') { v = 0; while((i = getc(ibuf1)) != -1) { if(i == '\n') break; v = v*10 + (i - '0'); } search(buf,b - buf,&itab,v); b = buf - 1; } else { if((b - buf) > 39) { printf("Ignore/only symbol too long.\n"); dexit(); } } } } close(ibuf1); return; } ; tlno = 1; cs = SKIP; return; } search(symbol,length,params,install) char *symbol; int length; struct htab *params; int install; { char *sp,*p; static int *hptr,hsiz,nsym; static char *ssiz; static int curb; static char *symt; auto h,i,j,k; if(hptr != params->hptr) { hptr = params->hptr; hsiz = params->hsiz; symt = params->symt; ssiz = params->ssiz; curb = params->curb; nsym = params->nsym; } symbol[length] = '\0'; /*printf("ssiz = %d; nsym = %d; %s\n", ssiz, nsym, symbol);/(flag[fl] != &pno) { flag[++fl] = &pno; pn = 0; return(1); } if(c == '\n') { fl--; out(); return(1); } pn = pn*10 + c - '0'; return(1); } EXTERN char c; EXTERN int cursl; EXTERN char curs[9]; EXTERN int curfl; EXTERN char curf[10]; EXTERN int usw; EXTERN int xsw; EXTERN int only; EXTERN int cross; EXTERN int file; EXTERN int cs; EXTERN int (*flag[8])(); EXTERN int fl; EXTERN char gch[8]; EXTERN struct htab { int hsiz; int ssiz; int nsym; int curb; int *hptr; char *symt; }; EXTERN struct htab itab; EXTERN int ipsp[PTRI]; EXTERN char issp[CHARI]; EXTERN int ib1[131]; EXTERN char *ibuf; EXTERN char *ibuf1; extern char mone; EXTERN struct tempent { char *beg; int ct; char term; } temp[30]; EXTERN char lbuf[5]; EXTERN int cflag; EXTERN int t1; EXTERN int level; EXTERN int hlevel; EXTERN int dlevel; EXTERN int xtrn; EXTERN int tp[5]; EXTERN struct { int cl[NUMC]; } tab[NUMS]; EXTERN int coll(); EXTERN int save(); EXTERN int out(); EXTERN int asym(); EXTERN int asw(); EXTERN int csym(); EXTERN int csw(); EXTERN int incl(); EXTERN int decl(); EXTERN int sk2(); EXTERN int sk(); EXTERN int tabs(); EXTERN int semi(); EPVEKQWX^jY_# #define EXTERN extern # include "../econs.h" # include "../ecmn.h" # define SKIP 0 # define COLLECT 1 # define SKIP2 2 int tlno 1; coll() { cs = COLLECT; temp[t1].beg = &line[l]; return; } save() { extern only; char *pt1,*pt2,cbuf[30]; int a,tt,val; cs = SKIP; line[l] = '\0'; temp[t1].ct = &line[l] - temp[t1].beg; if(!count) if(temp[t1].ct == 1) goto no; pt1 = temp[t1].beg-1; pt2 = cbuf-1; while(*++pt2 = *++pt1) if(*pt2 >= 'A' && *pt2 <= 'Z') *pt2 =| 040; if(count) goto yes; *DEBUG*/ sp = symbol; i = length; h = 1; while(i--) h =* *sp++; if(h == 0100000) { h = 1; } else { h = h<0?(-h)%hsiz:h%hsiz; } if(h == 0) h++; /* printf("%s %d\n",symbol,h); /*DEBUG*/ while((p = &symt[hptr[h]]) > symt) { j = length + 2; sp = symbol; while(--j) { if(*p++ != *sp++) goto no; } return(*p); no: h = (h + h)%hsiz; } if(install) { if(++nsym >= hsiz) { printf("Too many symbols in ignore/only file.\n"); dexit(); } hptr[h] = curb; length++; if((curbint optr; char obuf[512]; int nflush; put(string,n) char *string; { extern utmp; int i; char *o; /*printf("%d %c %d\n",fil,*string,n);/*DEBUG*/ string--; if((i = optr + n - 512) >= 0) { n =- i; o = &obuf[optr] -1; while(--n >= 0) *++o = *++string; optr = 512; flsh(1); n = i; } o = &obuf[optr] - 1; optr =+ n; while(--n >= 0) { *++o = *++string; } return(0); } flsh(fil) { extern tp[],utmp; if(optr <= 0) return(optr); nflush++; if(write(tp[0],obuf,optr) != optr) reEXTERN int order; EXTERN int ssw; EXTERN int type; EXTERN char *utmp; XTERN char line[132]; EXTERN int l; EXTERN int lno; EXTERN char c; EXTERN int cursl; EXTERN char curs[9]; EXTERN int curfl; EXTERN char curf[10]; EXTERN int usw; EXTERN int xsw; EXTERN int only; extern int cross; EXTERN int file; EXTERN int cs; EXTERN int (*flag[8])(); EXTERN int fl; EXTERN char gch[8]; EXTERN struct htab { int hsiz; int ssiz; int nsym; int curb; int *hptr; char *symt; }; EXTERN struct htab itab; EXTERN struct htab xtab; EXTERN int ipsp[PTRI]; EXTERN char issp[CHARI]; EXTEt(&status)); /* printf("Status = %o, %s\n",status,f); /*DEBUG*/ if((t = (status & 0377)) != 0) { if(t != 2) { printf("Fatal error in %s\n",f); printf("t = %d\n",t); } dexit(); } return((status>>8) & 0377); } flags(argv) char *argv[]; { int j,xx; char *ap; j = 1; ap = argv[1]; while(*++ap != '\0') { switch(*ap) { default: printf("Unrecognized flag: %c\n",*ap); dexit(); case 'c': count = 1; continue; case 'i': /* Ignore file */ if(!xx) { xx = 1; val = search(cbuf,temp[t1].ct,&itab,0); if(!val == !only) goto yes; no: line[l] = c; return(0); yes: if(count == 0) { tt = t1; while(tt) if(comp(temp[t1].beg,temp[--tt].beg)) goto no; } temp[t1++].term = c; return(1); } out() { auto i,ct,t2; char *b,*e; if(cs == COLLECT) save(); ct = t1; while(ct--) temp[ct].beg[temp[ct].ct] = temp[ct].term; t2 = t1 - 1; while(t1--) { /*printf("t1 = %d beg = %o ct = %d\n",t1,temp[t1].beg,temp[t1].ct); /* DEBUG */ if((ct = temp[t1].ct) >= 15) { + length) >= ssiz) { printf("i/o file too big; ssiz = %d\n", ssiz); dexit(); } while(length--) symt[curb++] = *symbol++; symt[curb++] = install; params->curb = curb; params->nsym = nsym; } return(0); } conf(n,width,buf) char *buf; { auto i,a; i = width; while(i--) buf[i] = ' '; buf[(a = n/10)?conf(a,--width,buf):--width] = n%10 + '0'; return(++width); } comp(a,b) char *a; char *b; { a--; b--; while(*++a == *++b) if(*a == '\0') return(1); return(0); } hyphen() { /turn(-1); optr = 0; return(0); } # define NUMA 14 # define NUMC 128 # define NUMS 3 # define SIZA 8 # define SIZC 2 # define SIZS 8 # define PTRI 509 # define CHARI 4000 # define PTRX 5147 # define CHARX 40000 # define CONT 0 # define COLL 1 # define SAVE 2 # define OUT 3 # define EGOBL 4 # define SHARP 5 # define PNO 6 # define SKIP 0 # define COLLECT 1 # define SKIP2 2 #define CREATC 0644 RN int xpsp[PTRX]; EXTERN char xssp[CHARX]; EXTERN int ib1[259]; EXTERN int ib2[259]; EXTERN char *ibuf; EXTERN char *ibuf1; EXTERN char *ibuf2; extern char mone; extern int order; EXTERN int ssw; EXTERN int type; EXTERN char *utmp; Cross-reference program - see CREF(I) fd 0; int ninclude 0; int filestack[10]; int linect[10]; int errorflag 0; #define MAXNAMES 300 char *names[MAXNAMES]; char *nameptr[MAXNAMES]; int nnames 0; main(argc,argv) int argc; char **argv; { contfld = errorflag = 0; if(argc>1 && argv[1][0]=='-'){ if(argv[1][1]=='6') contfld=6; argc--; argv++; } svargc = argc; svargv = argv; filestack[0] = infile = fd = ninclude = linect[0] = 0; if(--svargc>0) if( (fd = filestack[0] = copen(svargv[++infile],'r')) < 0 ) { error("can't open %s", s("can't open %s", svargv[infile]); cexit(1); } linect[0] = 0; goto loop; } return(0); } inclstat(){ register int i,c; static char fname[50] "/usr/rat/"; while( (c=getc())==' ' || c=='\t' ); peek = c; for(i=9; (fname[i]=c=getc())!='\n' && c!=';' && c!=' ' && c!='\t'; i++); fname[i] = '\0'; if( (fd = copen(&fname[9],'r')) < 0 ) { if( (fd = copen(fname,'r')) < 0 ) { error("can't open %s", fname); cexit(1); } } filestack[++ninclude] = fd; linect[ninclude] = 0; } lookup(strin())!=' ' && c!='\t' && c!='\n' && c!='{' && c!='}' && c!=';' && c!='(' && c!=')' ; ) if( c=='\'' || c=='"' ) while( (s[sp++]=getc())!=c ); peek = c; s[--sp]='\0'; return(sp); } alldigits(s) register char *s; { register int c; if( *s == '\0' ) return(0); while( (c = *s++) != '\0' ) if( c<'0' || c>'9' ) return(0); return(1); } int dbg 0; yyerror(){;} alphanum(c) register int c; { if(c>='0' && c<='9') return(1); if(c>='a' && c<='z') return(1); if(c>='A' && c<='Z') return(1); retustruct buf { int fildes; int left; char *next; char buff[512];}; struct buf *abps[15]; /*array of buffer pointers*/ copen(filename,type) char *filename; int type; { register struct buf *bp; register int fd; if((bp = alloc(sizeof(*bp))) < 0) return(-1); if((fd=bp->fildes=open(filename,0)) < 0 || fd > 14) return(-1); abps[fd] = bp; /* save buffer pointer addr */ bp->left = 0; return(fd); } cgetc(fd) int fd; { register struct buf *bp; register char c; bp = abps[fd]; if(--bp->lefpar=i=0; (bp[i++]=c=getc())!='\0'; ){ if( c=='\'' || c=='"' ) while( (bp[i++]=getc()) != c ); if( i>=499 || c=='{' || c=='}' ){ error("missing right parenthesis at %.20s", bp); break; } if( c=='(' ) lpar++; else if( c==')' ) lpar--; if( lpar == 0 ) break; } bp[i] = '\0'; return(bp); } int labval 23000; genlab(){ return(++labval); } gokcode(p1) char *p1; { outcode("\t"); outcode(p1); eatup(p1,scrat); outcode(scrat); outcode(0); } eatup(p1,bp) char *p1; register chchdir tab cc mtab.c a.out atable atab a.out ctable ctab a.out etable etab chdir ../src cc -s -o upost upost.c cc -s -o crpost crpost.c cc -s -o cref dr.c acts.c put.c chdir ../index cc -s -o index ind?.c vargv[infile]); cexit(1); } yyparse(); cexit(errorflag); } int peek -1; int nextchar '\n'; getc(){ nextchar = (peek<0) ? gchar(): peek; peek = -1; return(nextchar); } int gcp 0; char gcbuf[300]; int apos -1; gchar(){ register int c,i,atype,t; register char **hp; if( c=gcbuf[gcp++] ) return(c); loop: for(gcp=0; (c=gcbuf[gcp]=cgetc(fd))!='\0' ; gcp++ ){ if( gcbuf[0]== '%' ){ while(putchar(cgetc(fd))!='\n'); gcp = -1; ++linect[ninclude]; continue; } if( (atype=alphanum(g,tbl) register char *string; register char *tbl[]; { register i,j, r; for(i=0; tbl[i]!=0; i++){ for( j=0; (r=tbl[i][j])==string[j] && r!='\0'; j++); if( r == string[j] ) return(i); } return( -1 ); } char str[200]; yylex(){ register int c, type; char **dlookup(); top: while( (c=getc())==' ' || c=='\n' || c=='\t' ); yylval = c; switch(c){ case '\0': return('\0'); case ';': return(SCOL); case'{': return(LCURL); case '}': return(RCURL); } peek = c; getstr(str); yylval = rn(0); } defstat(){ register int c,i,index; register char **hp; char *alloc(); char **dlookup(); if (++nnames >= MAXNAMES-2 ) { error("too many defined names"); cexit(1); } while( (c=getc())==' ' || c=='\t' || c=='(' ); peek = c; for(i=0; c=getc(); i++ ){ if(c==' ' || c=='\t' || c=='\n' || c==',' ) break; str[i] = c; } peek = c; str[i] = '\0'; if ( *(hp = dlookup(str)) == 0 ) { *hp = alloc(i+1); for (i=0; hp[0][i] = str[i]; i++) ; } while( (c=getc())==' ' || c=='\t' || c==',' );t < 0) { bp->left = c = read(bp->fildes,bp->buff,sizeof(bp->buff))-1; if(c<0) return('\0'); bp->next = bp->buff; } return(*bp->next++); } cclose(fd) int fd; { free(abps[fd]); close(fd); abps[fd]=0; } cexit(rc) int rc; { register int fd; for(fd=3;fd<15;fd++) if (abps[fd] != 0) cclose(fd); exit(rc); } ar *bp; { extern int peek; register int i,c,lnb,lpar; lnb = '\n'; while( c = *p1++ ) if( c!=' ' ) lnb = c; i = lpar = 0; more: for( ; (bp[i++]=c=getc())!=';' && c!='{' && c!='\n' && c!='}'; ){ if( i>=499 ){ error("statement too long at %.20s", bp); break; } if( c != ' ' && c != '\t' ) lnb = c; if( c=='\'' || c=='"' ) while( (bp[i++]=getc()) != c ); if( c=='(' ) lpar++; else if( c==')' ) { lpar--; if( lpar < 0 ) error("missing left paren at %.20s",bp); } }chdir tab cmp atab /usr/lib/atab cp atab /usr/lib/atab cmp ctab /usr/lib/ctab cp ctab /usr/lib/ctab cmp etab /usr/lib/etab cp etab /usr/lib/etab rm a.out atab ctab etab chdir ../src cmp upost /usr/bin/upost cp upost /usr/bin/upost cmp crpost /usr/bin/crpost cp crpost /usr/bin/crpost cmp cref /usr/bin/cref cp cref /usr/bin/cref rm *.o upost crpost cref chdir ../index cmp index /usr/bin/index cp index /usr/bin/index rm *.o index c)) && apos < 0 ){ apos = gcp; continue; } if( !atype ) if( apos >= 0 ){ gcbuf[gcp] = '\0'; if (nnames>0 && *(hp=dlookup(&gcbuf[apos])) != 0 ) { hp = hp - names + nameptr; for (i=0; gcbuf[apos++] = hp[0][i]; i++); gcp = apos-1; } apos = -1; gcbuf[gcp] = c; } if( c < ' ' && (c!='\n' && c!='\t') ) /* strip crap */ c = gcbuf[gcp] = ' '; if( c=='#' ){ gcbuf[gcp] = '\n'; while( (c=cgetc(fd))!='\n' && c!='\0'); } if( c=='"' || c=='\'' ){ while&str[0]; if( alldigits(str) ) return(DIGITS); type = lookup(str,keyword); if( keytran[type]==XDEFINE ) { defstat(); goto top; } else if( keytran[type]==XINCLUDE ) { inclstat(); goto top; } else if( type > 1 ) return(keytran[type]); else if( type < 0 ) return(XGOK); while( (c=getc())==' ' || c=='\t' || c=='\n' ); peek = c; if( c>='a' && c<='z' || c>='A' && c<='Z' ) return(NEWDO); else return(OLDDO); } getstr(s) register char *s; { register int c, sp; for (sp=0; (c=s[sp++]=getc peek = c; for( i=0; (c=getc())!='\n' && c!='\0' && c!=')'; i++ ) str[i] = c; str[i] = '\0'; hp = hp - names + nameptr; *hp = alloc(i+1); for (i=0; hp[0][i] = str[i]; i++); } char ** dlookup(s) register char *s; { register int i; register char **hp; register char *cp,*cp1; i=0; for (cp=s; *cp;) i = (i<<1) + *cp++; for (hp = &names[(i&077777)%MAXNAMES]; *hp!=0;) { cp1 = *hp; for (cp=s; *cp == *cp1++;) if (*cp++ == '\0') return(hp); if (++hp >= &names[MAXNAMES] ) hp = names;#include "r.h" char scrat[500]; int brkptr -1; int brkstk[10]; int forptr 0; int forstk[10]; repcode() { outcont(0); yyval = genlab(); outcont(yyval); brkstk[++brkptr] = yyval+1; genlab(); genlab(); } untils(p1) register int p1; { outnum(p1+1); outcode("\tif(.not."); balpar(scrat); outcode(scrat); outcode(")"); outgoto(p1); outcont(p1+2); brkptr--; } ifcode(p1) register int p1; { outcode("\tif(.not."); balpar(scrat); outcode(scrat); outcode(")"); outgoto(yyval=genlab()); genlab(); } if( c == '\n' ){ if( lnb=='\n' || lnb=='+' || lnb=='-' || lnb=='*' || lnb=='(' || lnb==',' || lnb=='&' || lnb=='|' || lnb=='=' ) goto more; c = ';'; } if( c!=';' ) peek = c; bp[i-1] = '\0'; if( lpar > 0 ) error("missing right paren at %.20s",bp); return(bp); } forcode(){ extern int peek; register int i,j,c; register char *bp; char *alloc(); outcont(0); balpar(scrat); yyval = genlab(); genlab(); genlab(); brkstk[++brkptr] = yyval+1; if( scrat[0] == '\0' ){ forstk[forptr# include "r.h" char *keyword []{ "do", "DO", /* have to be first */ "if", "IF", "else", "ELSE", "for", "FOR", "repeat", "REPEAT", "until", "UNTIL", "while", "WHILE", "break", "BREAK", "next", "NEXT", "define", "DEFINE", "include", "INCLUDE", 0}; #include "y.tab.c" int keytran[]{ 0, 0, XIF, XIF, XELSE, XELSE, XFOR, XFOR, REPEAT, REPEAT, UNTIL, UNTIL, XWHILE, XWHILE, XBREAK, XBREAK, NEXT, NEXT, XDEFINE, XDEFINE, XINCLUDE, XINCLUDE, 0}; int svargc; char **svargv; int infile 0; int ( (gcbuf[++gcp]=t=cgetc(fd)) != c ) if( t=='\n' ) { error("unbalanced quote"); gcbuf[gcp] = c; gcbuf[++gcp] = c = '\n'; goto newline; } continue; } newline: if( c=='\n' ){ gcbuf[gcp+1] = '\0'; gcp = 1; ++linect[ninclude]; return(gcbuf[0]); } } if(ninclude){ cclose(filestack[ninclude--]); fd = filestack[ninclude]; goto loop; } cclose(filestack[ninclude]); if(--svargc>0){ if( (fd = filestack[ninclude] = copen(svargv[++infile],'r')) < 0) { errorqw}rx~sy } return(hp); } whilecode(p1) register int p1; { outcont(0); brkstk[++brkptr] = yyval = genlab(); genlab(); outnum(yyval); outcode("\tif(.not."); balpar(scrat); outcode(scrat); outcode(")"); outgoto(yyval+1); } whilestat(p1) register int p1; { outgoto(p1); outcont(p1+1); brkptr--; } balpar(bp) register char *bp; { register int i, c, lpar; extern int peek; while( (c=getc()) == ' ' || c == '\t' || c=='\n' ); peek = c; if( c != '(' ){ error("missing left paren"); bp[0] = '\0'; return(bp); } for( l++] = bp = alloc(1); *bp = '\0'; return; } scrat[0] = '\t'; for( i=1; (c=scrat[i++])!=';' && c!='\0' ; ) if( c=='\'' || c=='"' ) while( scrat[i++] != c ); scrat[i-1] = '\0'; if( nonblank(scrat) ){ outcode(scrat); outcode(0); } for( j=i; (c=scrat[i++])!=';' && c!='\0' ; ) if( c=='\'' || c=='"' ) while( scrat[i++] != c ); scrat[i-1] = '\0'; if( nonblank(&scrat[j]) ){ outnum(yyval); outcode("\tif(.not.("); outcode(&scrat[j]); outcode("))"); outgoto(yyval+2); } else outcont(yyval); for( j=0; scrat[i+1]!='\0'; ) scrat[j++] = scrat[i++]; scrat[j] = '\0'; forstk[forptr++] = bp = alloc(j+1); for(i=0; *bp++ = scrat[i++]; ); } forstat(p1) register int p1; { register char *bp, *q; register int i; bp = forstk[--forptr]; outnum(p1+1); if( nonblank(bp) ){ outcode("\t"); outcode(bp); outcode(0); } outgoto(p1); outcont(p1+2); for( q=bp; *q++; ); free(bp, q-bp); brkptr--; } docode(new,p1) register int new; register char *p1; { outcode("\t"); outcode(p1); }' && c != '\n' && c != '\0' ); yychar = -1; errorflag = 1; } ); } outgoto(n) int n; { outcode("\tgoto "); outnum(n); outcode(0); } extern int brkptr; nountil(p1) int p1; { outnum(p1+1); outgoto(p1); outcont(p1+2); brkptr--; } 4361,8211,4362,8210,4363,8200,4364,8201 ,4365,8203,4366,8213,4367,8204,4370,8212,0,12297 ,12298,12300,12301,12302,12305,12307,12309,12310,12311,12312 ,12306,4360,8223,12291,12292,12293,12294,4371,8224,12295 ,12299,4352,8208,4353,8206,4354,8225,4357,8205,4358 ,8214,4359,8209,4361,8211,4362,8210,4363,8200,4364 ,8201,4365,8203,4366,8213,4367,8204,4370,8212,0 ,12304,12308,12296,12303,-1}; int yypact[] {0,1,2,31,32,32,32,32,32,59 ,60,32,61,62,63,1,32,64,65,66 ,67,68,69,70,71,74,75,76,77,80 ,81,110,111,112,113,- goto passa; break; case 'v': vflag = 0; break; case 'r': rflag = fflag = cflag = 1; break; case 'f': fflag = 1; break; case 'c': cflag = 1; break; case 'S': sflag = 1; break; } else { passa: t = argv[i]; if( (c=getsuf(t))=='r' ) ratcomp(t); else llist[nl++] = t; } } if(rflag) dexit(); if ((signal(2, 1) & 01) == 0) signal(2, &dexit); /*** do fortran compile assemble and link ***/ if ( fortcoeatup(p1,scrat); yyval = 0; if(new){ yyval = genlab(); genlab(); brkstk[++brkptr] = yyval; outnum(yyval); } outcode(scrat); outcode(0); } dostat(p1) register int p1; { if( p1==0 ) return; outcont(p1); outcont(p1+1); brkptr--; } breakcode(p1) register int p1; { if(brkptr<0){ error("illegal BREAK"); return; } outgoto(brkstk[brkptr]+1); } nextcode(p1) register int p1; { if(brkptr<0){ error("illegal NEXT"); return; } outgoto(brkstk[brkptr]); } nonblank(s) register char *s; #include "r.h" char outbuf[80]; int outp 0; int cont 0; outcode(p) char *p; { int i,j,c,c1; char *q; if( p == 0 ){ outbuf[outp] = '\0'; printf("%s\n", outbuf); outp = cont = 0; return; } while( (c = *p++) ){ c1 = *p; switch(c){ case '"': for( q=p; *q != c; q++ ); outnum(q-p); ptc('h'); while( p != q ) ptc(*p++); p++; break; case '>': if( c1=='=' ){ pts(".ge."); p++; } else pts(".gt."); break; case '<': if( c1=='=' ){ pts(".le."); p++; %term LCURL RCURL LPAR RPAR SCOL DIGITS %term XIF XELSE XFOR XWHILE XBREAK NEXT %term OLDDO NEWDO %term XGOK XDEFINE XINCLUDE %term REPEAT UNTIL %% statl : statl stat | ; stat : if stat ={ outcont($1); } | ifelse stat ={ outcont($1+1); } | while stat ={ whilestat($1); } | for stat ={ forstat($1); } | repeat stat ={ nountil($1); } | repeat stat UNTIL ={ untils($1); } | XBREAK ={ breakcode($1); } | NEXT ={ nextcode($1); } | newdo stat ={ dostat($1); } | OLDDO ={ docode(0,$1); } | XGOK ={ gok# # define LCURL 257 # define RCURL 258 # define LPAR 259 # define RPAR 260 # define SCOL 261 # define DIGITS 262 # define XIF 263 # define XELSE 264 # define XFOR 265 # define XWHILE 266 # define XBREAK 267 # define NEXT 268 # define OLDDO 269 # define NEWDO 270 # define XGOK 271 # define XDEFINE 272 # define XINCLUDE 273 # define REPEAT 274 # define UNTIL 275 #define yyclearin yychar = -1 #define yyerrok yyerrflag = 0 extern int yychar, yyerrflag; int yyval 0; int *yypv; int yylval 0; yyactr(__np__){ sw1}; int yyr1[] {0,1,1,2,2,2,2,2,2,2 ,2,2,2,2,2,2,2,2,9,3 ,4,5,6,7,8,-1}; int yyr2[] {0,2,0,2,2,2,2,2,3,1 ,1,2,1,1,1,3,2,1,1,1 ,3,1,1,1,1,-1}; int yygo[] {0,14,29,-1,1,3,23,4,24,5 ,25,6,26,7,27,10,28,15,30,-1 ,2,-1,3,-1,4,-1,5,-1,6,-1 ,7,-1,10,-1,15,-1}; int yypgo[] {0,1,5,21,23,25,27,29,31,33 ,-1}; int nterms 21; int nnonter 9; int nstate 34; char *yysterm[] { "error", "LCURL", "RCURL", "LPAR", "RPAR", "SCOL", "DIGITS", "XIF", "XELSE", "XFOR", "XWHILE", "XBREAK", "NEXT", "OLDDO", "NEWDO", "XGOK", "XDEFmp() == 0 && fflag == 0 ) { for ( i=0; i' ){ pts(".ne."); p++; } else pts(".lt."); break; case '=': if( c1=='=' ){ pts(".eq."); p++; } else ptc('='); break; case '!': case '^': if( c1=='=' ){ pts(".ne."); p++; } else pts(".or."); break; case '&': if( c1=='&' ) p++; pts(".and."); break; case '|': if( c1=='|' ) p++; pts(".or."); break; case '\t': tabs(); break; case '\n': ptc(' '); break; default: ptc(c); break; } } } pcode($1); } | SCOL | LCURL statl RCURL | label stat | error ={ errcode($1); yyclearin; } ; label : DIGITS ={ outcode($1); outcode("\t"); } ; if : XIF ={ ifcode($1); } ; ifelse : if stat XELSE ={ outgoto($1+1); outcont($1); } ; while : XWHILE ={ whilecode($1); } ; for : XFOR ={ forcode($1); } ; repeat : REPEAT ={ repcode($1); } ; newdo : NEWDO ={ docode(1,$1); } ; %% itch(__np__){ case 3:{ outcont(yypv[1]); } break; case 4:{ outcont(yypv[1]+1); } break; case 5:{ whilestat(yypv[1]); } break; case 6:{ forstat(yypv[1]); } break; case 7:{ nountil(yypv[1]); } break; case 8:{ untils(yypv[1]); } break; case 9:{ breakcode(yypv[1]); } break; case 10:{ nextcode(yypv[1]); } break; case 11:{ dostat(yypv[1]); } break; case 12:{ docode(0,yypv[1]); } break; case 13:{ gokcode(yypv[1]); } break; case 17:{ errcode(yypv[1]); yyclearin; } break; case 18:{ outcode(yypv[1]); outcode("\t"); INE", "XINCLUDE", "REPEAT", "UNTIL", 0 }; char *yysnter[] { "$accept", "statl", "stat", "if", "ifelse", "while", "for", "repeat", "newdo", "label" }; exit(1); } while( t!=wait(&status) ); if( (t=(status&0377)) != 0 && t!=14 ) texit(); /*** temp ***/ t = (status>>8) & 0377; if( t ) /*** return(++cflag);****/ texit(); /*** temp ***/ splitup(); } fortcomp(){ register int t; register int j; register int i; j=1; av[0] = complr; if ( cflag ) av[j++] = "-c"; if ( sflag ) av[j++] = "-S"; for ( i=0; i 0 ) outnum(n); outcode("\tcontinue"); outcode(0extern int contfld; extern int dbg; extern int yyval; extern int *yypv; extern int yylval; extern int peek; extern int errorflag; } break; case 19:{ ifcode(yypv[1]); } break; case 20:{ outgoto(yypv[1]+1); outcont(yypv[1]); } break; case 21:{ whilecode(yypv[1]); } break; case 22:{ forcode(yypv[1]); } break; case 23:{ repcode(yypv[1]); } break; case 24:{ docode(1,yypv[1]); } break; } return(0); } int yyerrval 256; int yyact[] {0,12290,4096,16384,4352,8208,4353,8206,4357,8205 ,4358,8214,4359,8209,4361,8211,4362,8210,4363,8200 ,4364,8201,4365,8203,4366,8213,4367,8204,4370,8212 ,0,12289,4352,8208,4353,8206,4357,8205,4358,8214 ,4359,8209,/* Ratfor-Fortran command */ extern int fin, fout; char ts[500]; char *tsp ts; char *av[50]; char *rlist[50]; int nr 0; char *llist[50]; int nl 0; int bdcount 0; /* count block data files generated */ int rflag 0; int vflag 1; int fflag 0; int cflag 0; int sflag 0; char *complr "/usr/bin/fort"; char *ratfor "/usr/bin/ratinc"; main(argc, argv) char *argv[]; { register char *t; register int i, j, c; int dexit(); for(i=0; ++i < argc; ) { if(*argv[i] == '-') switch (argv[i][1]) { default: av[j++] = "-lr"; av[j] = 0; if( callsys(complr, av) ) return(1); return(0); } getsuf(s) char s[]; { int c; char t, *os; c = 0; os = s; while(t = *s++) if (t=='/') c = 0; else c++; s =- 3; if (c<=14 && c>2 && *s++=='.') return(*s); return(0); } setsuf(s, ch) char s[]; { char *os; os = s; while(*s++); s[-2] = ch; return(os); } callsys(f, v) char f[], *v[]; { int i, t, status; if ((t=fork())==0) { execv(f, v); printf("Can't find %s\n", f); exit(1); } else if (t == -1) { printf("Try again\n"); return(1); } while(t!=wait(&status)); if ((t=(status&0377)) != 0 && t!=14) { if (t!=2) /* interrupt */ printf("Fatal error in %s\n", f); dexit(); } t = (status>>8) & 0377; return(t); } copy(s) char s[]; { char *otsp; if ( tsp > &ts[500] ) error("too many files \n"); otsp = tsp; while(*tsp++ = *s++); return(otsp); } cunlink(f) char *f; { if (f==0) return(0); return(unlink(f)); } splitup(){ char in[200], fname[20]; int buf[259]; int i,fd,s,"complex") ){ s =+ 7; goto loop; } else if( compar(s,"block") ){ s = "blockdata "; s[9] = (bdcount++) + '0'; goto bot; } else { for(i=0; f[i]="MAIN.f"[i]; i++); return; } bot: while( *s == ' ' || *s == '\t' ) s++; for(i=0; alphanum(s[i]); i++) f[i] = s[i]; f[i++] = '.'; f[i++] = 'f'; f[i++] = '\0'; } compar(s,t) char *s,*t; { while( *t ) if( *s++ != *t++ ) return(0); return(1); } alphanum(c) int c; { return( (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<=cp rc /usr/bin rm rc chdir ratinc cp ratinc /usr/bin rm ratinc *.o chdir ../lib ar ru /lib/libr.a rm *.f rm *.o - read character from standard input integer function getc(c) integer c integer getch getc = getch(c, STDIN) return end # getlin - read a line integer function getlin(buf, f) character buf(MAXLINE) integer f, i integer getch for (i = 1; getch(buf(i), f) ^= NEWLINE; i = i + 1) { if (buf(i) == EOF) { getlin = EOF return } if (i >= MAXLINE-2) { i = i + 1 buf(i) = NEWLINE break } } buf(i+1) = EOS getlin = i return end # index - find character c in string str integ field width >=w subroutine putdec(n, w) character chars(MAXCHARS) integer itoc integer i, n, nd, w nd = itoc(n, chars, MAXCHARS) for ( i = nd+1; i <= w; i = i+1 ) call putc(BLANK) for (i = 1; i <= nd; i = i + 1) call putc(chars(i)) return end # putlin - write a line subroutine putlin(buf, f) character buf(ARB) integer f, i for (i = 1; buf(i) ^= EOS; i = i + 1) call putch(buf(i), f) return end # putstr - write a hollerith string to std output unit subroutine putstr(string) inIG0/ data digits(2) /DIG1/ data digits(3) /DIG2/ data digits(4) /DIG3/ data digits(5) /DIG4/ data digits(6) /DIG5/ data digits(7) /DIG6/ data digits(8) /DIG7/ data digits(9) /DIG8/ data digits(10) /DIG9/ data digits(11) /EOS/ # string lowalf "abcdefghijklmnopqrstuvwxyz" data lowalf(01)/LETA/ data lowalf(02)/LETB/ data lowalf(03)/LETC/ data lowalf(04)/LETD/ data lowalf(05)/LETE/ data lowalf(06)/LETF/ data lowalf(07)/LETG/ dc; if( (fin=open("ratjunk", 0)) < 0) error("can't open ratjunk\n"); while( gets(in) ){ getname(in, fname); savename(fname); if( (fd = fcreat(fname, buf)) < 0) error("can't open %s", fname); puts(in,buf); while( ! endcard(in) ){ gets(in); puts(in,buf); } fflush(buf); close(fd); } close(fin); } gets(s) char *s; { int c; while( (*s++=c=getchar()) != '\n' && c != '\0' ); *s = '\0'; return(c); } puts(s,b) char *s; int *b; { while( *s ) putc(*s++, b); } savename(s) char *s'9') ); } endcard(s) char *s; { if( *s==0 ) return(1); while( *s==' ' || *s=='\t' ) s++; if( *s!='e' || *(s+1)!='n' || *(s+2)!='d' || *(s+3)!='\n' ) return(0); return(1); } error(s1, s2){ fout = 1; printf(s1,s2); putchar('\n'); flush(1); cflag++; } include rat.h # cant - print cant open file message subroutine cant(buf) integer buf(MAXLINE) call putlin(buf, ERROUT) call error(" : can't open.") return end # ctoi - convert string at in(i) to integer, increment i integer function ctoi(in, i) character in(ARB) integer index integer d, i # string digits "0123456789" integer digits(11) data digits(1) /DIG0/ data digits(2) /DIG1/ data digits(3) /DIG2/ data digits(4) /DIG3/ data digits(5) /DIG4/ data digiter function index(str, c) character c, str(ARB) for (index = 1; str(index) ^= EOS; index = index + 1) if (str(index) == c) return index = 0 return end define(abs,iabs) # itoc - convert integer int to char string in str integer function itoc(int, str, size) integer iabs, mod integer d, i, int, intval, j, k, size character str(size) # string digits "0123456789" integer digits(11) data digits(1) /DIG0/ data digits(2) /DIG1/ data digits(3) /DIG2/ data lowalf(08)/LETH/ data lowalf(09)/LETI/ data lowalf(10)/LETJ/ data lowalf(11)/LETK/ data lowalf(12)/LETL/ data lowalf(13)/LETM/ data lowalf(14)/LETN/ data lowalf(15)/LETO/ data lowalf(16)/LETP/ data lowalf(17)/LETQ/ data lowalf(18)/LETR/ data lowalf(19)/LETS/ data lowalf(20)/LETT/ data lowalf(21)/LETU/ data lowalf(22)/LETV/ data lowalf(23)/LETW/ data lowalf(24)/LETX/ data lowalf(25)/LETY/ data lowalf(26)/LETZ/ data lowalf(27)/EOS/ # string upalf ; { rlist[nr++] = copy(s); } getname(s,f) char *s,*f; { int i,j,c; loop: while( *s == ' ' || *s == '\t' ) s++; if( compar(s,"subroutine") ){ s =+ 10; goto bot; } else if( compar( s,"function") ){ s =+ 8; goto bot; } else if( compar(s,"real") ){ s =+ 4; goto loop; } else if( compar(s,"integer") ){ s =+ 7; goto loop; } else if( compar(s,"logical") ){ s =+ 7; goto loop; } else if( compar(s,"double") ){ s =+ 6; goto loop; } else if( compar(s,"precision") ){ s =+ 9; goto loop; } else if( compar(ratinc - source for ratfor preprocessor (ratinc) - note: ocg.c contains fake portable library routines rc.c - ratfor command (rc) - calls ratinc and fort lib - some routines from "Software Tools" - note: rat.h contains standard defines and should be copied to /usr/rat/rat.h s(6) /DIG5/ data digits(7) /DIG6/ data digits(8) /DIG7/ data digits(9) /DIG8/ data digits(10) /DIG9/ data digits(11) /EOS/ while (in(i) == BLANK ! in(i) == TAB) i = i + 1 for (ctoi = 0; in(i) ^= EOS; i = i + 1) { d = index(digits, in(i)) if (d == 0) # non-digit break ctoi = 10 * ctoi + d - 1 } return end # equal - compare str1 to str2; return YES if equal, NO if not integer function equal(str1, str2) character str1(ARB), str2(ARB)ata digits(4) /DIG3/ data digits(5) /DIG4/ data digits(6) /DIG5/ data digits(7) /DIG6/ data digits(8) /DIG7/ data digits(9) /DIG8/ data digits(10) /DIG9/ data digits(11) /EOS/ intval = iabs(int) str(1) = EOS i = 1 repeat { # generate digits i = i + 1 d = mod(intval, 10) str(i) = digits(d+1) intval = intval / 10 } until (intval == 0 ! i >= size) if (int < 0 & i < size) { # then sign i = i + 1 str(i) = MINUS }teger*2 string(ARB) integer i, c for (i = 1; ; i = i + 1) { c = string(i) if (c == x'41f0') # branch & link instruction ! break call putc(c/256) call putc(mod(c,256)) } return end # remark - write a hollerith string to error output unit subroutine remark(string) integer*2 string(ARB) integer i, c for (i = 1; ; i = i + 1) { c = string(i) if (c == x'41f0') # branch & link instruction ! break call putch(c/256, STDOUT) call putch(mod(c, 256), STDOUT) } call putch(NEWLINE, STD"ABCDEFGHIJKLMNOPQRSTUVWXYZ" data upalf(01) /BIGA/ data upalf(02) /BIGB/ data upalf(03) /BIGC/ data upalf(04) /BIGD/ data upalf(05) /BIGE/ data upalf(06) /BIGF/ data upalf(07) /BIGG/ data upalf(08) /BIGH/ data upalf(09) /BIGI/ data upalf(10) /BIGJ/ data upalf(11) /BIGK/ data upalf(12) /BIGL/ data upalf(13) /BIGM/ data upalf(14) /BIGN/ data upalf(15) /BIGO/ data upalf(16) /BIGP/ data upalf(17) /BIGQ/ data upalf(18) /BIGR/ data upalf(19) /BIGS/ data echo == ratfor command cc -o rc rc.c echo == ratfor compiler chdir ratinc yacc r.g cc -o ratinc lex.c ocg.c r[123].c -ly echo == ratfor library chdir ../lib rc -c lib.r integer i for (i = 1; str1(i) == str2(i); i = i + 1) if (str1(i) == EOS) { equal = YES return } equal = NO return end # error - print fatal error message, then die subroutine error(buf) integer buf(ARB) call remark(buf) stop end # fcopy - copy file in to file out subroutine fcopy(in, out) character buf(MAXLINE) integer getlin integer in, out while (getlin(buf, in) ^= EOF) call putlin(buf, out) return end # getc itoc = i - 1 for (j = 1; j < i; j = j + 1) { # then reverse k = str(i) str(i) = str(j) str(j) = k i = i - 1 } return end # length - compute length of string integer function length(str) integer str(ARB) for (length = 0; str(length+1) ^= EOS; length = length + 1) ; return end define(MAXCHARS,10) # putc - write character to standard output subroutine putc(c) integer c call putch(c, STDOUT) return end # putdec - put decimal integer n inOUT) return end # scopy - copy string at from(i) to to(j) subroutine scopy(from, i, to, j) character from(ARB), to(ARB) integer i, j, k1, k2 k2 = j for (k1 = i; from(k1) ^= EOS; k1 = k1 + 1) { to(k2) = from(k1) k2 = k2 + 1 } to(k2) = EOS return end # type - determine type of character character function type(c) character c integer index integer upalf(27) integer lowalf(27) integer digits(11) # string digits "0123456789" data digits(1) /Dupalf(20) /BIGT/ data upalf(21) /BIGU/ data upalf(22) /BIGV/ data upalf(23) /BIGW/ data upalf(24) /BIGX/ data upalf(25) /BIGY/ data upalf(26) /BIGZ/ data upalf(27) /EOS/ if (index(lowalf, c) > 0) type = LETTER else if (index(upalf, c) > 0) type = LETTER else if (index(digits, c) > 0) type = DIGIT else type = c return end define(ALPHA,10100) define(AMPER,38) # ampersand define(ARB,100) define(ATSIGN,64) define(BACKSLASH,92) define(BACKSPACE,8) define(BANG,33) # exclamation mark define(BAR,124) define(BIGA,65) define(BIGB,66) define(BIGC,67) define(BIGD,68) define(BIGE,69) define(BIGF,70) define(BIGG,71) define(BIGH,72) define(BIGI,73) define(BIGJ,74) define(BIGK,75) define(BIGL,76) define(BIGM,77) define(BIGN,78) define(BIGO,79) define(BIGP,80) define(BIGQ,81) define(BIGR,82) define(BIGS,83) define(BIGT,84) define(BIGU,8RD define(MAXNAME,30) # file name size in gettok define(MAXPTR,200) # number of defines in lookup define(MAXSTACK,100) # max stack depth for parser define(MAXTBL,1500) # max chars in all definitions define(MAXTOK,200) # max chars in a token define(MINUS,45) define(NCHARS,33) # number of special characters define(NEWLINE,10) define(NFILES,5) # max depth of file inclusion define(NO,0) define(NOT,BANG) # exclamation mark for now; change for ebcdic define(PERCENT,37) define(PERIOD,46) define(PLU int symbuf[128]; int nsym; /* no. words in buf */ int symoff; /* file offset of sym tab */ int symno; /* next available sym number */ /* table of common blocks */ #define NCOM 32 struct combuf { int com_name[2]; /* name of common block */ int com_sym; /* symbol number */ int com_len; /* length of block */ int com_off; /* offset of beginning of block */ } combuf[NCOM]; struct combuf *lastcom combuf; int bdata; /* block data flag */ struct segment *curseg { &impure }; struct chain *top { &: putsym(SEXT+SABS, get(3)); break; case 5: putsym(SEXT+STEXT, get(3)); break; case 6: putsym(SEXT+SDATA, get(3) + hdr.tsize); break; default: error("Unknown entry symbol type"); } break; case 14: /* Common definition */ cp = putcom(); symno++; cp->com_len = n = get(3); putsym(SEXT, n); break; case 15: /* Label */ skip(8); break; case 16: /* 3 bytes abs, 3 bytes pure */ put(get(2), RABS); case 9: /* 4 bytes pure */ word = n = get(4); dchain(&pure, n } symno++; break; case 24: /* Length of impure & pure segments */ n = get(3); reset(n, get(3)); break; case 25: /* Perform fullword chain */ case 27: /* No-op */ break; /* * New code (undocumented!) produced by CAL-R05 * - code 31 apparently means 'one byte absolute' * It will be handled correctly only if followed immediately * by an 'org' or another 1-byte code */ case 31: /* 1 byte absolute? */ put1byte(get(1)); break; default: /* Absolute data */ if ((c =- 31) if (ch->defloc > loc) break; if (ch->defloc == loc && (ch->refseg > 0)) { seg = ch->refseg; loc = ch->refloc; ch->refseg = -symno; ch->refloc = 0; ch = seg->first; continue; } ch = ch->next; } seg->loc = loc; curseg = seg; dchain(-symno, 0); } pass2() { register n; n = sizeof hdr; fixup(&pure, n, 0); fixup(&impure, n =+ hdr.tsize, 0); fixup(&pure, n =+ hdr.dsize, 1); fixup(&impure, n =+ hdr.tsize, 1); } fixup(seg, off, flag) struct segment *seg; { register struct cha5) define(BIGV,86) define(BIGW,87) define(BIGX,88) define(BIGY,89) define(BIGZ,90) define(BLANK,32) define(BUFSIZE,300) # pushback buffer for ngetch and putbak define(COLON,58) define(COMMA,44) define(DEFTYPE,10010) define(DIG0,48) define(DIG1,49) define(DIG2,50) define(DIG3,51) define(DIG4,52) define(DIG5,53) define(DIG6,54) define(DIG7,55) define(DIG8,56) define(DIG9,57) define(DIGIT,2) define(DOLLAR,36) define(DQUOTE,34) define(EOF,10003) define(EOS,10002) define(EQUALS,61) define(ERR,-1) define(ERROUTS,43) define(QMARK,63) define(RBRACE,125) define(RBRACK,93) define(READONLY,0) define(RPAREN,41) define(SEMICOL,59) define(SHARP,35) define(SLASH,47) define(SQUOTE,39) define(STAR,42) define(STDIN,0) define(STDOUT,1) define(character,integer) define(TAB,09) define(YES,1) define(NO,0) define(xor,ieor) end }; struct chain *avail { &end }; /* tricky structure for accessing bytes of a word */ struct { char byte[]; }; int ofile; main(argc, argv) char *argv[]; { if (argc != 3) error("Usage: cvo infile outfile"); close(0); if (open(argv[1], 0) != 0) error("Can't find input file"); if ((ofile = creat(argv[2], 0666)) < 0) error("Can't create output file"); pass1(); /* If block data program, make another pass through input */ if (bdata) { seek(0, 0, 0); close(ofile); if ((ofile = creat(arg&03777777); if (c==9) word.byte[0] = '\0'; put(word>>16, RTEXT+RHI); put(n&0177777, RTEXT); break; case 17: /* 3 bytes abs, 3 bytes impure */ put(get(2), RABS); case 10: /* 4 bytes impure */ word = n = get(4); dchain(&impure, n&03777777); n = word.byte[0]; word =+ hdr.tsize; word.byte[0] = c == 10 ? '\0' : n; put((n=word)>>16, RDATA+RHI); put(n&0177777, RDATA); break; case 18: /* Entry address */ case 19: /* Chain definition address */ skip(4); break; case 21: /* 2 b<= 0 || c > 60) error("Unknown control item"); if (bdata) skip(c*2); else while (c--) put(get(2), RABS); } } /* * Define a common block and write its name to the symbol table * (returns pointer to common table entry) */ putcom() { int name[2]; register struct combuf *cp; if ((cp = lastcom) >= &combuf[NCOM]) error("Too many common blocks"); cp->com_name[0] = get(4); cp->com_name[1] = get(4); cp->com_sym = symno; symbol(cp->com_name); lastcom = ++cp; return(cp - 1); } /* * Looin *ch; static zero, s; for (ch = seg->first; ch; ch = ch->next) if (ch->refseg <= 0) { if (flag) { seek(ofile, off + ch->defloc, 0); s = (-ch->refseg)<<20 | REXT+RHI<<16 | (-ch->refseg)<<4 | REXT; write(ofile, &s, sizeof s); } else { seek(ofile, off + ch->defloc + 1, 0); write(ofile, &ch->refloc.byte[1], 3); } } } /* * Read next record from object file */ char inbuff[126]; char *inp; readobj() { if (read(0, inbuff, 126) != 126) error("Input file i/o error"); ,2) define(GREATER,62) define(LBRACE,123) define(LBRACK,91) define(LESS,60) define(LETA,97) define(LETB,98) define(LETC,99) define(LETD,100) define(LETE,101) define(LETF,102) define(LETG,103) define(LETH,104) define(LETI,105) define(LETJ,106) define(LETK,107) define(LETL,108) define(LETM,109) define(LETN,110) define(LETO,111) define(LETP,112) define(LETQ,113) define(LETR,114) define(LETS,115) define(LETT,116) define(LETTER,1) define(LETU,117) define(LETV,118) define(LETW,119) define(LETX,120) define(LETY,12# /* * Interdata -> Unix object code converter */ /* Relocation bits */ #define RABS 00 #define RTEXT 02 #define RDATA 04 #define REXT 010 #define RHI 01 /* Symbol types */ #define SABS 01 #define STEXT 02 #define SDATA 03 #define SEXT 040 /* a.out header */ struct { int mword; int tsize; int dsize; int bsize; int ssize; int entrypt; int unused; int rflag; } hdr; /* External reference chain */ struct chain { struct chain *next; /* link to next entry */ int defloc; /* location of referencev[2], 0666)) < 0) error("can't create output file"); blkdata(); } putbuf(&pure); putbuf(&impure); putsymbuf(); hdr.ssize = symno * 16; hdr.mword = 0407; seek(ofile, 0, 0); write(ofile, &hdr, sizeof hdr); if (bdata == 0) pass2(); } pass1() { register c, n; register struct combuf *cp; int name[2], word; readobj(); for(;;) switch (c = cget()) { case 1: /* End of program */ return; case 2: /* Reset sequence number */ break; case 3: /* Block data initialization */ cp = getk up a common block name & return a pointer to its common table entry */ getcom() { int name[2]; register struct combuf *cp; name[0] = get(4); name[1] = get(4); for (cp = combuf; cp < lastcom; cp++) if (cp->com_name[0] == name[0] && cp->com_name[1] == name[1]) return(cp); error("Undefined common block reference"); } /* * Link an entry into chain of possible external references * (sorted by location). */ dchain(seg, loc) struct segment *seg; { register struct chain *ch, *lastch, *av; if ( inp = &inbuff[4]; } /* * Get next command code from object file */ cget() { register n; if ((n = get(1)) == 0) { readobj(); n = get(1); } return(n); } /* * Get next n bytes (1 - 4) from object file */ get(n) { register i, w; w = *inp++; for (i=1; icom_off = 1; /* flag for second pass */ bdata++; skip(3); break; case 5: /* Pure address */ curseg = &pure; goto addr; case 6: /* Impure address */ curseg = &impure; addr: if ((n = get(3) - curseg->loc) != 0) org(n); break; case 11: /* Common reference */ cp = getcom(); curseg->loc =- 4; dchain(-cp->com_sym, get(3)); curseg->loc =+ 4; break; case 13: /* Entry */ name[0] = get(4); name[1] = get(4); symbol(name); symno++; switch (cget()) { case 4ytes abs, 2 bytes pure */ put(get(2), RABS); case 7: /* 2 bytes pure */ put(get(2), RTEXT); break; case 22: /* 2 bytes abs, 2 bytes impure */ put(get(2), RABS); case 8: /* 2 bytes impure */ put(get(2) + hdr.tsize, RDATA); break; case 12: /* EXTRN */ name[0] = get(4); name[1] = get(4); symbol(name); putsym(SEXT, 0); switch (cget()) { case 5: mkchain(&pure, get(3)); break; case 6: mkchain(&impure, get(3)); break; default: error("Unknown extrn address type"); (seg > 0) && loc >= seg->maxloc) /* ignore forward refs */ return; if ((av = avail) >= top) brk(top =+ 64); lastch = &curseg->first; for (ch = curseg->first; ch; ch = ch->next) { if (ch->defloc > curseg->loc) break; lastch = ch; } av->next = ch; lastch->next = av; av->defloc = curseg->loc; av->refseg = seg; av->refloc = loc; avail = ++av; } /* * Make chain of external references */ mkchain(seg, loc) struct segment *seg; { register struct chain *ch; for (ch = seg->first; ch;) { \n", 1); exit(1); } /* * Initialize offsets & buffers */ reset(dsize, tsize) { register n; hdr.dsize = dsize; hdr.tsize = tsize; pure.offset[0] = n = sizeof hdr; impure.offset[0] = n =+ tsize; pure.offset[1] = n =+ dsize; impure.offset[1] = n =+ tsize; impure.maxloc = impure.loc = pure.nchar = impure.nchar = 0; curseg = &impure; symoff = n =+ dsize; nsym = 0; } /* * Put a halfword of code & corresponding relocation bits to output */ put(code, rel) { register struct segment *seg; register i; seg = curseg; if (seg->nchar >= 512) putbuf(seg); i = seg->nchar; seg->obuf[0][i] = code>>8; seg->obuf[0][i+1] = code&0377; seg->obuf[1][i] = rel>>8; seg->obuf[1][i+1] = rel&0377; seg->nchar = i+2; seg->loc =+ 2; if (seg->loc > seg->maxloc) seg->maxloc = seg->loc; } /* * Put out 1 absolute byte * (This had better be followed by an org) */ put1byte(code) { register struct segment *seg; register i; seg = curseg; if (seg->nchar >= 512) putbuf(seg); i = seg->nchar; seg->obu(cp->com_off) { cp->com_off = n; n =+ cp->com_len; cp->com_len = 0; } /* reset buffers & re-process input */ reset(n, 0); readobj(); for (;;) switch (c = cget()) { case 1: /* End of program */ return; case 2: /* Reset sequence number */ break; case 3: /* block data initialization */ cp = getcom(); org(cp->com_off + get(3) - curseg->loc); break; case 14: /* Common definition */ cp = getcom(); skip(3); symbol(cp->com_name); if (cp->com_len) putsym(SEXT, cp->com ; tend = q; if (stat(to, &stbuf) < 0 || (stbuf.flags&060000) != 040000) { write(1, target, sizeof target); exit(1); } tdev = stbuf.dev; tino = stbuf.ino; buff = sbrk(BUFFSIZE); close(0); close(2); dcopy(1); } dcopy(firsttime) { register fi, fo, len; register t0, t1; int status; if (vflag) { puts(from); putchar('\n'); } if (stat(from, &stbuf) < 0) { msg("can't find"); return; } switch (stbuf.flags & 060000) { /* ordinary file */ case 0000000: if ((fi = open(from, 0)) , *t, *p; f = fend; t = tend; if (f[-1] != '/') *f++ = '/'; if (t[-1] != '/') *t++ = '/'; for (p = fn; p < &fn[14] && (*t = *f = *p++); ++t, ++f) if (t>=&to[sizeof(to)-1] || f>=&from[sizeof(from)-1]) { msg("name too long"); return(0); } fend = f; tend = t; return(1); } lstpath() { register char *f, *t; f = fend; t = tend; do --f; while (*--t != '/'); *f = *t = '\0'; fend = f; tend = t; } msg(s) char *s; { if (!vflag) puts(from); puts(" -- "); puts(s); putchar('\n'); p) { seek(disc, dirp<<8, 0); if (read(disc, buffer, sizeof buffer) < 0) return(-1); for (bp = &buffer[1]; bp < &buffer[5*12+1]; bp =+ 12) if (bp[9] & (1<<28)) if ((*func)(bp)) return(1); dirp = buffer[0]; } return(0); } char *mdtab[] { "co", "ch", "in" }; struct { int *intp; }; /* * check whether filename in directory matches given pattern */ match(fn) char *fn; { register i; register char *p; register mode; p = filename; for (i=0; i<8; p++) if ((*p = fn[i++]) == ' ')/* * al: allocate empty files * * usage: al file1 ... [ -mode ] filen filem [ -mode ] ... * * author: ross nealon (uow) */ int fd; int mode; char c; char *name; main(argc, argv) char **argv; { if (argc < 2) { printf("usage: al [-mode] filename ...\n"); exit(0); } mode = 0666; while (--argc) { name = *++argv; if (*name == '-') { mode = 0; while((c = *++name) >= '0' && c <= '7') mode = (mode << 3) + (c - '0'); if (mode > 0777) { printf("bad file mode: %o \f[0][i] = code; seg->obuf[1][i] = 0; seg->nchar = ++i; seg->loc++; if (seg->loc > seg->maxloc) seg->maxloc = seg->loc; } /* * Adjust location in current segment by offset of (off) */ org(off) { register struct segment *seg; register n; seg = curseg; if ((n = off) > 0 && seg->loc >= seg->maxloc && n < 512) { while (n--) put1byte(0); return; } putbuf(seg); seg->offset[0] =+ n; seg->offset[1] =+ n; seg->loc =+ n; if (seg->loc > seg->maxloc) seg->maxloc = seg->loc; } /* * Flush o_len); else putsym(SEXT+SDATA, cp->com_off); break; case 24: /* Length of impure & pure segments */ skip(6); break; default: if ((c =- 31) <= 0 || c > 60) error("Illegal control item in block data program"); while (c--) put(get(2), RABS); } } < 0) msg("can't open"); else if ((fo = creat(to, stbuf.flags&07777)) < 0) { msg("can't create"); close(fi); } else { while((len = read(fi, buff, BUFFSIZE)) > 0) { if (write(fo, buff, len) != len) { msg("write error"); break; } } if (len < 0) msg("read error"); close(fi); close(fo); chown(to, (stbuf.gid<<8) | stbuf.uid); smdate(to, stbuf.mtime); } break; /* special file */ case 020000: case 060000: if (mknod(to, stbuf.flags, stbuf.addr[0]) < 0} puts(s) char *s; { register char *p; for (p = s; putchar(*p); p++) ; } break; *p++ = '.'; for (i=8; i<11; p++) if ((*p = fn[i++]) == ' ') break; *p++ = '\0'; if (!amatch(filename, pattern)) return(0); printf("%.8s %.3s", fn, &fn[8]); if (lflag) { mode = fn[36]>>5; printf(" %s", mdtab[mode]); printf("%6d", (fn[22]<<8) | fn[23]); if (mode == 0) printf("%8d", fn.intp[4] - fn.intp[3] + 1); else printf("%8d", fn.intp[10]); } if (putchar('\n') <= 0) return(1); return(0); } amatch(as, ap) char *as, *ap; { register char *s, *p; register scc; n", mode); exit(1); } continue; } fd = creat(name, mode); if (fd < 0) { printf("can't create %s\n", name); exit(1); } close(fd); } exit(0); } utput buffers */ putbuf(seg) { register n, i; if ((n = seg->nchar) <= 0) return; for (i=0; i<=1; i++) { seek(ofile, seg->offset[i], 0); write(ofile, seg->obuf[i], n); seg->offset[i] =+ n; } seg->nchar = 0; } /* * Copy a symbol name to the output file */ symbol(name) char *name; { int sym[2]; register c, i; register char *p, *q; p = sym; q = name; for (i=8; i>0; i--) { if ((c = *q++) == ' ') c = '\0'; *p++ = c; } putsym(sym[0], sym[1]); } /* * Write two words to the symbol # char usage[] "Usage: dcopy -v input-directory output-directory\n"; char source[] "Input directory not found\n"; char target[] "Output directory not found\n"; struct { int dev; int ino; int flags; char nlinks; char uid; char gid; char size0; int size1; int addr[8]; int actime[2]; int mtime[2]; } stbuf; char *buff; /* buffer allocated dynamically */ #define BUFFSIZE 1024*10 char from[128], to[128]; char *fend from; char *tend; int tdev, tino; /* device & inode of target directory */ int f) msg("can't mknod"); else { chown(to, (stbuf.gid<<8) | stbuf.uid); smdate(to, stbuf.mtime); } break; /* directory */ case 040000: t0 = stbuf.mtime[0]; t1 = stbuf.mtime[1]; if (!firsttime) { if (stbuf.dev != fdev || (stbuf.dev == tdev && stbuf.ino == tino)) break; if (!fork()) { execl("/bin/mkdir", "mkdir", to, 0); msg("can't exec mkdir"); exit(1); } wait(&status); if (status) break; chmod(to, stbuf.flags&07777); chown(to, (stbuf.gid< 1 && *(p=argv[1]) == '-') { ++argv; --argc; while (c = *++p) switch(c) { case 'l': case 'L': ++lflag; break; } } if (argc < 2) { printf("Usage: dfi [ -l ] dev [ pattern ]\n"); exit(1); } if ((disc = open(argv[1], 0)) < 0) { printf("Can't open %s\n", argv[1]); exit(1); } int c, cc, ok, lc; s = as; p = ap; if (scc = *s++) if ((scc =& 0177) == 0) scc = 0200; switch (c = *p++) { case '[': ok = 0; lc = 077777; while (cc = *p++) { if (cc==']') { if (ok) return(amatch(s, p)); else return(0); } else if (cc=='-') { if (lc<=scc && scc<=(c = *p++)) ok++; } else if (scc == (lc=cc)) ok++; } return(0); default: if (c!=scc) return(0); case '?': if (scc) return(amatch(s, p)); return(0); case '*': retur/* * export dev filename [recl] * * Copy a file to an OS-formatted disc. * Output file will be indexed, lrecl=recl, blksize 1/1. * * Note: no check is made to see whether the OS file already exists -- * this may cause duplicate filenames. */ /* OS directory structure */ struct dir { char fnm[12]; int flba; int llba; int keyl; int date[2]; int counts; char atrb; char dbsz; char ibsz; char flro; int csec; int filler; }; struct dirblk { int nextdir; struct dir dirent[5]; }; /* OS distable */ putsym(s1, s2) { if (nsym >= 128) putsymbuf(); symbuf[nsym++] = s1; symbuf[nsym++] = s2; } /* * Flush the symbol table buffer */ putsymbuf() { if (nsym <= 0) return; seek(ofile, symoff, 0); write(ofile, symbuf, nsym*4); symoff =+ nsym*4; nsym = 0; } /* * Second pass for block data program -- * turn initialized common blocks to data */ blkdata() { register struct combuf *cp; register n, c; /* find total length of commons */ n = 0; for (cp = combuf; cp < lastcom; cp++) if dev; /* device of source directory */ int vflag; main(argc, argv) char **argv; { register char *p, *q; if (--argc > 0 && **++argv == '-') { if (argv[0][1] == 'v') vflag++; argc--; argv++; } if (argc != 2) { write(1, usage, sizeof usage); exit(1); } p = argv[0]; for (q = from; *q = *p++; *q++) ; fend = q; if (stat(from, &stbuf) < 0 || (stbuf.flags&060000) != 040000) { write(1, source, sizeof source); exit(1); } fdev = stbuf.dev; p = argv[1]; for (q = to; *q = *p++; *q++) 8) | stbuf.uid); } if ((fi = open(from, 0)) < 0) msg("can't open"); else { while (read(fi, buff, 16) == 16) if ((buff[0] | buff[1]) != 0 && (buff[2] != '.' || (buff[3] != '\0' && (buff[3] != '.' || buff[4] != '\0'))) && nxtpath(&buff[2])) { dcopy(0); lstpath(); } close(fi); } if (!firsttime) { stbuf.mtime[0] = t0; stbuf.mtime[1] = t1; smdate(to, stbuf.mtime); } break; } return; } nxtpath(fn) char *fn; { register char *f if (argc > 2) pattern = argv[2]; mfd(disc, match); } /* * read the directory on the disc assigned to fd , passing * each directory block to function . * if returns nonzero, stop reading the directory. * returns -1: disc error * 0: all directory blocks read * 1: requested termination */ mfd(disc, func) int (*func)(); { register int dirp, *bp; seek(disc, 0, 0); if (read(disc, buffer, sizeof buffer) < 0) return(-1); dirp = buffer[2]; while (dirn(umatch(--s, p)); case '\0': return(!scc); } } umatch(s, p) char *s, *p; { if(*p==0) return(1); while(*s) if (amatch(s++,p)) return(1); return(0); } c information */ int disc; /* fd for OS disc */ int bitmapsector; /* bit map */ int bitmap[19584/32]; int dirsector; /* directory block */ struct dirblk dirbuff; struct dir *dirp; /* ¤t dir entry */ int indexsector; /* index block */ int indexbuf[64]; int *indexp; /* &next free index */ int offset; /* no. of chars in file */ int recl; /* logical record length of file */ char buffer[256]; main(argc, argv) char *argv[]; { register len, i; if (argc < 3) error("Usage: export dev filename [recl]"); if ((disc = open(argv[1], 2)) < 0) error("Can't open %s", argv[1]); close(0); if (open(argv[2], 0) != 0) error("Can't find %s", argv[2]); if (argc < 4 || (recl = atoi(argv[3])) <= 0) recl = 256; getmap(); oscreat(argv[2]); while ((len = read(0, buffer, 256)) > 0) { offset =+ len; while (len < 256) buffer[len++] = '\0'; /* pad last block with zeroes */ oswrite(buffer); } if (len < 0) error("Input file read error"); /* because of the peculiar way in which os/32 functionew * directory block. Return a pointer to the dir entry. */ makdir() { register struct dir *dp; int sector; seek(disc, 8, 0); if (read(disc, §or, sizeof sector) <= 0) error("Volume descriptor read error"); if (sector == 0) error("No directory entries"); while(sector) { dirsector = sector; xseek(disc, dirsector); if (xread(disc, &dirbuff, sizeof dirbuff)) error("Directory block read error"); for (dp = &dirbuff.dirent[0]; dp < &dirbuff.dirent[5]; dp++) if ((dp->atrb&020) == 0) izeof dirbuff); } /* * Read bit map */ getmap() { seek(disc, 20, 0); if (read(disc, &bitmapsector, sizeof bitmapsector) <= 0) error("Volume descriptor read error"); xseek(disc, bitmapsector); if (xread(disc, bitmap, sizeof bitmap)) error("Bit map read error"); } /* * Rewrite bit map */ putmap() { xseek(disc, bitmapsector); xwrite(disc, bitmap, sizeof bitmap); } /* * Allocate one free sector from the bit map -- return sector number. */ alloc() { register d, i, b; for (d=0; d= 'a' && c <= 'z') c =+ 'A'-'a'; namebuff[i++] = c; } while (i < 8) namebuff[i++] = ' '; if (c = '.') for (p++; (c = *p) != '\0'; p++) if (i < 11) { if (c>='a' && c<='z') c =+ 'A'-'a'; namebuff[i++] = c; } while (i < 11) namebuff[i++] = ' '; seek(disc, 8, 0); /* pointer to first directory block */ xread(disc, §, sizeof sect); while (sect) { xseek(disc, sect); if (xread(disc, &dirbuff, sizeof dirbuff)) error("Directory blocks, if the * logical file size is an exact multiple of 256 bytes, an extra * block must be allocated. I don't know whether this is a bug * or a feature. */ if (recl == 256) offset = (offset+255)&~0377; else offset = (offset/recl)*recl; if ((offset&0377) == 0) oswrite(buffer); osflush(); putmap(); } /* * Error exit */ error(s, x) { printf(s, x); putchar('\n'); exit(1); } /* * Initialize directory entry and first index block for new OS file */ oscreat(name) { register struct dir * return(dp); sector = dirbuff.nextdir; } xseek(disc, dirsector); dirsector = alloc(); dirbuff.nextdir = dirsector; xwrite(disc, &dirbuff, sizeof dirbuff); zero(&dirbuff, sizeof dirbuff); return(&dirbuff.dirent[0]); } /* * Write one sector of the OS file */ oswrite(buff) { register sector; sector = alloc(); if (indexp >= &indexbuf[64]) nextblk(); *indexp++ = sector; xseek(disc, sector); xwrite(disc, buff, 256); } /* * Allocate the next index block */ nextblk() { register sector; ap; d++) if (bitmap[d] != -1) { for (i=31; bitmap[d]&(b = 1< 3 && (fd = creat(argv[3], 0666)) < 0) error("Can't create %s", argv[3]); while ((len = osread(&osfile, buffer)) > 0) write(fd, buffer, len); } error(s, x) { printf read error"); for (dp = &dirbuff.dirent[0]; dp < &dirbuff.dirent[5]; dp++) if ((dp->atrb&020) && match(dp, namebuff)) return(dp); sect = dirbuff.nextdir; } return(0); } /* * String comparison */ match(dirname, name) char *dirname, *name; { register char *p, *q; register count; p = dirname; q = name; for (count = 0; count < 11; count++) if (*p++ != *q++) return(0); return(1); } /* * Read a sector from OS file */ osread(afp, buff) struct osfile *afp; { register struct osfile *fdp; dirp = dp = makdir(); zero(dp, sizeof *dp); packfd(name, dp->fnm); dp->atrb = 0120; /* indexed file */ dp->ibsz = dp->dbsz = 1; /* blksize 1/1 */ dp->keyl = recl; /* record length */ indexsector = alloc(); dp->flba = indexsector; indexbuf[0] = 0; indexp = &indexbuf[2]; } /* * Zero a block of memory */ zero(addr, len) char *addr; { register char *p; register n; p = addr; for (n=len; n--; *p++ = '\0') ; } /* * Pack a file name into OS directory format, converting lowercase * let/* * xlib libfile directory * * expand an interdata object library */ char record[128]; int out; char anon[] { "anon000 " }; main(argc, argv) char *argv[]; { register n, in; register char *anonp; if (argc != 3) error("usage: xlib libfile directory"); if ((in = open(argv[1], 0)) < 0) error("can't open %s", argv[1]); if (chdir(argv[2]) < 0) error("bad directory %s", argv[2]); anonp = &anon[6]; while((n = read(in, record, 126)) == 126) { if (record[4] == 15) mkobj(&record[5]); elsef); /* copy program to a.out file */ while (progsize >= 256) { read(in, ibuf, 256); for (i=0; i<64; i++) putw(ibuf[i], obuf); progsize =- 256; } if (progsize > 0) { read(in, ibuf, progsize); for (i=0; iatrb)>>5) { case 00: /* contiguous file */ fp->iscontig = 1; fp->size = (dp->llba - dp->flba + 1)*256; fp->sector = dp->flba; break; case 02: /* indexed file */ fp->ibsize = dp->ibsz; fp->dbsize = dp->dbsz; fp->size p; register len; fp = afp; len = fp->size - fp->offset; if (len > 256) len = 256; if (len <= 0) return(len); if (!fp->iscontig && --fp->nleft < 0) nextblk(fp); xseek(disc, fp->sector++); if (xread(disc, buff, len)) printf("Read error - offset %o", fp->offset); fp->offset =+ len; return(len); } /* * Find next block of indexed file */ nextblk(afp) struct osfile *afp; { register struct osfile *fp; fp = afp; if (fp->indexp >= &fp->indexbuf[fp->ibsize * 256/4]) { xseek(disc, fp->indeters to uppercase. */ packfd(name, dest) char *name, *dest; { register char *p; register c, i; i = 0; for (p=name; (c = *p) != '\0' && c != '.'; p++) if (i < 8) { if (c >= 'a' && c <= 'z') c =+ 'A'-'a'; dest[i++] = c; } while(i < 8) dest[i++] = ' '; if (c = '.') for (p++; (c = *p) != '\0'; p++) if (i < 11) { if (c>='a' && c<='z') c =+ 'A'-'a'; dest[i++] = c; } while (i < 11) dest[i++] = ' '; } /* * Get an unused directory entry. If none found, allocate a n sector = alloc(); indexbuf[1] = sector; xseek(disc, indexsector); xwrite(disc, indexbuf, sizeof indexbuf); indexbuf[0] = indexsector; indexsector = sector; indexp = &indexbuf[2]; } /* * Update directory information and flush the last index block */ osflush() { while (indexp < indexbuf[64]) *indexp++ = 0; indexbuf[1] = 0; xseek(disc, indexsector); xwrite(disc, indexbuf, sizeof indexbuf); dirp->csec = offset/recl; dirp->llba = indexsector; xseek(disc, dirsector); xwrite(disc, &dirbuff, s if (record[4] == 24) { mkobj(anon); if (++(*anonp) > '9') { *anonp = '0'; if (++(anonp[-1]) > '9') { anonp[-1] = '0'; (anonp[-2])++; } } } if (out) write(out, record, 126); } } mkobj(name) char *name; { char fn[16]; register i, c; register char *p; for (i=0; i<8; i++) if ((c = name[i]) == ' ') break; else { if (c >= 'A' && c <= 'Z') c =+ 'a'-'A'; fn[i] = c; } for (p = ".obj"; fn[i++] = *p; p++) ; if (out) close(out); if ((out = creat(f/* * import dev filename [newname] * * - read file from OS-formatted disc and * copy it to file (default - standard output) */ struct osfile { /* information about os file */ int iscontig; /* contiguous file */ int size; /* size of file (in bytes) */ int sector; /* current sector */ int offset; /* current offset in bytes */ int nleft; /* sectors left in current block */ int *indexbuf; /* buffer for index block */ int *indexp; /* ¤t index */ int ibsize; = dp->csec * (dp->keyl & 077777); fp->indexbuf = sbrk(fp->ibsize * 256); fp->indexbuf[1] = dp->flba; fp->indexp = &fp->indexbuf[fp->ibsize * 256/4]; break; default: error("Illegal os file type %o", dp->atrb); } } /* * Find directory entry for given file */ getdir(name) { char namebuff[11]; struct dirblk dirbuff; int sect; register struct dir *dp; register i; register char *p, c; /* convert filename to form in which it appears in directory */ i = 0; for (p=name; (c = *p) != '\0' && xbuf[1]); if (xread(disc, fp->indexbuf, fp->ibsize * 256)) error("Index block read error"); fp->indexp = &fp->indexbuf[2]; } fp->sector = *fp->indexp++; fp->nleft = fp->dbsize - 1; } xseek(fd, sect) { seek(fd, sect*256, 0); } xread(fd, addr, len) int *addr; { extern int errno; register io; if ((io = read(fd, addr, len)) < 0) return(1); return(0); } /MT disc import - copy file from Interdata OS/MT disc log - log input/output from terminal session onto a file press - compress strings of duplicate characters from a file rkdump - transform image of PDP-11 UNIX filesystem to dump tape format tc - mag tape commands tm - mag tape map of records and filemarks xlib - expand Interdata CAL object library to a.out files #define THRESH 4 int ibuf[131], obuf[131]; char cbuf[128]; int unflag; main(argc, argv) char **argv; { if (argc > 1 && argv[1][0] == '-') { unflag++; argc--; argv++; } if (argc > 1 && (ibuf[0] = open(argv[1], 0)) < 0) { printf("Can't find %s\n", argv[1]); exit(1); } if (argc <= 2) obuf[0] = dup(1); else if ((obuf[0] = creat(argv[2], 0666)) < 0) { printf("Can't create %s\n", argv[2]); exit(1); } if (unflag) unpress(); else press(); fflush(obuf); } press() { register c,/* * attach/detach ttyid [...] * * Turn terminals on and off by changing ttys file and signalling init */ char tfile[] "/etc/ttys"; char tbuf[512]; int len; main(argc, argv) char **argv; { register char *p; register set, fd, tty; char *find(); if (argc <= 1) error("Usage: %s tty-id ...\n", *argv); if ((fd = open(tfile, 2)) < 0) error("Can't open %s\n", tfile); if ((len = read(fd, tbuf, sizeof tbuf)) == sizeof tbuf) error("?? %s too big ??", tfile); if (len <= 0) error("Can't read %s",/* * Perform backspace-delete function as in tty.c * - useful after an edit session when you forgot stty */ main() { register i, c, col; extern fout; static line[256]; fout = dup(1); col = 0; while (c = getchar()) { switch (c) { case '\n': for (i=0; i= 0) { if (c == lastc) { if (++nsame == THRESH) { putstr(count-THRESH+1); count = 0; while ((c=getc(ibuf))==lastc && nsame < 128) nsame++; putc(0200|(nsame-1), obuf); putc(lastc, obuf); if (c < 0) break; nsame = 1; lastc = c; } } else { nsame = 1; lastc = c; } cbuf[count++] = c; if (count >= 128) { putstr(count); count = 0; } } putstr(count); } putstr(n) { reg tfile); /* Determine which name command was called by */ for (p = *argv; *p; p++) ; while (p >= *argv && *p != '/') p--; set = p[1]=='d'? '0' : '1'; while (--argc) { if ((*++argv)[1] != '\0') error("Use single-character tty-ids"); tty = (*argv)[0]; if ((p = find(tty)) == 0) error("tty%c not found", tty); *p = set; } seek(fd, 0, 0); if (write(fd, tbuf, len) != len) error("Can't write %s", tfile); if (kill(1, 1) < 0) error("Can't signal init process"); } /* * Find entry f/* * cv [-]{bcdho}{bcdhlo} n [n...] */ char digits[] "0123456789abcdef"; main(argc, argv) char *argv[]; { register char *p; register ibase, obase, i; if (argc < 3) error("Arg count"); p = argv[1]; if (*p = '-') p++; ibase = cvbase(*p); obase = cvbase(*++p); for (i=2; i 0) printf("%d:%d\n", prev, nrec); prev = len; nrec = 0; } if (done) break; if (len == -1) { printf("** Read Error b%d\n", rec); if dup(fp[1].p_out); execl("/bin/sh", "-", 0); error("Can't exec shell"); } close(fp[1].p_out); close(0); dup(fp[1].p_in); pipeline(); } pipeline() { register n; while ((n = read(0, buff, sizeof buff)) > 0) { write(1, buff, n); write(log, buff, n); } exit(); } error(s, x) { printf(s, x); putchar('\n'); exit(1); } ) char **argv; { register tf; register count; register char **pp; if (argc > 1 && argv[1][0] == '-') { tdrive = argv[1][1]; argc--; argv++; } if (argc < 2 || (tcom[0] = lookup(argv[1])) < 0) { printf(usage); for (pp = clist; *pp; pp++) printf("\t%s\n", *pp); return; } if ((tf = open(tname, 0)) < 0) { printf("Can't open %s\n", tname); exit(1); } if (argc < 3 || tcom[0] == 7 || (count = atoi(argv[2])) <= 0) count = 1; while (count--) { stty(tf, tcom); if (errno) { ister i; if (n) { putc(n-1, obuf); for (i = 0; i= 0) { if (n&0200) { n =& 0177; if ((c = getc(ibuf)) < 0) inerr(); while (n-- >= 0) putc(c, obuf); continue; } else { while (n-- >= 0) { if ((c = getc(ibuf)) < 0) inerr(); putc(c, obuf); } } } } inerr() { printf("Input file format error\n"); exit(1); } or given tty */ char * find(tty) { register char *p; for (p = tbuf; p < &tbuf[len]; ) { if (p[1] == tty) return(p); while (*p++ != '\n') ; } return(0); } error(s, x) { printf(s, x); putchar('\n'); exit(1); } se 'L': return(10); case 'd': case 'D': return(0); case 'h': case 'H': return(16); } error("Conversion type"); } error(s) { printf("Error: %s\n", s); exit(1); } getnum(s,base) char *s; { register char *p; register c, n; n = 0; if (base == 1) { for (p = s; c = *p; p++) n = (n<<8) + c; return(n); } if (base == 0) base = 10; if (*(p = s) == '-') p++; for (; c = *p; p++) { if (c >= 'a' && c <= 'f') c =+ '0'+10-'a'; if (c >= 'A' && c <= 'F') c =+ '0'+10-'A'; if ((c =(!errflag) done++; } nrec++; if (len == 0) { rec = 0; if (nrec >= maxtm) done++; } else if (rec >= maxrec) done++; } } usage() { printf("Usage: tm [-drive] [-t] [-r] [-e]\n"); exit(1); } Miscellaneous Wollongong University commands al - create files in specified mode attach - attach/detach terminals by changing /etc/ttys and signalling init beep - ring terminal bell bs - perform tty-like backspace-delete function on a file cv - convert numbers to different bases cvo - convert Interdata CAL object format to a.out cvtask - convert Interdata TET task format to a.out dcopy - recursively copy directory and contents dfi - display files on Interdata OS/MT disc export - copy file onto Interdata OS perror("Stty"); exit(1); } } } lookup(arg) register char *arg; { register struct opt *op; register char *name, *p; if (*arg == '-') arg++; for (op = optab; name = op->name; op++) { for (p = arg; *p == *name; p++) if (*name++ == 0) return(op->value); } return(-1); } cc -s -o al al.c cc -s -o attach attach.c; chmod 4750 attach cc -s -o beep beep.c cc -s -o bs bs.c cc -s -o cv cv.c cc -s -o cvo cvo.c cc -s -o cvtask cvtask.c cc -s -o dcopy dcopy.c cc -s -o dfi dfi.c cc -s -o export export.c cc -s -o import import.c cc -s -o log log.c cc -s -o press press.c cc -s -o rkdump rkdump.c cc -s -o tc tc.c cc -s -o tm tm.c cc -s -o xlib xlib.c /* beep */ main() { write(2, "\07", 1); } - '0') < 0 || c > base) error("Number syntax"); n = n*base + c; } return(*s == '-' ? -n : n); } putnum(num, base) { register n, c, i; char buff[32]; extern int ldivr; n = num; if (base == 0) { base = 10; if (n < 0) { n = -n; putchar('-'); } } i = 31; if (base == 1) { while (c = n&0377) { buff[i--] = c; n =>> 8; } } else do { n = ldiv(0, n, base); buff[i--] = digits[ldivr]; } while (n); while (++i < 32) putchar(buff[i]); } cpall \ al \ beep \ bs \ cv \ cvo \ cvtask \ dcopy \ dfi \ export \ import \ log \ press \ rkdump \ tc \ tm \ xlib \ /usr/bin cp attach /etc rm /etc/detach ln /etc/attach /etc/detach rm \ al \ attach \ beep \ bs \ cv \ cvo \ cvtask \ dcopy \ dfi \ export \ import \ log \ press \ rkdump \ tc \ tm \ xlib # /* * Make Interdata UNIX dump tape from PDP-11 UNIX RK disc image * * rkdump fsb filesystem * f take output tape from arglist * s specify tape size in feet (feet = blocks/9) * b specify tape size in blocks */ char *dargv[] { 0, "0", "/dev/dfix", 0 }; #include "/usr/sys/ino.h" #define MAXSIZE 1000 #define XCBLKINT 128 /*******/ #define XCBLKSH 256 /*******/ /* * Inode structure as it appears on * PDP-11 disk. */ struct iinode { short ii_mode; char ii_nlink; char ii_uid; char ii_gid;tf("%s:\n", argv[1]); fi = open(argv[1], 0); if(fi < 0) { printf("cannot open %s\n", argv[1]); exit(); } printf("RK filesystem dump\n"); sync(); bread(1, &sblock); isize = swab(sblock.s_isize); /***/ talist = sbrk(size(0, isize*(512*4/sizeof (struct iinode))*512)); tap = talist; if(tap == -1) { printf("No memory\n"); exit(); } nfil = 0; nblk = size(0, isize*(512*4/sizeof (struct iinode))); /***/ ino = 0; for(i=0; i= tsize) taddr = 0; } rdline() { char c; /***/ loop: c = 0; read(0, &c, 1); if(c == 0) exit(); if(c != '\n') goto loop; } number(s) char *s; { register n, c; n = 0; while(c = *s++) { if(c<'0' || c>'9') continue; n = n*10+c-'0'; } return(n); } size(s0, s1) { register s; extern ldivr; s = ldiv(s0&0377, s1, 512); if(ldivr) s++; return(s); } otape() { register char *p; fo = creat(ofile, completely generated 1 = state awaiting generation 2 = state with an empty production in closure */ extern int stsize ; /* maximum number of states, at present */ extern int memsiz ; /* maximum size for productions and states */ extern int mem0[] ; /* added production */ extern int *mem ; extern int amem[]; /* action table storage */ extern int actsiz; /* action table size */ extern int memact ; /* next free action table position */ extern int nprod ; /* number of productions */ extern ier of nonterminals */ extern int lastred ; /* the number of the last reduction of a state */ extern int ftable; /* y.tab.c file */ extern int foutput; /* y.output file */ extern int cin; /* current input file */ extern int cout; /* current output file */ extern int arrndx; extern int zzcwset; extern int zzpairs ; extern int zzgoent ; extern int zzgobest ; extern int zzacent ; extern int zzacsave ; extern int zznsave ; extern int zzclose ; extern int zzrrconf ; extern int zzsrconf ; extern char *ctokn; s char ii_size0; short ii_size1; short ii_addr[8]; short ii_atime[2]; short ii_mtime[2]; }; /* modes */ #define IALLOC 0100000 #define IFMT 060000 #define IFDIR 040000 #define IFCHR 020000 #define IFBLK 060000 #define ILARG 010000 #define ISUID 04000 #define ISGID 02000 #define ISVTX 01000 #define IREAD 0400 #define IWRITE 0200 #define IEXEC 0100 struct { short s_isize; short s_fsize; short s_junk[254]; } sblock; char *ofile; int *talist; int fi; int buf[XCBLKINT]; short dbuf[XCBLKSH]; short ib]; ip++) { ino++; if(ip->ii_mode == 0 || ip->ii_nlink == 0) { *tap++ = -1; continue; } s = size(ip->ii_size0&0377, swab(ip->ii_size1)) + 1; if (s>MAXSIZE && aflg==0 && iflg!=0) { printf("%l big; not dumped.\n", ino); goto no; } nfil++; nblk =+ s; *tap++ = s; continue; no: *tap++ = 0; } } printf("%l files\n%l blocks\n", nfil, nblk); i = ldiv(0, nblk, ldiv(0, tsize, 10)); printf("%l.%l tapes\n", i/10, i%10); tap = buf; clrbuf(tap); *tap++ = isize*siz); np->i_mtime[1] = (swab(ip->ii_mtime[0])<<16) | swab(ip->ii_mtime[1]); swrite(dbuf); if(swab(ip->ii_mode) & (IFBLK&IFCHR)) { if(sz != 0) printf("special\n"); return; } dirflag = ((swab(ip->ii_mode)&IFMT) == IFDIR); for(p = &ip->ii_addr[0]; p < &ip->ii_addr[8]; p++) if(*p) { if(swab(ip->ii_mode)&ILARG) { bread(swab(*p), ibuf); for(q = &ibuf[0]; q < &ibuf[XCBLKSH]; q++) if(*q) { if(p == &ip->ii_addr[7]) { bread(swab(*q), vbuf); for(r = &vbuf[0]; r < &vbuf[XCBLKSH]; r++0666); if(fo < 0) { printf("can not open %s\n", ofile); exit(); } if(!cflg) return; p = ofile; while(*p++) ; p[-2]++; } equal(a, b) char *a, *b; { while(*a++ == *b) if(*b++ == 0) return(1); return(0); } struct { char byte[4]; }; swab(pair) { return ((pair.byte[3]<<8) | pair.byte[2]); } dirfix(dir) register struct dir { short dinode; char dname[14]; } *dir; { register struct dir *dp; for (dp = dir; dp < &dir[32]; dp++) dp->dinode = swab(dp->dinode); } nt *prdptr[]; /* pointers to descriptions of productions */ extern int prdlim; /* the number of productions allowed */ extern int levprd[] ; /* contains production levels to break conflicts */ /* last two bits code associativity: 0 = no definition 1 = left associative 2 = binary 3 = right associative bit 04 is 1 if the production has an action the high 13 bits have the production level */ extern int nterms ; /* number of terminals */ extern int nerrors; /* numbertruct {int **ppi;} ; extern int ntlim ; /* maximum number of nonterminals */ extern int tlim ; /* maximum number of terminals */ extern int lineno; /* current line number */ extern int peekc; /* look-ahead character */ extern int tstates[]; extern int ntstates[]; extern int mstates[]; extern struct looksets clset; extern struct looksets lkst[]; extern int nlset; /* next lookahead set index */ extern int lsetsz; /* number of lookahead sets */ extern struct wset { int *pitem, flag, ws[ _tbitset ]; } wsets[uf[XCBLKSH]; short vbuf[XCBLKSH]; char *date[2]; char *ddate[2]; int fo -1; int pher; int dflg; int iflg; int cflg; int aflg; char *tsize 19000; char *taddr; main(argc, argv) char **argv; { char *key; int s, i, nfil, nblk, f; register *tap; register struct iinode *ip; int ino; int isize; ofile = "/dev/mt0"; time(date); if(argc == 1) { argv = dargv; for(argc = 1; dargv[argc]; argc++); } argc--; argv++; key = *argv; while(*key) switch(*key++) { default: printf("bad character in key\neof (struct inode)/sizeof (struct iinode); *tap++ = swab(sblock.s_fsize); *tap++ = date[0]; *tap++ = date[1]; *tap++ = ddate[0]; *tap++ = ddate[1]; *tap++ = tsize; swrite(buf); i = size(0, isize*(512*4/sizeof (struct iinode))); /***/ tap = talist; while(i--) { bwrite(tap); tap =+ XCBLKINT; } tap = talist; for(i=0; i= 0) bwrite(dbuf); pher++; } bread(bno# /* MANIFEST CONSTANT DEFINITIONS */ # define NTBASE 010000 /* internal codes for error and accept actions */ # define ERRCODE 8190 # define ACCEPTCODE 8191 # define errfileno 1 /* file number for erros and reduction message */ # define _tbitset 6 /* 16*_tbitset - 1 >= _nterms */ extern int tbitset; /* number of wds of lookahead vector */ extern int nolook; /* flag to turn off lookahed computations */ struct looksets { int lset[ _tbitset ]; } ; struct item { int *pitem; struct looksets *lo of errors */ extern int fatfl; /* if on, error is fatal */ /* the ascii representations of the terminals */ extern int extval; /* start of output values */ extern struct sxxx1 {char *name; int value;} trmset[]; extern char cnames[]; extern int cnamsz; extern char *cnamp; extern int maxtmp ; /* the size of the temp arrays */ /* temporary vectors, indexable by states, terms, or nterms */ extern int temp1[]; extern int temp2[]; extern int trmlev[]; /* vector with the precedence of the terminals */ /* '-"(.#/"); exit(); case '-': continue; case 'c': /* increment file name */ cflg++; continue; case 'f': /* file name from arg list */ argc--; argv++; ofile = *argv; continue; case 's': /* tape size */ tsize = number(argv[1]) * 9; argv++; argc--; continue; case 'b': /* tape size */ tsize = number(argv[1]); argv++; argc--; continue; case '0': /* dump all */ ddate[0] = ddate[1] = 0; continue; } if(argc <= 1) { printf("no file system specified\n"); exit(); } prinher); exit(); } dump(ip, sz) register struct iinode *ip; { register short *p, *q, *r; register struct inode *np; register int *t; int dirflag; np = dbuf; clrbuf(np); np->i_mode = swab(ip->ii_mode); np->i_nlink = ip->ii_nlink; np->i_uid = ip->ii_uid; np->i_gid = ip->ii_gid; np->i_size0 = ip->ii_size0; np->i_size1 = swab(ip->ii_size1); p = &ip->ii_addr[0]; t = &np->i_addr[0]; while (p < &ip->ii_addr[8]) *t++ = swab(*p++); np->i_atime[1] = (swab(ip->ii_atime[0])<<16) | swab(ip->ii_atime[1], b) { seek(fi, bno, 3); if(read(fi, b, 512) != 512) { printf("read error %l\n", bno); } } clrbuf(b) int *b; { register i, *p; p = b; i = XCBLKINT; while(i--) *p++ = 0; } swrite(b) int *b; { register i, s, *p; i = XCBLKINT-2; s = taddr; p = b; while(i--) s =+ *p++; *p++ = taddr; *p = 031415 - s; bwrite(b); } bwrite(b) { if(taddr == 0) { if(fo != -1) { printf("change tapes\n"); close(fo); rdline(); } otape(); } wloop: if(write(fo, b, 512) != 512) { printf("writok; } ; /* output actions */ # define ERRACT 0 # define TESTACT 4096 # define SHIFTACT 8192 # define REDUCACT 12288 # define ACCEPTACT 16384 # define _REGISTER register extern int nstate ; /* number of states */ extern struct item *pstate[]; /* pointers to the descriptions of the states */ extern int apstate[]; /* index to actions in amem by state */ extern int actsiz; /* size of the action table array */ extern int tystate[]; /* contains type information about the states */ /* 0 = simple state,The levels are the same as for levprd, but bit 04 is always 0 */ /* the ascii representations of the nonterminals */ extern struct sxxx2 { char *name; } nontrst[]; extern int indgo[]; /* index to the stored goto table */ extern int ***pres; /* vector of pointers to the productions yielding each nonterminal */ extern struct looksets **pfirst; /* vector of pointers to first sets for each nonterminal */ extern int *pempty ; /* table of nonterminals nontrivially deriving e */ extern int nnonter ; /* the numb]; extern int cwset; extern int wssize; extern int numbval; /* the value of an input number */ extern int rflag; /* ratfor flag */ extern int sflag; /* suppress crap output flag */ extern int oflag; /* optimization flag */ extern int ndefout; /* number of defined symbols output */ extern int machine; # define UNIX 1 # define GCOS 2 # define IBM 3 # include "dextern" struct looksets *flset(); /***/ cpres(){ /* conpute an array with the beginnings of productions yielding given nonterminals The array pres points to these lists */ int i,j,c; pres = yalloc(nnonter+1); for(i=0;i<=nnonter;i++){ c = i+NTBASE; pres[i] = mem; fatfl = 0; /* make undefined symbols nonfatal */ for(j=0;jpitem > k->pitem ){ s = k->pitem; k->pitem = l->pitem; l->pitem = s; s = k->look; k->look = l->look; l->look = s; } } size1 = p2 - p1; /* size of state */ for( i= (c>=NTBASE)?ntstates[c-NTBASE]:tstates[c]; i != 0; i = mstates[i] ) { /* get ith state */ q1 = pstate[i]; q2 = pstate[i+1]; size2 = q2 - q1; if (size1 != size2) continue; k=p1; for(l=q1;lpitem != k->pitem ) break; ++k; } if (l != q2) continue; /* found it */ ps06<B17=C8>D39?E4:@F1[c] = state(c); else temp1[c-NTBASE+nterms] = state(c); } if( gsdebug ){ settty(); printf( "%d: ", i ); for( j=1; j<=nterms; ++j ){ if( temp1[j] != 0 ) printf( "%s %d, ", symnam(j), temp1[j]); } for( j=1; j<=nnonter; ++j ){ if( temp1[j+nterms] ) printf( "%s %d, ", nontrst[j].name, temp1[j+nterms] ); } printf("\n"); } apstate[i] = apack( &temp1[0], nterms ); indgo[i] = apack( &temp1[nterms+1], nnonter-1 ) - 1; go if( !pempty[ch-NTBASE] ) break; } if( ch<=0 ) setunion( clset.lset, clset.lset, wsets[k].ws ); } } /* now loop over productions derived from c */ c =- NTBASE; /* c is now nonterminal number */ t = pres[c+1]; for( s=pres[c]; s0 && c 0 ; ++p ) { if( ch < NTBASE ) { wsets[i].ws[ch>>4] =| (1 << (ch&017) ); break; } tate[nstate+1] = pstate[nstate]; /* delete last state */ /* fix up lookaheads */ k=p1; for( l=q1; llook->lset, k->look->lset ) ) { tystate[i] = 1; /* register the new set */ l->look = flset( &clset ); } ++k; } return (i); } /* state is new */ pstate[nstate+2] = p2; if(nstate+1 >= stsize) error("too many states"); if( c >= NTBASE ){ mstates[ nstate ] = ntstates[ c-NTBASE ]; ntstates[ c-NTBASE ] = nstate; } else { mstates[inals marked with pempty = 1 */ /* loop as long as we keep finding nontrivial empty nonterminals */ again: for( i=1; i=NTBASE && pempty[*p-NTBASE]!=0 ; ++p ) ; if( *p < 0 ){ /* we have a nontrivially empty nonterminal */ pempty[*prdptr[i]-NTBASE] = 1; goto again; /* got one ... try for another */ } } } } int gsdebug 0; stagen(){ /* generate the stto more; /* we have done one goto; do some more */ } /* no more to do... stop */ } int cldebug 0; /* debugging flag for closure */ closure(i){ /* generate the closure of state i */ int c, ch, work; _REGISTER j, k; int *pi; int **s, **t; struct item *q; _REGISTER struct item *p; ++zzclose; /* first, copy kernel of state i to wsets */ cwset = 0; q = pstate[i+1]; for( p=pstate[i]; ppitem; wsets[cwset].flag = 1; /* this item must gnexts; if( setunion( wsets[k].ws, wsets[k].ws, clset.lset ) ) wsets[k].flag = work = 1; goto nexts; } } /* not there; make a new entry */ if( cwset+1 >= wssize ) error( "working set overflow" ); wsets[cwset].pitem = *s; wsets[cwset].flag = 1; if( nolook ){ cwset++; goto nexts; } work = 1; for( k=0; k>4])&(1<<(k&017))) != 0 ) { if( temp1[k] == 0 ) temp1[k] = c; else if( temp1[k]<0 ){ /* reduce/reduce conflict */ settty(); printf("\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s", i, -temp1[k], lastr else if( !pempty[ch-NTBASE] ) break; } } } /* now, reflect transitivity */ changes = 1; while( changes ){ changes = 0; for( i=0; i<=nnonter; ++i ){ t = pres[i+1]; for( s=pres[i]; s= 0; ++p ) { changes =| setunion( wsets[i].ws, wsets[i].ws, wsets[ch].ws ); if( !pempty[ch] ) break; } } } } for( i=0; i<=nnonter; i++ ) pfirst[i] = flset( wsets[i].ws ); i nstate ] = tstates[ c ]; tstates[ c ] = nstate; } tystate[nstate]=1; return(nstate++); } int pidebug 0; /* debugging flag for putitem */ putitem ( ptr, lptr ) int *ptr; struct looksets *lptr;{ int *jip, k; struct item *i, *j; if( pidebug ) { settty(); printf("putitem(%s), state %d\n", writem(&ptr), nstate ); } /* see if it's there */ j = pstate[nstate+1]; for( i=pstate[nstate]; ipitem == ptr) { error("yacc error--duplicate item"); ates */ int i, j, k, c; /* initialize */ nstate = 0; pstate[0] = pstate[1] = mem; aryfil( clset.lset, tbitset, 0 ); putitem( prdptr[0]+1, &clset ); tystate[0] = 1; nstate = 1; pstate[2] = pstate[1]; memact = 0; aryfil( amem, actsiz, 0 ); /* now, the main state generation loop */ more: for( i=0; ilook->lset[k]; ++cwset; } /* now, go through the loop, closing each item */ work = 1; while( work ){ work = 0; for( j=0; j zzcwset ) zzcwset = cwset; if( !cldebug ) return; settty(); printf("\nState %d, nolook = %d\n", i, nolook ); for( j=0; j lastred ) temp1[k] = -lastred; ++zzrrconf; settab(); } else { /* potential shift/reduce conflict */ switch( precftn( lastred, k ) ) { case 0: /* precedence does not apply */ settty(); printf("\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", i, temp1[k], lastred, symnam(k) ); ++zzsrconf; settab(); f( !indebug ) return; settty(); for( i=0; i<=nnonter; i++ ){ printf( "\n%s: ", nontrst[i].name ); prlook( pfirst[i] ); printf( " %d\n", pempty[i] ); } } state(c){ /* sorts last state,and sees if it equals earlier ones. returns state number */ int s,size1,size2; _REGISTER i; struct item *p1, *p2, *k, *l, *q1, *q2; p1 = pstate[nstate]; p2 = pstate[nstate+1]; if(p1==p2) return(0); /* null state */ /* sort the items */ for(k=p2-1;k>p1;k--) { /* make k the biggest */ for(l=k-1;l> } /* not there */ j->pitem = ptr; j->look = flset( lptr ); pstate[nstate+1] = ++j; jip = j; if(jip-mem0 >= memsiz) error("out of state space"); } cempty(){ /* mark nonterminals which derive the empty string */ int i, *p; /* set pempty to 0 */ pempty = yalloc( nnonter ); aryfil( pempty, nnonter+1, 0 ); for( i=1; i0 ){ if( ch < NTBASE ){ /* terminal symbol */ clset.lset[ch>>4] =| (1<<(ch&017)); break; } /* nonterminal symbol */ setunion( clset.lset, clset.lset, pfirst[ch-NTBASE] ); pointed to by p is known */ /* return pointer to a perminent location for the set */ int j, *w; _REGISTER *u, *v, i; for( i=0; ilset; v = lkst[i].lset; w = & v[tbitset]; while( v= lsetsz )error("too many lookahead sets"); for( j=0; jlset[j]; } return( & lkst[nlset++]); } break; case 1: /* reduce */ temp1[k] = -lastred; break; case 2: /* error, binary operator */ temp1[k] = ERRCODE; break; case 3: /* shift ... leave the entry alone */ break; } } } } } } wract(i); } settab(); arrdone(); /* now, output the pointers to the action array */ /* also output the info about reductions */ prred(); } prred(){ /* print the information about the actions and the reductions */ int index, i; arrset("yypact"); index = 1; /* position in the output table */ for( i=0; i0 ){ /* the state is real */ temp1[i] = index; arrval( index ); index =+ tystate[i]; } else { arrval( temp1[-tystate[i]] ); } } arrdone(); arrset("yyr1"); for( i=1; ipitem) ) < NTBASE ) goto standard; if( p0 == 0 ) p0 = p1; else if( p0 != p1 ) goto standard; } /* now, all items have dots before p0 */ if( cdebug ){ settty(); printf("state %d, pre-nonterminal %s\n",i,nontrst[p0-NTBASE].name); } for( j=0; j j ){ / temp2[i] = offset; best = -1; times = 0; for( j=0; j<=nstate; ++j ){ /* is j the most frequent */ if( tystate[j] == 0 ) continue; if( tystate[j] == best ) continue; /* is tystate[j] the most frequent */ count = 0; cbest = tystate[j]; for( k=j; k<=nstate; ++k ) if( tystate[k]==cbest ) ++count; if( count > times ){ best = cbest; times = count; } } /* best is now the default entry */ zzgobest =+ (times-1)*2; p->pitem) >= NTBASE ){ if( temp1[cc =- NTBASE] ){ /* goto on c is possible */ tystate[i] = amem[indgo[i]+c]; break; } } } if( tystate[i] ) printf("\t%d\t%d\n", i, tystate[i]); } } precftn(r,t){ /* decide a shift/reduce conflict by precedence. Returns 0 if action is 'do nothing',1 if action is reduce, 2 if the action is 'error,binary operator' and 3 if the action is 'reduce'. */ int lp,lt; lp = levprd[r]; lt = trmlev[t]; if ((lt==0)cdebug )printf("states %d and %d have equal positions\n",i,j); q1 = pstate[j+1]; for( q0=pstate[j]; q0pitem) != p0 ) goto nextj; } /* we have a match with state j ! */ tystate[i] = -j; zzacsave =+ tystate[j]; zznsave++; wrstate(i); return; nextj: ; } standard: tystate[i] = 2; wrstate(i); size = 0; for( p0=1; p0<=nterms; ++p0 ) if( (p1=temp1[p0])!=0 ) { arrval( TESTACT+trmse/* fake portable I/O routines, for those sites so backward as to not have the port. library */ int cin, cout; extern int fin, fout; copen( s, c ) char *s; { int f; if( c == 'r' ){ fin = f = open( s, 0 ); } else if( c == 'a' ){ f = open( s, 1 ); seek( f, 0, 2 ); } else { /* c == w */ f = creat( s, 0666 ); } return( f ); } cflush(x){ /* fake! sets file to x */ flush(); fout = x; } system(){ error( "The function \"system\" is called" ); } ccld read productions */ tbitset = (nterms+16)/16; cpres(); /* make table of which productions yield a given nonterminal */ cempty(); /* make a table of which nonterminals can match the empty string */ cpfir(); /* make a table of e free first lists */ stagen(); /* generate the states */ output(); /* write the states and the tables */ go2out(); summary(); windup(); } whereami(){ /* sets the variable machine to UNIX, GCOS, or IBM */ int i; /***/ machine = UNIX; /***/ return; i = 1; * no actions */ return(0); } j =- off; for( k=0; k= actsiz ) error("action table overflow"); if( k+l >= memact ) memact = k+l; amem[k+l] = p[off+l]; settab(); for( j=0; j<=nstate; ++j ){ if( tystate[j] != 0 && tystate[j]!=best ){ arrval( j ); arrval( tystate[j] ); offset =+ 2; zzgoent =+ 2; } } /* now, the default */ zzgoent =+ 2; arrval( -1 ); arrval( best ); offset =+ 2; } arrdone(); arrset("yypgo"); for( i=1; i<=nnonter; ++i ) arrval( temp2[i] ); arrdone(); } int g2debug 0; go2gen(c){ /* output the gotos for nonterminal c */ int i, work, cc; struc||((lp&03)==0))return(0); if((lt>>3) == (lp>>3)){ return(lt&03); } if((lt>>3) > (lp>>3)) return(3); return(1); } int cdebug 0; /* debug for common states */ wract(i){ /* output state i */ /* temp1 has the actions, lastred the default */ int p, p0, p1, size; int ntimes, tred, count, j; struct item *q0, *q1; /* find the best choice for lastred */ lastred = 0; ntimes = 0; for( j=1; j<=nterms; ++j ){ if( temp1[j] >= 0 ) continue; if( temp1[j]+lastred == 0 ) continue; /* cot[p0].value ); if( p1 < 0 ) arrval( REDUCACT - p1 ); else if( p1 == ACCEPTCODE ) arrval( ACCEPTACT ); else if( p1 == ERRCODE ) arrval( ERRACT ); else arrval( SHIFTACT + p1 ); size =+ 2; } if( lastred ) arrval( REDUCACT + lastred ); else arrval( ERRACT ); tystate[i] = size+1; /* store entry size in tystate */ zzacent =+ (size+1); return; } wrstate(i){ /* writes state i */ int j0,j1,s; struct item *pp, *qq; settty(); printf("\nsose(i){ close(i); } cexit(i){ flush(); exit(i); } i = i << 30; if( i == 0 ) { machine = UNIX; return; } i = i << 4; if( i == 0 ){ machine = IBM; return; } machine = GCOS; } windup(){ /* no errors, do the optimization if appropriate */ char *cp; int i; cflush(1); if( !oflag ) cexit(0); for( i=3; i<10; ++i ) cclose(i); switch( machine ){ case GCOS: if( rflag ){ if( foutput<0 ) system( "./yopt -r" ); else system( "./yopt -rv" ); } else { if( foutput<0 ) system( "./yopt" ); } } if( pkdebug ){ for( k=0; k= 0 ){ /* cc is a nonterminal */ if( temp1[cc] != 0 ){ /* cc has a goto on c */ cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */ if( temp1[cc] == 0 ){ work = 1; temp1[cc] = 1; } } unt the number of appearances of temp1[j] */ count = 0; tred = -temp1[j]; for( p=1; p<=nterms; ++p ){ if( temp1[p]+tred == 0 ) ++count; } if( count >ntimes ){ lastred = tred; ntimes = count; } } /* clear out entries in temp1 which equal lastred */ for( p=1; p<= nterms; ++p ) if( temp1[p]+lastred == 0 )temp1[p]=0; /* write out the state */ /* first, check for equality with another state */ /* see if there is a nonterminal with all dots tate %d\n",i); qq = pstate[i+1]; for( pp=pstate[i]; pp0 ){ /* shift, error, or accept */ if( j1 == ACCEPTCODE ) printf( "accept" ); else if( j1 == ERRCODE ) print# include "dextern" /* * * * * y a c c * * * * */ /* features to be fixed up ... *** Print estimate of total space needed for parser *** Either list inputs on y.output, or list empty prdn's in states *** Mention nonterms not used (or, rules. not reduced) as nonfatal error *** Output states where conflicts were found by default on y.output *** Engage in newspeak: production=>grammar rules, term=>token, etc. *** handle # define, #ifdef, etc., in yacc actions, %{ %} else system( "./yopt -v" ); } cexit(0); /* terminate */ case UNIX: cp = "/usr/yacc/yopti"; if( rflag ) execl( cp, cp, (foutput<0)?"-r":"-rv", 0 ); else if( foutput<0 ) execl( cp, cp, 0 ); else execl( cp, cp, "-v", 0 ); error( "optimization execl call fails" ); case IBM: if( rflag ){ if( foutput<0 ) system( "MH2019.yaccopt -r" ); else system( "MH2019.yaccopt -rv" ); } else { if( foutput<0 ) system( "MH2019.yaccopt" ); else system( "MH2019.yaccopt -v" ); } cexit(0); } } settty() /* sets the output file to y.output */ { cflush( foutput ); /* a bit of a cheat */ cout = foutput; } settab(){ /* sets the output file to y.tab.c */ cflush( ftable ); cout = ftable; } char *chcopy( p, q ) char *p, *q; { /* copies string q into p, returning next free char ptr */ while( *p = *q++ ) ++p; return( p ); } char *writem(pp) struct item *pp; { /* creates output string for item pointed to by pp */ int i,*p; statd terminals, %d/%d nonterminals\n", nterms, tlim, nnonter, ntlim ); printf("%d/%d grammar rules, %d/%d states\n", nprod, prdlim, nstate, stsize ); printf("%d shift/reduce, %d reduce/reduce conflicts reported\n", zzsrconf, zzrrconf ); pn = pstate[nstate+1]; printf("%d/%d working sets used\n", zzcwset, wssize ); printf("memory: states,etc. %d/%d, parser %d/%d\n", pn-mem0, memsiz, memact, actsiz ); printf("%d/%d distinct lookahead sets\n", nlset, lsetsz ); printf("%d extra closures\n ) int *a, *b, *c; { /* set a to the union of b and c */ /* a may equal b */ /* return 1 if c is not a subset of b, 0 otherwise */ _REGISTER int i, x, sub; sub = 0; for( i=0; ilset; if( pp == 0 ) printf("\tNULL"); else { printf(" { " ); for( j=1; j<=nterms; ++j ){ if( (pp[j>>4]>>(j&017) )&01 != 0 ) printf( "%s ", symnam(j) ); } printfinput" ); settab(); printf("#\n"); ctokn = "$end"; defin(0); /* eof */ extval = 0400; /* beginning of assigned values */ ctokn = "error"; defin(0); ctokn = "$accept"; defin(1); mem=mem0; cnamp = cnames; lev=0; i=0; while( t = gettok() ){ switch( t ){ case IDENTIFIER: j = chfind(0); trmlev[j] = lev; continue; case ',': case ';': continue; case TERM: lev=0; continue; case LEFT: lev=(++i<<3)|01; continue; case BINARY: lev=(++i<<3)|02; continue; case RIGHT: l"token illegal on lhs of grammar rule" ); i=1; ++mem; continue; case IDENTIFIER: *mem=chfind(1); if(*mem < NTBASE)levprd[nprod]=trmlev[*mem]; mem++; if(i==0) error("missing :"); continue; case '=': levprd[nprod] =| 04; if( i==0 ) error("semicolon preceeds action"); printf( rflag?"\n%d ":"\ncase %d:", nprod ); cpyact(); printf( rflag ? " return" : " break;" ); case '|': case ';': if(i){ *mem++ = -nprod; prdptr[++nprod] = mem; levprd[nprod]=0; i=0;else { /* ------- The next line is an INGRES customization ------- */ printf( "\n}\nreturn(0);\n}\n" ); printf( "int yyerrval %d;\n", trmset[2].value ); } } defin(t) { /* define ctokn to be a terminal if t=0 or a nonterminal if t=1 */ char *cp,*p; int c; if (t) { if( ++nnonter >= ntlim ) error("too many nonterminals, limit %d",ntlim); nontrst[nnonter].name = ctokn; return( NTBASE + nnonter ); } else { if( ++nterms >= tlim ) error("too many tic char sarr[100]; char *q; for( p=pp->pitem; *p>0 ; ++p ) ; p = prdptr[-*p]; q = chcopy( sarr, nontrst[*p-NTBASE].name ); q = chcopy( q, " : " ); for(;;){ *q++ = ++p==(pp->pitem) ? '_' : ' '; if((i = *p) <= 0) break; q = chcopy( q, symnam(i) ); } *q = '\0' ; return( sarr ); } char *symnam(i){ /* return a pointer to the name of symbol i */ char *cp; cp = (i>=NTBASE) ? nontrst[i-NTBASE].name : trmset[i].name ; if( *cp == ' ' ) ++cp; return( cp ); } summary(){ /* output the summary", zzclose - 2*nstate ); printf("%d action entries\n", zzacent ); printf("%d action entries saved through merging %d states\n",zzacsave,zznsave); printf("%d goto entries\n", zzgoent ); printf("%d entries saved by goto default\n", zzgobest ); if( zzsrconf!=0 || zzrrconf!=0 ){ cflush( errfileno ); cout = errfileno; printf("\nconflicts: "); if( zzsrconf )printf( "%d shift/reduce" , zzsrconf ); if( zzsrconf && zzrrconf )printf( ", " ); if( zzrrconf )printf( "%d reduce/reduce" ,( "}" ); } } ev=(++i<<3)|03; continue; case MARK: defout(); if( rflag ){ /* RATFOR */ printf( "define yyerrok yyerrf = 0\n" ); printf( "define yyclearin yychar = -1\n" ); printf( "subroutine yyactr(yyprdn)\n"); printf( "common/yycomn/yylval,yyval,yypv,yyvalv(150)\n" ); printf( "common/yylcom/yychar,yyerrf,yydebu\n" ); printf( "integer yychar, yyerrf, yydebu\n" ); printf( "integer yyprdn,yyval,yylval,yypv,yyvalv\n" ); } else { printf( "#define yyclea} if (t=='|'){i=1;*mem++ = *prdptr[nprod-1];} continue; case 0: /* End Of File */ case MARK: if( i != 0 ) error( "rule not terminated before %%%% or EOF" ); settab(); finact(); /* copy the programs which follow the rules */ if( t == MARK ){ while (c=getchar()) putchar(c); } return; case PREC: if( i==0 ) error( "%%prec must appear inside rule" ); if( gettok()!=IDENTIFIER)error("illegal %%prec syntax" ); j=chfind(2); if(j>=NTBASE)error("nonterminal %s illegal after %%erminals, limit %d",tlim ); trmset[nterms].name = ctokn; if( ctokn[0]==' ' && ctokn[2]=='\0' ) /* single character literal */ trmset[nterms].value = ctokn[1]; else if ( ctokn[0]==' ' && ctokn[1]=='\\' ) { /* escape sequence */ if( ctokn[3] == '\0' ){ /* single character escape sequence */ switch ( ctokn[2] ){ /* character which is escaped */ case 'n': trmset[nterms].value = '\n'; break; case 'r': trmset[nterms].value = '\r'; break; case 'b': trmset[nterms].value = '\b'; brea on the tty */ int i, s, *pn; if (!rflag && !sflag) { settab(); printf("\nint nterms %d;",nterms); printf("\nint nnonter %d;", nnonter); printf("\nint nstate %d;", nstate); printf("\nchar *yysterm[] {"); for (i=1;i<=nterms;i++) if( trmset[i].value >= 0400 ) printf("\n\"%s\",",symnam(i)); printf( "\n0 };\n" ); printf("\nchar *yysnter[] {"); for (i=0;i= 2 && argv[1][0] == '-' ) { while( *++(argv[1]) ){ switch( *argv[1] ){ case 'v': case 'V': foutput = copen("y.output", 'w' ); if( foutprin yychar = -1\n" ); printf( "#define yyerrok yyerrflag = 0\n" ); printf( "extern int yychar, yyerrflag;\n" ); printf("\nint yyval 0;\nint *yypv;\nint yylval 0;"); printf("\nyyactr(__np__){\n"); } break; case LCURLY: defout(); cpycode(); continue; case NUMBER: trmset[j].value = numbval; if( j < ndefout && j>2 ) error("please define type # of %s earlier", trmset[j].name ); continue; default: error("bad precedence syntax, input %d", t );ntcioudjvekqwx~yzk; case 't': trmset[nterms].value = '\t'; break; case '\'': trmset[nterms].value = '\''; break; case '"': trmset[nterms].value = '"'; break; case '\\': trmset[nterms].value = '\\'; break; default: error( "invalid escape" ); } } else if( ctokn[2] <= '7' && ctokn[2]>='0' ){ /* \nnn sequence */ if( ctokn[3]<'0' || ctokn[3] > '7' || ctokn[4]<'0' || ctokn[4]>'7' || ctokn[5] != '\0' ) error("illegal \\nnn construction" ); trmset[nterms].value = 64*(ctokn[2]-'0')+8*(ctokn[3]-'0')+^MSY_`flagmsbh ctokn to v */ char *p; p=ctokn; while( *v++ = *p++ ); } compare(v) char *v; { /* compare ctokn with v */ char *p; for( p=ctokn; ; ++p ){ if( *p != *v++ ) return( 0 ); if( *p == 0 ) return(1); } } int *yalloc(n){ /* allocate n+1 words from vector mem */ int *omem; omem = mem; mem =+ n+1; if(mem-mem0 >= memsiz) error("memory overflow"); return(omem); } aryfil( v, n, c ) int *v,n,c; { /* set elements 0 through n-1 to c */ int i; for( i=0; i 1 ) cin = copen( argv[1], 'r' ); if( cin < 0 ) error( "cannot open } break; } prdptr[0]=mem; /* added production */ *mem++ = NTBASE; *mem++ = NTBASE+1; *mem++ = 1; *mem++ = 0; prdptr[1]=mem; i=0; /* i is 0 when a rule can begin, 1 otherwise */ for(;;) switch( t=gettok() ) { case C_IDENTIFIER: if( mem == prdptr[1] ) { /* first time */ if( rflag ){ printf( "goto 1000\n" ); } else printf("\nswitch(__np__){\n"); } if( i != 0 ) error( "previous rule not terminated" ); *mem = chfind(1); if( *mem < NTBASE )error( prec", nontrst[j-NTBASE].name); levprd[nprod]=trmlev[j]; continue; case LCURLY: if( i!=0 ) error( "%%{ appears within a rule" ); cpycode(); continue; default: error( "syntax error, input %d", t ); } } finact(){ /* finish action routine */ register i; if( rflag ){ printf( "\n1000 goto(" ); for( i=1; i='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' || c=='_' ) ; /* VOID */ else goto nodef; } /* define it */ printf( "%c define %s %d\n", rflag?' ':'#', trmset[i].name, trmset[i].value ); nodef: ; } ndefout = nterms+1; } chstash( c ){ /* put character away into cnames */ if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" ); else *cnamp++ = c; } int gettok() { int j, base; static int peekline; /* number of '\n' seen in lookahead */ auto int c, match, reserve; begin: resehstash( c ); if( peekc>=0 ) { c = peekc; peekc = -1; } else c = getchar(); } } else return(c); peekc=c; } chstash( '\0' ); if( reserve ){ /* find a reserved word */ if( compare("term")) return( TERM ); if( compare("TERM")) return( TERM ); if( compare("token")) return( TERM ); if( compare("TOKEN")) return( TERM ); if( compare("left")) return( LEFT ); if( compare("LEFT")) return( LEFT ); if( compare("nonassoc")) return( BINARY ); if( compare("NONASSOC")) return( ){ case ';': if( brac == 0 ){ putchar( c ); return; } goto lcopy; case '{': brac++; goto lcopy; case '$': s = 1; c = getchar(); if( c == '$' ){ printf("yyval"); goto loop; } if( c == '-' ){ s = -s; c = getchar(); } if( c>='0' && c <= '9' ){ j=0; while( c>='0' && c<= '9' ){ j= j*10+c-'0'; c = getchar(); } if( rflag ) printf( "yyvalv(yypv%c%d)", s==1?'+':'-', j ); else printf("yypv[%d]", s*j ); goto swt; } putchar( '$' ); if( smain( argc, argv ) int argc; char *argv[]; { yyinit( argc, argv ); if( yyparse() ) return; yyaccpt(); } yyval=yylval; yychar= -1; if( yyerrflag ) --yyerrflag; goto stack; /* stack new state */ case 3: /* reduce */ if( yydebug ) printf("reduce %d\n",n); ps =- yyr2[n]; yypv =- yyr2[n]; yyval=yypv[1]; yyactr(n); /* consult goto table to find next state */ for( p= &yygo[yypgo[yyr1[n]]]; *p != *ps && *p >= 0 ; p =+ 2 ) ; yystate = p[1]; goto stack; /* stack new state and value */ case 4: /* accept */ return(0); caseyyaccpt(){} rve = 0; if( peekc>=0 ) { c = peekc; lineno =+ peekline; peekc = -1; peekline = 0; } else c = getchar(); while( c==' ' || c=='\n' || c=='\t' ){ if( c == '\n' ) ++lineno; c=getchar(); } if (c=='/') {if (getchar()!='*')error("illegal /"); c=getchar(); while(c) { if( c == '\n' ) ++lineno; if (c=='*') {if((c=getchar())=='/')break;} else c=getchar();} if (!c) return(0); goto begin;} j=0; switch(c){ case '"': case '\'': m BINARY ); if( compare("binary")) return( BINARY ); if( compare("BINARY")) return( BINARY ); if( compare("right")) return( RIGHT ); if( compare("RIGHT")) return( RIGHT ); if( compare("prec")) return( PREC ); if( compare("PREC")) return( PREC ); error("invalid escape, or illegal reserved word: %s", ctokn ); } /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ look: while( peekc==' ' || peekc=='\t' || peekc == '\n' ) { if( peekc == '\n' ) ++peekline; peekc = getchar(); } <0 ) putchar('-'); goto swt; case '}': brac--; if( brac == 0 ){ putchar( c ); return; } goto lcopy; case '/': /* look for comments */ putchar( c ); c = getchar(); if( c != '*' ) goto swt; /* it really is a comment */ putchar( c ); while( c=getchar() ){ if( c=='*' ){ putchar( c ); if( (c=getchar()) == '/' ) goto lcopy; } putchar( c ); } error( "EOF inside comment" ); case '\'': /* character constant */ match = '\''; goto string; case '"': /* chara# define _maxdepth 150 /* parser for yacc output */ extern int yyval; /* defined in the table file */ extern int yylval; /* defined in the table file */ extern int *yypv; /* defined in the table file */ int yydebug 0; /* 1 for debugging */ int yyv[_maxdepth]; /* where Kthe values are stored */ int yystate 0; /* current parser state */ int yychar -1; /* current input token number */ int yyline 0; /* line number for error message */ int yynerrs 0; /* number of errors */ int yyerrflag 0; /* error recove 0: /* Ierror ... attempt to resume parsing */ switch( yyerrflag ){ case 0: /* brand new error */ ++yynerrs; yyerror( "syntax error" ); case 1: case 2: /* incompletely recovered error ... try again */ yyerrflag = 3; /* find a state where "error" is a legal shift action */ while ( ps >= s ) { for( p= &yyact[ yypact[*ps+1] ] ; (*p>>12) == 1 ; p =+ 2 ) /* search ps actions */ if( *p == 4352 ) goto found; extern int yyline; /* input line number */ yyerror(s) char *s; { extern int yychar; extern char *yysterm[]; printf("\n%s", s ); if( yyline ) printf(", line %d,", yyline ); printf(" on input: "); if( yychar >= 0400 ) printf("%s\n", yysterm[yychar-0400] ); else switch ( yychar ) { case '\t': printf( "\\t\n" ); return; case '\n': printf( "\\n\n" ); return; case '\0': printf( "$end\n" ); return; default: printf( "%c\n" , yychar ); return; } } atch = c; ctokn = cnamp; chstash( ' ' ); while(1){ c = getchar(); if( c == '\n' || c == '\0' ) error("illegal or missing ' or \""); if( c == '\\' ){ c = getchar(); chstash( '\\' ); } else if( c == match ) break; chstash( c ); } break; case '%': case '\\': switch(c=getchar()) {case '0': return(TERM); case '<': return(LEFT); case '2': return(BINARY); case '>': return(RIGHT); case '%': case '\\': return(MARK); case '=': return(PREC); cas if( peekc != ':' ) return( IDENTIFIER ); peekc = -1; lineno =+ peekline; peekline = 0; return( C_IDENTIFIER ); } chfind(t) { int i,j; if (ctokn[0]==' ')t=0; for(i=1;i<=nterms;i++) if(compare(trmset[i].name)){ cnamp = ctokn; return( i ); } for(i=1;i<=nnonter;i++) if(compare(nontrst[i].name)) { cnamp = ctokn; return( i+NTBASE ); } /* cannot find name */ if( t>1 && ctokn[0] != ' ' ) error( "%s should have been defined earlier", ctokn ); return( defin( t ) ); } cpycode(){cter string */ match = '"'; string: putchar( c ); while( c=getchar() ){ if( c=='\\' ){ putchar( c ); c=getchar(); } else if( c==match ) goto lcopy; putchar( c ); } error( "EOF in string or character constant" ); case '\0': error("action does not terminate"); case '\n': ++lineno; goto lcopy; } lcopy: putchar( c ); goto loop; } ry flag */ yyparse() { extern int yygo[], yypgo[], yyr1[], yyr2[], yyact[], yypact[]; auto int *ps, s[_maxdepth]; auto int ac, n, *p; yystate = 0; yychar = -1; yynerrs = 0; yyerrflag = 0; ps= &s[0]-1; yypv= &yyv[0]-1; stack: /* put a state and value onto the stack */ if( yydebug ) printf( "state %d, value %d, char %d\n",yystate,yyval,yychar ); *++ps = yystate; *++yypv = yyval; newstate: /* set ap to point to the parsing actions for the new state */ p /* the current ps has no shift onn "error", pop stack */ if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *ps, ps[-1] ); --ps; --yypv; } /* there is no state on the stack with an error shift ... abort */ abort: return(1); found: /* we have a state with a shiI@ft on "error", resume parsing */ yystate = p[1] & 07777; goto stack; case 3: /* no shift yet; clobber input char */ yyinit(){} e '{': return(LCURLY); default: reserve = 1; } default: if( c >= '0' && c <= '9' ){ /* number */ numbval = c-'0' ; base = (c=='0') ? 8 : 10 ; for( c=getchar(); c>='0' && c<='9'; c=getchar() ){ numbval = numbval*base + c - '0'; } peekc = c; return(NUMBER); } else if( (c>='a'&&c<='z')||(c>='A'&&c<='Z')||c=='_'||c=='.'||c=='$'){ ctokn = cnamp; while( (c>='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') || c=='_' || c=='.' || c=='$' ) { c /* copies code between \{ and \} */ int c; c = getchar(); if( c == '\n' ) { c = getchar(); lineno++; } while( c ){ if( c=='\\' ) if( (c=getchar()) == '}' ) return; else putchar('\\'); if( c=='%' ) if( (c=getchar()) == '}' ) return; else putchar('%'); putchar( c ); if( c == '\n' ) ++lineno; c = getchar(); } error("eof before %%}"); } cpyact(){ /* copy C action to the next ; or closing } */ int brac, c, match, *i, j, s; brac = 0; loop: c = getchar(); swt: switch( cYacc command - slightly modified version from Berkeley; compatible with INGRES = &yyact[ yypact[yystate+1] ]; actn: /* get the next action, and perform it */ n = ( ac = *p++ ) & 07777; /* n is the "address" of the action */ switch( ac>>12 ) { /* switch on operation */ case 1: /* skip on test */ if( yydebug && (yychar<0) ){ yychar = yylex(); printf( "character %d read\n", yychar ); } if( n != ( (yychar<0) ? ( yychar=yylex() ) : yychar ) ) ++p; goto actn; /* get next action */ case 2: /* shift */ yystate=n; if( yydebug ) printf( "error recovery discards char %d\n", yychar ); if( yychar == 0 ) goto abort; /* don't discard EOF, quit */ yychar = -1; goto newstate; /* try again in the same state */ } } } # define _actsize 1500 # define _memsize 3500 # define _nstates 400 # define _nterms 95 # define _nprod 250 # define _nnonterm 150 # define _tempsize 400 # define _cnamsz 2000 # define _lsetsize 200 # define _wsetsize 150 # define _tbitset 6 int tbitset; /* size of lookahed sets */ int nolook 0; /* flag to suppress lookahead computations */ struct looksets { int lset[ _tbitset ]; } ; struct item { int *pitem; } ; /* this file contains the definitions for most externally known data */ int nstate 0; /* number of states */ struct item *pstate[_nstates]; /* pointers to the descriptions of the states */ int apstate[_nstates]; /* index to the actions for the states */ int tystate[_nstates]; /* contains type information about the states */ int stsize _nstates; /* maximum number of states, at present */ int memsiz _memsize; /* maximum size for productions and states */ int mem0[_memsize] ; /* production storage */ int *mem mem0; int amem[_actsize]; /* action table storage */ int actsiz _actsize; /* action tablt; /* vector of pointers to first sets for each nonterminal */ int *pempty 0 ; /* table of nonterminals nontrivially deriving e */ int nnonter -1; /* the number of nonterminals */ int lastred 0; /* the number of the last reduction of a state */ int ftable; /* y.tab.c file */ int foutput; /* y.output file */ int arrndx; /* used in the output of arrays on y.tab.c */ int zzcwset 0; int zzpairs 0; int zzgoent 0; int zzgobest 0; int zzacent 0; int zzacsave 0; int zznsave 0; int zzclose 0; int zzsrconf 0; int zecho = yacc command cc -o yacc y?.c echo = yacc library cc -c main.c yy*.c flags */ case 'P': pflag++; cflag++; plist[np++] = argv[i]; break; case 'D': case 'U': case 'I': if (argv[i][2]) plist[np++] = argv[i]; else if (i+1=0) { close(c); tmp0[9]++; } while((creat(tmp0, 0400))<0) tmp0[9]++; } if ((signal(2, 1) & 01) == 0) signal(2, &dexit); (tmp1 = copy(tmp0))[8] = '1'; (tmp2 = copy(tmp0))[8] = '2'; (tmp3 = copy(tmp0))[8] = '3'; /*** if (oflag) (tmp5 = copy(tmp0))[8] = '5'; ***/ if (pflag==0) (tmp4 = copy(tmp0))[8] = '4'; for (i=0; i1) printf("%s:\n", clist[i]); urn(1); } cunlink(f) char *f; { if (f==0) return(0); return(unlink(f)); } h 13 bits have the production level */ int nterms 0; /* number of terminals */ int tlim _nterms ; /* the maximum number of terminals */ /* the ascii representations of the terminals */ int extval 0; /* start of output values */ struct sxxx1 {char *name; int value;} trmset[_nterms]; char cnames[_cnamsz]; int cnamsz _cnamsz; char *cnamp; int maxtmp _tempsize; /* the size of the temp1 array */ int temp1[_tempsize]; /* temporary storage, indexed by terms + nterms or states */ int temp2[_nnonterm]; /* tempm, flag, ws[_tbitset]; } wsets[ _wsetsize ]; int cwset; int wssize _wsetsize; int numbval; /* the value of an input number */ int rflag 0; /* ratfor flag */ int sflag 0; /* suppress crap output flag */ int oflag 0; /* optimization flag */ int ndefout 3; /* number of defined symbols output */ int nerrors 0; /* number of errors */ int fatfl 1; /* if on, error is fatal */ int machine; /* has a number describing the machine */ xo; int dexit(); i = nc = nl = np = f20 = nxo = 0; while(++i < argc) { if(*argv[i] == '-') switch (argv[i][1]) { default: goto passa; case 'S': sflag++; cflag++; break; case 'O': oflag++; break; case 'p': proflag++; pref = "/lib/mcrt0.o"; break; case 'm': mflag++; break; case 'c': cflag++; break; case '2': if(argv[i][2] == '\0') pref = "/lib/crt2.o"; else { pref = "/lib/crt20.o"; if (getsuf(clist[i]) == 's') asm = clist[i]; else { av[0] = "cpp"; for (j=1; j<=np; j++) av[j] = plist[j-1]; av[j++] = clist[i]; if (pflag) tmp4 = setsuf(clist[i], 'i'); av[j++] = tmp4; av[j++] = 0; exfail = callsys(passp, av); if (pflag || exfail) continue; av[0] = "c0"; av[1] = tmp4; av[2] = tmp1; av[3] = tmp2; j = 4; if (proflag) av[j++] = "-p"; if (mflag) av[j++] = "-m"; av[j] = 0; if (callsys(pass0, av)) { cflag++; continue; } av[0] = "c1"; dexit() { if (!pflag) { cunlink(tmp1); cunlink(tmp2); if (sflag==0) cunlink(tmp3); cunlink(tmp4); cunlink(tmp5); cunlink(tmp0); } exit(); } getsuf(as) char as[]; { register int c; register char *s; register int t; s = as; c = 0; while(t = *s++) if (t=='/') c = 0; else c++; s =- 3; if (c<=14 && c>2 && *s++=='.') return(*s); return(0); } setsuf(as, ch) char as[]; { register char *s, *s1; s = s1 = copy(as); while(*s) if (*s++ == '/') s1 = s; s[-1] = ch; retC compiler This is the 'Level 7' compiler as described in _T_h_e_ _C_ _P_r_o_g_r_a_m_m_i_n_g_ _L_a_n_g_u_a_g_e (Kernighan & Ritchie). Output must be processed by the UNIX assembler 'as'. Undefine the preprocessor variable 'unix' to produce a version compatible with the Interdata CAL assembler. The 16-bit version (produced by defining the preprocessor variable HALFW) is only partially implemented -- 'static', 'long' and 'float' don't work. Jobjar: - fix alignment of aggregates orary storage indexed by nonterminals */ int trmlev[_nterms]; /* vector with the precedence of the terminals */ /* The levels are the same as for levprd, but bit 04 is always 0 */ /* the ascii representations of the nonterminals */ struct sxxx2 { char *name; } nontrst[_nnonterm]; int ntlim _nnonterm ; /* limit to the number of nonterminals */ int indgo[_nstates]; /* index to the stored goto table */ int ***pres; /* vector of pointers to the productions yielding each nonterminal */ struct looksets **pfirscp yacc /usr/bin ar r /lib/liby.a main.o yy*.o rm yacc *.o f20 = 1; } break; case 'T': if (argv[i][2]=='p') passp = "/usr/c/cpp"; if (argv[i][2]=='0') pass0 = "/usr/c/c0"; if (argv[i][2]=='1') pass1 = "/usr/c/c1"; if (argv[i][2]=='2') pass2 = "/usr/c/c2"; break; case 'v': vflag++; break; /* change default output file */ case 'o': if (argv[i][2]) ofile = &argv[i][2]; else if (i+1>(currently all structs and unions are on a word boundary) - implement double-precision (currently 'double' is synonymous with 'float') and unsigned short - complete 16-bit version # # include "stdio.h" /* C command */ # define SBSIZE 10000 # define DROP (-2) # define SAME 0 # define MAXINC 10 char sbf[SBSIZE]; # define CHSPACE 1000 char ts[CHSPACE+50]; # define EXPSIZE 500 char *strdex(), *copy(), *calloc(), *token(), *coptok(); char *tsa ts; char *tsp ts; char *fnames[MAXINC]; # define LINELEN 512 FILE *fin; FILE *fout; int instring; char direct[50]; int nd 1; char *dirs[10] {direct, 0}; char nfil[100]; int pflag; int depth; int skipcom; FILE *fins[MAXINC]; int ifno; char *lp; chae '\0': continue; default: error("unknown flag %s", argv[i]); continue; } default: if (fin==stdin) { fin = fopen(argv[i], "r"); if (fin==NULL) { error("No source file %s",argv[i]); exit(8); } fnames[ifno]=argv[i]; strcpy(direct, argv[i]); for(sp=direct; *sp; sp++); while (sp>direct && *sp != '/') sp--; # ifdef unix if (sp==direct) *sp++ = '.'; # endif *sp=0; /* direct now has place where source file is */ rback("If-less else",0); goto out; } else if (np==udfloc) { state=6; } else if (np==ifloc) { /* if (flslvl ==0 && yyparse()) */ error("IF not implemented, true assumed",0); if (1) trulvl++; else flslvl++; return('\n'); } else if (np==lneloc) { if(pflag==0) fprintf(fout, "# "); lp=line; for(; c !='\n' && c != '\0'; c=getch()) if (!pflag) sch(c); sch('\0'); return(c); } else { errback("Unde } if (filok==0) errback("Can't find include file %s", filname); else { if (pflag==0) fprintf(fout, "\n# 1 \"%s\"", filname); lineno[ifno]=1; fnames[ifno] = copy(filname); } return(c); } } sch(sc=c); c = getch(); if (isdigit(sc)) { for (;isalpha(c) || isdigit(c); c=getch()) sch(c); } } sch('\0'); if (state>1) errback("Control syntax",0); return(c); } insym(sp, namep) struct symtab **sp; char *namep; { register struct symtab *np; *fout, "\n# %d \"%s\"\n",lineno[ifno], fnames[ifno]); c = getc1(); if (c=='\n') lineno[ifno]--; } if (c==EOF) return(0); if (c=='\n' ) lineno[ifno]++; return(c); } struct symtab * lookup(namep, enterf) char *namep; { register char *np, *snp; register struct symtab *sp; int i, c, around; np = namep; snp = np+8; around = i = 0; while ( (c = *np++ ) && (np-snp)<0) { i =+ c; } i =% symsiz; sp = &symtab[i]; while (sp->name[0]) { if (sp->name[0] != DROP) { snp = sp->name; r *line; # define NPREDEF 20 char *prespc[NPREDEF]; char **predef prespc; char *punspc[NPREDEF]; char **prund punspc; char **predp; int lineno[MAXINC]; int exfail; struct symtab { char name[8]; char *value; } *symtab, *lookup(); # define symsiz 400 struct symtab *defloc; struct symtab *udfloc; struct symtab *incloc; struct symtab *ifloc; struct symtab *elsloc; struct symtab *eifloc; struct symtab *ifdloc; struct symtab *ifnloc; struct symtab *sysloc; struct symtab *lneloc; struct symtab *prdloc; int trulv } else if (fout==stdout) { fout= fopen(argv[i], "w"); if (fout==NULL) { error("Can't write %s", argv[i]); exit(8); } } else error("extraneous name %s", argv[i]); } } fins[ifno]=fin; exfail = 0; /* after user -I files here are the standard include libraries */ # ifdef unix dirs[nd++] = "/usr/include"; # endif # ifdef gcos dirs[nd++] = "cc"; # endif # ifdef ibm dirs[nd++] = "stdio."; # endif /* dirs[nd++] = "/compool"; */ dirs[nd++, fout); # ifdef tgp if (ifbrk) fprintf(fout,"\n# %d",lineno[ifno]); # endif } putc('\n', fout); } # ifdef tgp checklen(line); # endif for(rlp=line; c = *rlp++;) putc(c,fout); } getline() { register int c, sc, state; struct symtab *np; char *namep, *filname, **dirp; int filok, inctype; lp = line; *lp = '\0'; state = 0; if ((c=getch()) == '#') state = 1; while (c!='\n' && c!='\0') { if (letter(c)) { namep = lp; sch(c); while (letnum(c=getch())) sch(c); sch('\0fined control",0); while (c!='\n' && c!='\0') c = getch(); return(c); } } else if (state==2) { if (flslvl) goto out; np->value = stringbuf; if (c != '\n' && c != 0) { savch(c); while ((c=getch())!='\n' && c!='\0') { if (c== '\\') { c = getch(); if (c=='\n')continue; savch('\\'); } savch(c); } } savch('\0'); return(1); } continue; } else if ((sc=c) == '\'' || sc== '"' || (stasp = np = lookup(namep, 1); np -> value = np -> name; } stsym(namep, valp) char *namep, *valp; { register struct symtab *np; np = lookup(namep, 1); np->value = valp; } error(s, x) char *s; { FILE *efout; efout = fout==stdout ? stderr : stdout; if (fnames[ifno][0]) fprintf(efout,"%s: %d: ", fnames[ifno], lineno[ifno]); fprintf(efout, s, x); putc('\n',efout); exfail++; } errback(s,x) char *s; { lineno[ifno]--; error(s,x); lineno[ifno]++; } sch(c) { register char *rlp; rlp = lp; if (rl np = namep; while (*snp++ == *np) if (*np++ == '\0' || np==namep+8) { if (enterf==DROP) { sp->name[0]= DROP; return(sp); } if (!enterf) subst(namep, sp); return(sp); } } if (++sp >= &symtab[symsiz]) if (around++) { error("too many defines", 0); exit(exfail); } else sp = symtab; } if (enterf>0) { snp = namep; for (np = &sp->name[0]; np < &sp->name[8];) if (*np++ = *snp) snp++; } rel; int flslvl; char *stringbuf; mainpp(argc,argv) char *argv[]; { int i; # ifdef tgp int ifbrk; # endif char ln[LINELEN]; register int c; register char *rlp; char *sp; static struct symtab stab[symsiz]; fin = stdin; fout = stdout; # ifdef unix fnames[ifno=0] = ""; # endif # ifdef gcos fnames[ifno=0] = "s*"; # endif # ifdef ibm fnames[ifno=0] = ""; # endif for(i=1; iprespc) i'); lp--; if (state==6) { lookup(namep, DROP); goto out; } if (state>3 && state <6) { if (flslvl==0 &&(state+!lookup(namep,-1)->name[0])==5) trulvl++; else flslvl++; out: while (c!='\n' && c!= '\0') c = getch(); return(c); } if (state==3) /* include */ if (*namep != '"' && *namep != '<') { error("Bad include syntax", 0); state=1; } if (state!=2 || flslvl==0) { pushback(c); np = lookup(namep, state); c te==3 && sc== '<')) { sch(sc); filname = lp; inctype = sc=='<'; if (sc== '<') { /* fprintf(fout==stdout?stderr:stdout, "note: include <> obsolete, use \"\"\n"); */ sc= '>'; } instring++; while ((c=getch())!=sc && c!='\n' && c!='\0') { sch(c); if (c=='\\') sch(getch()); } instring = 0; if (flslvl) goto out; if (state==3) { if (flslvl) goto out; *lp = '\0'; while ((c=getch())!='\n' && c!='\0'); if (ifno+1 >=MAXINC) p==line+LINELEN-2) error("Line overflow", 0); *rlp++ = c; if (rlp>line+LINELEN-1) rlp = line+LINELEN-1; lp = rlp; } savch(c) { *stringbuf++ = c; if (stringbuf-sbf < SBSIZE) return; error("Too much defining", 0); exit(exfail); } getch() { register int c, lastst; while ((c=getc1())=='/' && !instring) { if ((c=getc1())!='*') { pushback(c); return('/'); } if (!skipcom) {putc('/',fout); putc('*', fout);} lastst=0; while ( (c = getc1()) != '\0') { if (lastst && c=turn(sp); } char revbuff[200], *bp; backsch(c) { if (bp-revbuff > 200) error("Excessive define looping", bp--); *bp++ = c; } subst(np, sp) char *np; struct symtab *sp; { register char *vp; int macflg; lp = np; bp = revbuff; if (depth++>100) { error("define recursion loop on %s", np); return; } if ((vp = sp->value) == 0) return; macflg= (*vp == '('); /* arrange that define unix unix still has no effect, avoiding rescanning */ while (blank(*vp)) vp++; if (strcmp(sp->name,vp) == continue; case 'D': if (predef>prespc+NPREDEF) { error("too many -D options, ignoring %s",argv[i]); continue; } *predef++ = argv[i]+2; continue; case 'U': if (prund>punspc+NPREDEF) { error("too many -U options, ignoring %s",argv[i]); continue; } *prund++ = argv[i]+2; continue; case 'I': if (nd>8) error("excessive -I file (%s) ignored",argv[i]); else dirs[nd++] = argv[i]+2; continue; casf (sp=strdex(*--predp, '=')) { *sp++=0; stsym(*predp, sp); } else insym(&prdloc, *predp); predp=prund; while (predp>punspc) { if (sp=strdex(*--predp, '=')) *sp++=0; lookup(*predp, DROP); } stringbuf = sbf; trulvl = 0; flslvl = 0; line = ln; lineno[0] = 1; if (pflag==0) fprintf(fout, "# 1 \"%s\"\n", fnames[ifno]); while(getline()) { skipcom=0; if (ln[0] != '#' && flslvl==0) { # ifdef tgp ifbrk= checklen(line); # endif for (rlp = line; c = *rlp++;) putc(c= getch(); } if (state==1) { if (np==defloc) skipcom = state = 2; else if (np==incloc) state = 3; else if (np==ifnloc) state = 4; else if (np==ifdloc) state = 5; else if (np==eifloc) { if (flslvl) --flslvl; else if (trulvl) --trulvl; else errback("If-less endif",0); goto out; } else if (np==elsloc) { if (flslvl) --flslvl? ++flslvl : ++trulvl; else if (trulvl) {++flslvl; --trulvl;} else ererror("Unreasonable include nesting",0); filok=0; for(dirp=dirs+inctype; *dirp; dirp++) { if (filname[0]=='/' || **dirp=='\0') strcpy(nfil,filname); else { strcpy(nfil,*dirp); # ifdef unix strcat(nfil, "/"); # endif # ifdef gcos strcat(nfil, "/"); # endif # ifdef ibm strcat(nfil, "."); # endif strcat(nfil, filname); } if ( (fins[ifno+1]=fopen(nfil, "r"))!=NULL) { filok=1; fin = fins[++ifno]; break; } ='/') { if (!skipcom) putc('/', fout); break; } if (c=='\n' || !skipcom) putc(c, fout); lastst = (c=='*'); } if (c=='\0')break; } return(c); } char pushbuff[EXPSIZE]; char *pushp pushbuff; pushback(c) { *++pushp = c; if (pushp>pushbuff+EXPSIZE) { error("too much backup", 0); exit(8); } } getc1() { register c; if (*pushp !=0) return(*pushp--); depth=0; if ((c = getc(fin)) == EOF && ifno>0) { fclose(fin); fin = fins[--ifno]; if (pflag==0) fprintf(SAME) { while (*vp) sch(*vp++); return; } if (macflg) expdef(vp); else while (*vp) backsch(*vp++); while (bp>revbuff) pushback(*--bp); } char * copy(as) char as[]; { register char *otsp, *s; int i; otsp = tsp; s = as; while(*tsp++ = *s++); if (tsp >tsa+CHSPACE) { # ifdef unix tsp = tsa = i = calloc(CHSPACE+50,sizeof(char)); if (i== NULL) # endif { error("no space for file names", 0); exit(8); } } return(otsp); } expdef(proto) char *proto; { char buffer[EXPSIZE], *parg[20], *pval[20], name[20], *cspace, *wp; char protcop[EXPSIZE], *pr; int narg, k, c; pr = protcop; while (*pr++ = *proto++) if (pr>=protcop+EXPSIZE){ error("define prototype too big", 0); exit(8); } proto= protcop; for (narg=0; (parg[narg] = token(&proto)) != 0; narg++) ; /* now scan input */ cspace = buffer; while ((c=getch()) == ' '); if (c != '(') { error("defined function requires arguments", 0); return; } pushback(c); for(k=0; pval[k] = coptok(&cspace, buffer+EXPSIZE); k+(val); } letter(c) { if (isalpha(c) || c == '_') return (1); else return(0); } letnum(c) { if (letter(c) || isdigit(c)) return(1); else return(0); } blank(c) { return(c==' ' || c== '\t'); } char * strdex(s,c) char *s; { while (*s) if (*s==c) return(s); else s++; return(0); } # ifdef tgp # define MAXOUT 80 checklen(sln) char *sln; { /* for tgp: scans string sln, and puts in newlines for blanks, where it likes, but to make lines less than MAXOUT chars long */ char *p, *s, *st; intA@ 'tP & PX PA@ &t'P  #%C & P X&P#юp(p(ЇX,X(%Q CNX C06'tX & P & PX PA@ &t !$%C& & P P X&PX(#юp(XP@TXP@XP!P@%XP@`XP@d\!P@%XP@lXP@pXh!tabflg$cflg$labno#open" fin$printf" 0)back--; if (s-st >MAXOUT && p != 0) { st=p; *p= '\n'; ifdone=1; } if (stopc==0 && back==0) if (c==' ') p=s-1;; } return(ifdone); } # endif main(argc,argv) char *argv[]; { exit(mainpp (argc,argv) ); } $ PApC$ PAbCX!8$ PANCXC0@$PX@!9@PA@ <$P@@PA@ <$PCXB08X@!9@PA@ <$P@@PA@ <$Q@$P$PC4QPAAP -!4$QX P@C$QC@P@4&Y 3XPXB0X aBX z!%Q X PA.Cю$pDp0Ї$PX@C0X@P $P@#A@ P X !4$C`X {!9$QA@ P X }B0$AP %QB0X !5AvP X#6X@B0rX #юP@%XP@xXP@|Xt!P@%12EF H*12CS H ,1[aceinrz&b&<v(@dR #%':ABCFHIPRSTXYNbrXl|FF FFFFFFF FFFFFint nofloat; int peekc; int obuf[3+(512/sizeof(int))]; /***/ int tabflg; int cflg; int labno 1; main(argc, argv) char **argv; { /* A1 -> A A2 B A O B1 C B2 D BE L BF P C1 E C2 F F G H H R I R1 J S K I M M N * +1 S +2 C +4 1 +8 z -> 4 c 8 r 9 a 14 e 20 n 63 * +0100 */ auto c,snlflg,nlflg,t,smode,m,ssmode; extern fin; smode = nlflg = snlflg = ssmodr(t); goto loop; case '#': if(getcx()=='1') putchar('#'); else putchar('"'); goto loop; case '\'': printf("''"); goto loop; case '%': if (smode) /***/ printf(" PURE\n"); if (ssmode==0) { if ((peekc=getcx())=='[') { peekc = 0; /***/ printf(" IMPUR\n"); while((c=getcx())!=']') putchar(c); getcx(); /***/ printf(" EQU *\n PURE\n"); goto loop; } } loop1: switch (c=getcx()) { case ' ': case '\t': goto loop1; case 'a': m = 16; t ==')') return(0); while (**cpp == ' ') (*cpp)++; for (val = *cpp; (stc= **cpp) != ',' && stc!= ')'; (*cpp)++) { if (!letnum(stc) || (val == *cpp && !letter(stc))) { error("define prototype argument error"); return(0); } } return(val); } char * coptok (cpp, clim) char **cpp, *clim; { char *val; int stc, stop,paren; paren = stop = 0; val = *cpp; if (getch() == ')') return(0); while (((stc = getch()) != ',' && stc != ')' ) || paren > 0 || stop >0) { if (stc == '\0') { error("nondT'xXP PA@,PA@ XpDЇ$$P@PPPPXDC 6$PXHXPA@ P@#@PA@ X %C02$PX@&P@P@PA@ <$Q@X C@PA@ <@PA@ CX!:@PA@ <#:PACBAP 1#7X 2B0X PACOPAX P@Cp0p(Ї$AB C,$"$" $" $" $"$C$CCCb!)!X@P@ #юp(p(ЇX@C0P$P@X@!9@PA@ <$P@X(P@PA@ <$Q@C:X@C0$P@@PA@ <@PX(PA@ юp(C@"p(Ї@PA@ d#$# #юp(p(Ї,X( C0ɠ%#8PA@ZC$&ӡɠ-!3&&$ӭɠ9B ɠ0B$ &CP@$ɠ.B0,&ӡɠ9B ɠ0B$ e = cflg = 0; if (argc>1) if ((fin = open(argv[1], 0)) < 0) { printf("?\n"); return; } obuf[0] = 1; if (argc>2) if ((obuf[0] = creat(argv[2], 0666)) < 0) { printf("?\n"); return; } loop: c = getcx(); if (c!='\n' && c!='\t') nlflg = 0; if (ssmode!=0 && c!='%') { ssmode = 0; /***/ printf(" IMPUR\nL%d EQU *\n\tDB ", labno++); /***/ cflg++; } switch(c) { case '\0': /***/ printf(" PURE\n DC 0\n END\n"); fflush(obuf); return; case ':': if (!smode) /***/ = flag(); goto pf; case ',': /*** putchar(';'); ***/ goto loop1; case 'i': m = 12; t = flag(); goto pf; case 'z': m = 4; t = flag(); goto pf; case 'r': m = 9; t = flag(); goto pf; case '1': m = 5; t = flag(); goto pf; case 'c': t = 0; m = 8; goto pf; case 'e': t = flag(); m = 20; goto pf; case 'n': t = flag(); m = 63; pf: if ((c=getcx())=='*') m =+ 0100; else peekc = c; /***/ printf("\tDB X'%x',X'%x'\n" terminated macro call", 0); val = 0; break; } if (stop == 0 && (stc == '"' || stc == '\'')) stop = stc; else if (stc==stop) stop=0; if ( stc == '\\') { stc = getch(); if (stop>0 || (stc != ',' && stc != '\\')) *(*cpp)++ = '\\'; *(*cpp)++ = stc; } else { *(*cpp)++ = stc; if (stop==0) { if (stc == '(') paren++; if (stc == ')') paren--; } } if (*cpp >= clim) { error("define argument too long",0); exit(8); } } *(*cpp)++ = 0; pushback(stc); returnATCDCPAdCDPATCLPADCPPA4CC@P@0&Y 3X?PACAPACpGPACdAP 1!9JPACIPAX P@C(HPACMPACKPAz$PAPAHP C4$Q" $Q" $QC$QCQCC@DP@\&Y 3XX P@XPACzA1!8#PA#"PACR@5PA@ X#9@8PA@ op!=op; table++) if (table->op==0) return(0); for (opt = table->tabp; opt->tabdeg1!=0; opt++) { if (d1 > (opt->tabdeg1&077) || (opt->tabdeg1 >= 0100 && (p1->op != STAR))) continue; /***/ if (op != AMPER && notcompat(p1, opt->tabtyp1, op)) { continue; } if ((opdope[op]&BINARY)!=0 && p2!=0) { if (d2 > (opt->tabdeg2&077) || (opt->tabdeg2 >= 0100) && (p2->op != STAR) ) continue; if (notcompat(p2,opt->tabtyp2, 0)) continue; /*** *he register is pushed on the stack. * If the tree can't be compiled using efftab, * just use regtab. * Regtab must succeed or an "op not found" error results. * * A number of special cases are recognized, and * there is an interaction with the optimizer routines. */ rcexpr(atree, atable, reg) struct tnode *atree; struct table *atable; { register r; int modf, nargs, recurf; register struct tnode *tree; register struct table *table; table = atable; recurf = 0; if (reg<0) { recurf++; reg = ~ LTYPE lcval; extern int nchstr; extern int nerror; extern struct hshtab **paraml; extern struct hshtab **parame; extern int strflg; extern int mosflg; extern int initflg; extern int inhdr; extern char obuf[524]; /***/ extern char sbuf[524]; /***/ extern int regvar; extern int bitoffs; extern struct tnode funcblk; extern char cvntab[]; extern char numbuf[64]; extern struct hshtab **memlist; extern int nmems; extern struct hshtab structhole; extern int blklev; /* operators */ #define NULLOP 218 #define #define RLABEL 114 #define ITOC 109 #define SEOF 200 /* stack EOF marker in expr compilation */ /* types */ #define INT 0 #define CHAR 1 #define FLOAT 2 #define DOUBLE 3 #define STRUCT 4 #define SHORT 5 /***/ #define LONG 6 #define UNSIGN 7 #define UNION 8 /* adjusted later to struct */ #define TYPE 07 #define BIGTYPE 060000 #define TYLEN 2 #define XTYPE (03<<3) #define PTR 010 #define FUNC 020 #define ARRAY 030 /* storage classes */ #define KEYWC 1 #define DEFXTRN 20 #define TYPEDEF 9 #define MOS * functions */ char *sbrk(); struct tnode *tree(); char *copnum(); struct tnode *convert(); struct tnode *chkfun(); struct tnode *disarray(); struct tnode *block(); struct cnode *cblock(); struct fnode *fblock(); char *gblock(); struct tnode *pexpr(); struct str *strdec(); struct hshtab *xprtype(); struct tnode *nblock(); ascbuf)<0) { error("Missing temp file"); exit(1); } getree(); /***/ printf(" end\n"); flush(); exit(nerror!=0); } /* * Given a tree, a code table, and a * count of available registers, find the code table * for the appropriate operator such that the operands * are of the right type and the number of registers * required is not too large. * Return a ptr to the table entry or 0 if none found. */ char *match(atree, table, nrleft) struct tnode *atree; struct table *table; { int op, d1, d2, do** Kludge for SHORT - mh and dh don't mean what *** you think, so special case is required. *** This should really be handled by a new *** code table category. ***/ /***/ if (p2->type==SHORT && opt->tabtyp2==1 /***/ && (op==TIMES || op==ASTIMES || op==DIVIDE /***/ || op==ASDIV || op==MOD || op==ASMOD)) /***/ continue; } return(opt); } return(0); } /* * Given a tree, a code table, and a register, * produce code to evaluate the tree with the appropriate table. * Registreg; if (reg>=020) { reg =- 020; recurf++; } } again: if((tree=atree)==0) return(0); if (opdope[tree->op]&RELAT && tree->tr2->op==CON && tree->tr2->value==0 && table==cctab) tree = atree = tree->tr1; /* * fieldselect(...) : in efftab mode, * ignore the select, otherwise * do the shift and mask. */ if (tree->op == FSELT) { if (table==efftab) atree = tree = tree->tr1; else { tree->op = FSEL; atree = tree = optim(tree); } } switch (tree->op) { /* * An initializEOF 0 #define SEMI 1 #define LBRACE 2 #define RBRACE 3 #define LBRACK 4 #define RBRACK 5 #define LPARN 6 #define RPARN 7 #define COLON 8 #define COMMA 9 #define FSEL 10 #define CAST 11 #define ETYPE 12 #define KEYW 19 #define NAME 20 #define CON 21 #define STRING 22 #define FCON 23 #define SFCON 24 #define LCON 25 #define SLCON 26 #define SIZEOF 91 #define INCBEF 30 #define DECBEF 31 #define INCAFT 32 #define DECAFT 33 #define EXCLA 34 #define AMPER 35 #define STAR 36 #define NEG 37 #define COMPL 38 #def10 #define AUTO 11 #define EXTERN 12 #define STATIC 13 #define REG 14 #define STRTAG 15 #define ARG 16 #define ARG1 17 #define AREG 18 #define MOU 21 /* keywords */ #define GOTO 20 #define RETURN 21 #define IF 22 #define WHILE 23 #define ELSE 24 #define SWITCH 25 #define CASE 26 #define BREAK 27 #define CONTIN 28 #define DO 29 #define DEFAULT 30 #define FOR 31 /* characters */ #define BSLASH 117 #define SHARP 118 #define INSERT 119 #define PERIOD 120 #define SQUOTE 121 #define DQUOTE 122 #define LETTE# /* C compiler, part 2 */ #include "c1.h" #define dbprint(op) /* */ #ifdef DEBUG #define dbprint(op) printf("\t. %s", opntab[op]) /***/ #endif /* * If using OS/MT CAL assembler, read string file first, since * it contains ENTRY definitions for functions */ #ifdef unix #define FILE1 argv[1] #define FILE2 argv[2] #else #define FILE1 argv[2] #define FILE2 argv[1] #endif char maprel[] { EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ, LESS, GREATQP, GREATP, LESSEQP, LESSP }; char notrel[] { NEQUAL, EQpe; register struct tnode *p2; register struct tnode *p1, *tree; register struct optab *opt; if ((tree=atree)==0) return(0); if ((op = tree->op)==0) return(0); if (table == lsptab) table = sptab; dope = opdope[op]; if ((dope&LEAF) == 0) p1 = tree->tr1; else p1 = tree; d1 = dcalc(p1, nrleft); if ((dope&BINARY)!=0) { p2 = tree->tr2; /* * If a subtree starts off with a conversion operator, * try for a match with the conversion eliminated. * E.g. int = double can be done witho      &,2!'-3"(.4#)/5ing expression */ case INIT: tree = optim(tree); doinit(tree->type, tree->tr1); return(0); /* * Put the value of an expression in r0, * for a switch or a return */ case RFORCE: if((r=rcexpr(tree->tr1, regtab, reg)) != 0) movreg(r, 0, tree->tr1); return(0); /* * sequential execution */ case SEQNC: rcexpr(tree->tr1, efftab, reg); atree = tree = tree->tr2; goto again; /* * Handle a subroutine call. It has to be done * here because if cexpr got called twice, the * aine DOT 39 #define PLUS 40 #define MINUS 41 #define TIMES 42 #define DIVIDE 43 #define MOD 44 #define RSHIFT 45 #define LSHIFT 46 #define AND 47 #define OR 48 #define EXOR 49 #define ARROW 50 #define ITOF 51 #define FTOI 52 #define LOGAND 53 #define LOGOR 54 #define FTOL 56 #define LTOF 57 #define ITOL 58 #define LTOI 59 #define ITOP 13 #define PTOI 14 #define LTOP 15 #define EQUAL 60 #define NEQUAL 61 #define LESSEQ 62 #define LESS 63 #define GREATEQ 64 #define GREAT 65 #define LESSEQP 66 #define LESSP 67R 123 #define DIGIT 124 #define NEWLN 125 #define SPACE 126 #define UNKN 127 /* * Special operators in intermediate code */ #define BDATA 200 #define WDATA 201 #define PROG 202 #define DATA 203 #define BSS 204 #define CSPACE 205 #define SSPACE 206 #define SYMDEF 207 #define SAVE 208 #define RETRN 209 #define EVEN 210 #define PROFIL 212 #define SWIT 213 #define EXPR 214 #define SNAME 215 #define RNAME 216 #define ANAME 217 #define SETSTK 219 #define SINIT 220 #define GLOBAL 221 /***/ /* Flag bits */ UAL, GREAT, GREATEQ, LESS, LESSEQ, GREATP, GREATQP, LESSP, LESSEQP }; struct tconst czero { CON, INT, 0}; struct tconst cone { CON, INT, 1}; struct table cregtab[1], lsptab[1]; int nreg 6; /***/ int isn 10000; main(argc, argv) char *argv[]; { /***/ register i; extern fout; if (argc<4) { error("Arg count"); exit(1); } if(fopen(FILE1, ascbuf)<0) { error("Missing temp file"); exit(1); } if ((fout = creat(argv[3], 0666)) < 0) { error("Can't create %s", argv[3]); exit(1); } /*** ***ut generating * the converted int in a register by * movf double,fr0; movfi fr0,int . */ if (opdope[p1->op]&CNVRT && (opdope[p2->op]&CNVRT)==0 && (opdope[p1->tr1->op]&CNVRT)==0) { tree->tr1 = p1->tr1; if (opt = match(tree, table, nrleft)) return(opt); tree->tr1 = p1; } else if (opdope[p2->op]&CNVRT && (opdope[p1->op]&CNVRT)==0 && (opdope[p2->tr1->op]&CNVRT)==0) { tree->tr2 = p2->tr1; if (opt = match(tree, table, nrleft)) return(opt); tree->tr2 = p2; } d2 = ders reg and upcan be used. * If there is a value, it is desired that it appear in reg. * The routine returns the register in which the value actually appears. * This routine must work or there is an error. * If the table called for is cctab, sptab, or efftab, * and tree can't be done using the called-for table, * another try is made. * If the tree can't be compiled using cctab, regtab is * used and a "tst" instruction is produced. * If the tree can't be compiled using sptab, * regtab is used and trguments might be compiled twice. * There is also some fiddling so the * first argument, in favorable circumstances, * goes to (sp) instead of -(sp), reducing * the amount of stack-popping. */ case CALL: /*** r = 0; nargs = 0; modf = 0; if (tree->tr1->op!=NAME || tree->tr1->class!=EXTERN) { nargs++; nstack++; } tree = tree->tr2; if(tree->op) { while (tree->op==COMMA) { r =+ comarg(tree->tr2, &modf); tree = tree->tr1; nargs++; } r =+ comarg(tree, &modf); nargs++; } tree = atree; tree->op = CALL2; if (modf && tree->tr1->op==NAME && tree->tr1->class==EXTERN) tree->op = CALL1; cexpr(tree, regtab, reg); popstk(r); nstack =- nargs; ***/ /***/ /* Find length of arguments and adjust stack */ /***/ nargs = pstack; /***/ r = 0; /***/ tree = tree->tr2; /***/ if (tree->op) { /***/ while (tree->op == COMMA) { /***/ r =+ arlength(tree->tr2->type); /***/ tree = tree->tr1; /***/ } /***/ r =+ arlength(tree->type); /***/ r =/ NCPW; /***/lay(&atree, table, reg)) { tree = atree; table = efftab; reg = r-1; } } /* * Basically, try to reorder the computation * so reg = x+y is done as reg = x; reg =+ y */ if (recurf==0 && reorder(&atree, table, reg)) { if (table==cctab && atree->op==NAME) return(reg); } tree = atree; if (table==efftab && tree->op==NAME) return(reg); if ((r=cexpr(tree, table, reg))>=0) return(r); if (table!=regtab && (table!=cctab||(opdope[tree->op]&RELAT)==0)) { if((r=cexpr(tree, regtab, resion is * desired, more work must be done. */ if ((opd&RELAT||c==LOGAND||c==LOGOR||c==EXCLA) && table!=cctab) { cbranch(tree, c=isn++, 1, reg); rcexpr(&czero, table, reg); branch(isn, 0); label(c); rcexpr(&cone, table, reg); label(isn++); return(reg); } if(c==QUEST) { if (table==cctab) return(-1); cbranch(tree->tr1, c=isn++, 0, reg); flag = nstack; rreg = rcexpr(p1->tr1, table, reg); nstack = flag; branch(r=isn++, 0); label(c); reg = rcexpr(p1->tr2, table, rreg); if -p1->value; } p2 = 0; if (opdope[tree->op]&BINARY) { p2 = tree->tr2; if (p2->op==FCON && p2->value>0) { /***/ printf(" impur\nL%d\tdc\ty'%x'\n pure\n", /***/ p2->value, p2->fvalue); p2->value = -p2->value; } } loop: /* * The 0200 bit asks for a tab. */ if ((c = *string++) & 0200) { c =& 0177; putchar('\t'); } switch (c) { case '\n': dbprint(tree->op); break; case '\0': if (!isfloat(tree)) if (tree->op==MOD||tree->op==ASMOD) reg--; return(reg); /* A1 */ corce right register */ } /***/ if ((c&02)!=0) { /***/ ctable = lsptab; /***/ if (++ntemp > maxtemp) /***/ maxtemp = ntemp; /***/ } if ((c&04)!=0) ctable = cctab; if ((flag&01) && ctable==regtab && (c&01)==0 && (tree->op==DIVIDE||tree->op==MOD || tree->op==ASDIV||tree->op==ASMOD)) ctable = cregtab; if ((c&01)!=0) { p = p->tr1; /***/ if(collcon(p) && ctable!=lsptab) { /*** if (p->op==STAR) p = p->tr1; ***/ p = p->tr1; } } if (c&010) r = reg1; else ring == '+') { /* pop stack */ /***/ string++; /***/ ntemp--; /***/ } /***/ goto loop; /* #1 */ case '#': p = p1->tr1; goto nmbr; /* #2 */ case '"': p = p2->tr1; nmbr: if(collcon(p)) { /*** if (p->op==STAR) { printf("*"); p = p->tr1; } ***/ if ((p = p->tr2)->op == CON) { if (p->value) psoct(p->value); /***/ else /***/ putchar('0'); } else if (p->op==AMPER) pname(p->tr1, 0); } /***/ else /***/ putchar('0'); goto loop; /* * Certain adju if ((modf = nstack+r) > pstack) /***/ setstk(modf); /***/ if (modf < pstack) { /***/ nstack =+ pstack-modf; /***/ r =+ pstack-modf; /***/ } /***/ /* Compile arguments onto stack */ /***/ tree = atree->tr2; /***/ while (tree->op == COMMA) { /***/ comarg(tree->tr2); /***/ tree = tree->tr1; /***/ } /***/ comarg(tree); /***/ } /***/ tree = atree; /***/ tree->op = CALL1; /***/ cexpr(tree, regtab, reg); /***/ if (pstack != nargs) /***/ setstk(nargs); /***/ nstack =- r; ig))>=0) { fixup: /***/ modf = ishfloat(tree); if (table==sptab) { /***/ if(tree->type==LONG) /***/ printf("\tsta\tr%d,%d(sp)\n", /***/ r+1, (pstack-nstack+1)*NCPW); /***/ printf("\tst%c\tr%d,%d(sp)\n", modf, /***/ modf=='e'? r*2 : r, (pstack-nstack)*NCPW); } /***/ if (table==lsptab) { /***/ printf("\tst%c\tr%d,%d(r14)\n", modf, /***/ modf=='e'? r*2 : r, NCPW*(ntemp-1)); /***/ } if (table==cctab) /***/ movreg(r, r, tree); return(r); } } /* * There's a (rreg!=reg) movreg(reg, rreg, tree->tr2); label(r); return(rreg); } reg = oddreg(tree, reg); reg1 = reg+1; /* * long values take 2 registers. */ if ((tree->type==LONG||opd&RELAT&&tree->tr1->type==LONG) && tree->op!=ITOL) reg1++; /* * Leaves of the expression tree */ if ((r = chkleaf(tree, table, reg)) >= 0) return(r); /* * Because of a peculiarity of the PDP11 table * char = *intreg++ and *--intreg cannot go through. */ /*** if (tree->tr1->type==CHAR && tree->tr2->type!=Case 'A': p = p1; goto adr; /* A2 */ case 'B': p = p2; goto adr; adr: c = 0; while (*string=='\'') { c++; string++; } if (*string=='+') { c = 100; string++; } pname(p, c); goto loop; /* I */ case 'M': if ((c = *string)=='\'') string++; else c = 0; prins(tree->op, c, instab); goto loop; /* B1 */ case 'C': if ((opd&LEAF) != 0) p = tree; else p = p1; goto pbyte; /* BF */ case 'P': p = tree; goto pb1; /* B2 */ case 'D': p = p2; p if (opdope[p->op]&LEAF || p->degree < 2) r = reg; else r = areg; rreg = rcexpr(p, ctable, r); if (ctable!=regtab && ctable!=cregtab) goto loop; if (c&010) { if (c&020 && rreg!=reg1) movreg(rreg, reg1, p); else reg1 = rreg; } else if (rreg!=reg) if ((c&020)==0 && oddreg(tree, 0)==0 && tree->type!=LONG && (flag&04 || flag&01&&xdcalc(p2,nreg-rreg-1)<=(opt->tabdeg2&077) || flag&02&&xdcalc(p1,nreg-rreg-1)<=(opt->tabdeg1&077))) { reg = rreg; reg1 = rrstments for / % and PTOI */ case 'T': c = reg-1; /*** if (tree->op == PTOI) { printf("bic r%d,r%d\nsbc r%d\n", c,c,c); goto loop; } if (p1->type==UNSIGN || p1->type&XTYPE) { printf("clr r%d\n", c); goto loop; } if (dcalc(p1, 5)>12 && !match(p1, cctab, 10)) printf("tst r%d\n", reg); printf("sxt r%d\n", c); ***/ /***/ if (tree->op==PTOI || p1->type==UNSIGN || p1->type&XTYPE) { /***/ printf("\tlis\tr%d,0\n", c); /***/ goto loop; /***/ } /***/ printf("\tldar\tr%d,r%d\n\tsf (table==efftab || table==regtab) return(0); r = 0; goto fixup; /* * Longs need special treatment. */ case ASLSH: case LSHIFT: if (tree->type==LONG) { if (tree->tr2->op==ITOL) tree->tr2 = tree->tr2->tr1; else tree->tr2 = optim(tnode(LTOI,INT,tree->tr2)); if (tree->op==ASLSH) tree->op = ASLSHL; else tree->op = LLSHIFT; } break; /* * Try to change * to shift. */ case TIMES: case ASTIMES: tree = pow2(tree); break; /*** *** Interdata special: chalast chance for this operator */ if (tree->op==LTOI) { r = rcexpr(tree->tr1, regtab, reg); if (r >= 0) { r++; goto fixup; } } if (tree->type == STRUCT) error("Illegal operation on structure"); else if (tree->op>0 && tree->opop]) error("No code table for op: %s", opntab[tree->op]); else error("No code table for op %d", tree->op); return(reg); } /* * Try to compile the tree with the code table using * registers areg and up. If successful, * return the regHAR && (tree->tr2->op==AUTOI||tree->tr2->op==AUTOD)) tree->tr2 = tnode(LOAD, tree->tr2->type, tree->tr2); ***/ if (table==cregtab) table = regtab; /* * The following peculiar code depends on the fact that * if you just want the codition codes set, efftab * will generate the right code unless the operator is *** ASSIGN or * postfix ++ or --. Unravelled, if the table is * cctab and the operator is not special, try first * for efftab; if the table isn't, if the operator is, * or the fibyte: /***/ if (p->op==CON || p->op==AMPER) { #ifdef HALFW /***/ putchar('h'); #endif /***/ putchar('i'); /***/ goto loop; /***/ } /***/ if (p->op==NAME && p->class==REG) { #ifdef HALFW /***/ putchar('h'); #endif /***/ putchar('r'); /***/ goto loop; /***/ } /***/ if (p->type==CHAR) { /***/ putchar('b'); /***/ goto loop; /***/ } /***/ if (p->type==SHORT) { /***/ putchar('h'); /***/ goto loop; /***/ } /***/ pb1: /***/ if (c=ishfloat(p)) /***/ putchar(c); goto loop; /* BE */ eg+1; } else movreg(rreg, reg, p); goto loop; /* R */ case 'I': r = reg; if (*string=='-') { string++; r--; } goto preg; /* R1 */ case 'J': r = reg1; preg: if (*string=='+') { string++; r++; } /***/ else if (*string==':') { /***/ string++; /***/ if (tree->op==MOD || tree->op==ASMOD) /***/ r--; /***/ } /***/ else if (*string=='*') { /***/ string++; /***/ if (isfloat(tree) || tree->op==FTOI) { /***/ r =* 2; /***/ goto pregf; /***/ } /***/ } ifraa\tr%d,31\n", c, reg, c); goto loop; /* adc sbc, clr, or sxt as required for longs */ /*** case 'V': switch(tree->op) { case PLUS: case ASPLUS: case INCBEF: case INCAFT: printf("adc"); break; case MINUS: case ASMINUS: case NEG: case DECBEF: case DECAFT: printf("sbc"); break; case ASSIGN: p = tree->tr2; goto lcasev; case ASDIV: case ASMOD: case ASULSH: p = tree->tr1; lcasev: if (p->type!=LONG) { if (p->type==UNSIGN || p->type&XTYPE) pringe --, -= to ++, += to use AM instruction ***/ /***/ case ASMINUS: /***/ if (tree->tr2->op != CON) /***/ break; /***/ case DECBEF: /***/ case DECAFT: /***/ if (table==efftab || table==cctab) { /***/ tree->op =+ (ASPLUS-ASMINUS); /***/ tree->tr2->value = -tree->tr2->value; /***/ } } /* * Try to find postfix ++ and -- operators that can be * pulled out and done after the rest of the expression */ if (table!=cctab && table!=cregtab && recurf<2 && (opdope[tree->op]&LEAF)==0) { if (r=deister where the value actually ended up. * If unsuccessful, return -1. * * Most of the work is the macro-expansion of the * code table. */ cexpr(atree, table, areg) struct tnode *atree; struct table *table; { int c, r; register struct tnode *p, *p1, *tree; struct table *ctable; register struct tnode *p2; char *string; int reg, reg1, rreg, flag, opd; char *opt; tree = atree; reg = areg; p1 = tree->tr2; c = tree->op; opd = opdope[c]; /* * When the value of a relational or a logical expresrst match fails, try to match * with the table actually asked for. */ r = nreg - reg; /***/ if (table!=cctab || c==ASSIGN /***/ || c==INCAFT || c==DECAFT || tree->type==LONG || (opt = match(tree, efftab, r)) == 0) if ((opt=match(tree, table, r))==0) return(-1); string = opt->tabstring; p1 = tree->tr1; if (p1->op==FCON && p1->value>0) { /*** *** Warning -- lark's vomit *** (won't work on the 7/16) ***/ /***/ printf(" impur\nL%d\tdc\ty'%x'\n pure\n", p1->value, p1->fvalue); p1->value =/*** case 'L': if (p1->type==CHAR || p2->type==CHAR) putchar('b'); p = tree; goto pb1; ***/ /* F */ case 'G': p = p1; flag = 01; goto subtre; /* S */ case 'K': p = p2; flag = 02; goto subtre; /* H */ case 'H': p = tree; flag = 04; subtre: ctable = regtab; if (flag&04) ctable = cregtab; c = *string++ - 'A'; /***/ if ((c&020) && !reg) { /* nonzero register required */ /***/ reg = 1; /***/ reg1 = 2; /***/ } if (*string=='!') { string++; c =| 020; /* f (r>nreg || r>=4 && tree->type==DOUBLE) error("Register overflow: simplify expression"); /***/ pregf: printf("r%d", r); goto loop; /***/ /* P */ /***/ case 'Q': /***/ if (*string == '-') { /* push onto stack */ /***/ string++; /***/ if (++ntemp > maxtemp) /***/ maxtemp = ntemp; /***/ goto loop; /***/ } /***/ /* reference to top word on stack */ /***/ if (table==sptab) /***/ printf("%d(sp)", (pstack - nstack)*NCPW); /***/ else /***/ printf("%d(r14)", NCPW*(ntemp-1)); /***/ if (*stntf("clr"); else printf("sxt"); goto loop; } default: while ((c = *string++)!='\n' && c!='\0'); break; } goto loop; ***/ /* * Mask used in field assignments */ case 'Z': /***/ psoct(~tree->mask); goto loop; /* * Relational on long values. * Might bug out early. E.g., * (long<0) can be determined with only 1 test. */ case 'X': if (xlongrel(*string++ - '0')) return(reg); goto loop; } putchar(c); goto loop; } /* * This routine just calls sreorder (below) * on the subtrees and then on the tree itself. * It returns non-zero if anything changed. */ reorder(treep, table, reg) struct tnode **treep; struct table *table; { register r, o; register struct tnode *p; p = *treep; o = p->op; if (opdope[o]&LEAF || o==LOGOR || o==LOGAND) return(0); while(sreorder(&p->tr1, regtab, reg)) ; if (opdope[o]&BINARY) while(sreorder(&p->tr2, regtab, reg)) ; r = 0; /***/ if (table!=cctab && table!=cregtab) while (sreorder(treep, table, reg)) r++; *tre>tr1->class!=REG || p1->tr1->nloc!=p->tr1->nloc) rcexpr(p, efftab, reg); p->tr2 = p1->tr2; p->op = p1->op + ASPLUS - PLUS; *treep = p; return(1); } goto OK; case ASTIMES: if (!ispow2(p)) return(0); case ASPLUS: case ASMINUS: case ASAND: case ASANDN: case ASOR: case ASXOR: case INCBEF: case DECBEF: OK: if (table==cctab||table==cregtab) reg =+ 020; rcexpr(optim(p), efftab, ~reg); *treep = p1; return(1); } return(0); } /* * Delay h= p->nloc; return(q); } /* * If the tree can be immediately loaded into a register, * produce code to do so and return success. */ chkleaf(atree, table, reg) struct tnode *atree; { struct tnode lbuf; register struct tnode *tree; tree = atree; if (tree->op!=STAR && dcalc(tree, nreg-reg) > 12) return(-1); /***/ if (tree->op==AMPER) /***/ return(-1); lbuf.op = LOAD; lbuf.type = tree->type; lbuf.degree = tree->degree; lbuf.tr1 = tree; return(rcexpr(&lbuf, table, reg)); } /* * Compile a funct/***/ } /***/ else if (tree->op==AMPER && type!=SHORT && type!=CHAR) { pname(tree->tr1, 0); putchar('\n'); } else goto illinit; return; case DOUBLE: case FLOAT: if (tree->op==ITOF) { if (tree->tr1->op==CON) { fval = tree->tr1->value; } else goto illinit; } else if (tree->op==FCON || tree->op==SFCON) fval = tree->fvalue; else if (tree->op==LTOF) { if (tree->tr1->op!=LCON) goto illinit; fval = tree->tr1->lvalue; } else goto illinit; /*** if (type==FLOA# /* * C compiler */ #include "c1.h" max(a, b) { if (a>b) return(a); return(b); } degree(at) struct tnode *at; { register struct tnode *t, *t1; if ((t=at)==0 || t->op==0) return(0); if (t->op == CON) return(-3); if (t->op == AMPER) return(-2); if (t->op==ITOL) { if ((t1 = isconstant(t)) && t1->value>=0) return(-2); if ((t1=t->tr1)->type==UNSIGN && opdope[t1->op]&LEAF) return(-1); } if ((opdope[t->op] & LEAF) != 0) { if (t->type==CHAR || t->type==FLOAT) return(1); retap; { register struct tnode *p; p = ap; if (p->class==SOFFS || p->class==STATIC) printf("L%d", p->nloc); else /***/ printf("%.8s", &(p->nloc)); } xdcalc(ap, nrleft) struct tnode *ap; { register struct tnode *p; register d; p = ap; d = dcalc(p, nrleft); if (d<20 && p->type==CHAR) { if (nrleft>=1) d = 20; else d = 24; } return(d); } dcalc(ap, nrleft) struct tnode *ap; { register struct tnode *p, *p1; if ((p=ap)==0) return(0); switch (p->op) { case NAME: if (p->class==REG)ep = optim(*treep); return(r); } /* * Basically this routine carries out two kinds of optimization. * First, it observes that "x + (reg = y)" where actually * the = is any assignment op is better done as "reg=y; x+reg". * In this case rcexpr is called to do the first part and the * tree is modified so the name of the register * replaces the assignment. * Moreover, expressions like "reg = x+y" are best done as * "reg = x; reg =+ y" (so long as "reg" and "y" are not the same!). */ sreorder(treep, tandles postfix ++ and -- *** It observes that "x + reg++" is better *** treated as "x + reg; reg++". * If the operator is ++ or -- itself, * it calls rcexpr to load the operand, letting * the calling instance of rcexpr to do the * ++ using efftab. * Otherwise it uses sdelay to search for inc/dec * among the operands. */ delay(treep, table, reg) struct tnode **treep; { register struct tnode *p, *p1; register r; p = *treep; if ((p->op==INCAFT||p->op==DECAFT) /***/ && p->tr1->op==NAME && p->tr1ion argument. * If the stack is currently empty, put it in (sp) * rather than -(sp); this will save a pop. * Return the number of bytes pushed, * for future popping. */ comarg(atree) { register struct tnode *tree; register retval; tree = atree; /***/ if (tree->type == LONG) /***/ nstack++; /***/ nstack++; /***/ rcexpr(tree, sptab, 0); } /* * Compile an initializing expression */ doinit(atype, atree) struct tnode *atree; { register struct tnode *tree; register int type; float sfval; double fT) { ***/ sfval = fval; /***/ psoct(sfval); /***/ putchar('\n'); /*** } else printf("%o; %o; %o; %o\n", fval); ***/ return; /*** case LONG: if (tree->op==FTOL) { tree = tree->tr1; if (tree->op==SFCON) tree->op = FCON; if (tree->op!= FCON) goto illinit; lval = tree->fvalue; } else if (tree->op==ITOL) { if (tree->tr1->op != CON) goto illinit; lval = tree->tr1->value; } else if (tree->op==LCON) lval = tree->lvalue; else goto illinit; printf("%o; %o\urn(0); } return(t->degree); } pname(ap, flag) struct tnode *ap; { register i; register struct tnode *p; struct { int intx[2]; }; p = ap; loop: switch(p->op) { /*** case LCON: printf("$%o", flag>10? p->lvalue.intx[1]:p->lvalue.intx[0]); return; ***/ case SFCON: case CON: psoct(p->value); return; case FCON: printf("L%d", (p->value>0? p->value: -p->value)); return; case NAME: i = p->offset; if (flag>10) /***/ i =+ NCPW; /***/ if (p->class==OFFS && p->regno==14) { /***/ i return(9); case AMPER: case FCON: case LCON: case AUTOI: case AUTOD: return(12); case CON: case SFCON: if (p->value==0) return(4); if (p->value==1) return(5); /***/ return(8); /*** case STAR: p1 = p->tr1; if (p1->op==NAME||p1->op==CON||p1->op==AUTOI||p1->op==AUTOD) if (p->type!=LONG) return(12); ***/ } if (p->type==LONG) nrleft--; return(p->degree <= nrleft? 20: 24); } notcompat(ap, ast, op) struct tnode *ap; { register at, st; register struct tnode *p; p = aable, reg) struct tnode **treep; struct table *table; { register struct tnode *p, *p1; p = *treep; if (opdope[p->op]&LEAF) return(0); if (p->op==PLUS) if (reorder(&p->tr2, table, reg)) *treep = p = optim(p); p1 = p->tr1; if (p->op==STAR || p->op==PLUS) { if (reorder(&p->tr1, table, reg)) *treep = p = optim(p); p1 = p->tr1; } /***/ if (opdope[p->op]&LEAF) /***/ return(0); /***/ if (p1->op==NAME && p1->class==REG) switch(p->op) { case ASLSH: case ASRSH: case ASSIGN: /***/ if (p1->class==REG) { return(1+rcexpr(p->tr1, table, reg)); } p1 = 0; if (opdope[p->op]&BINARY) p1 = sdelay(&p->tr2); if (p1==0) p1 = sdelay(&p->tr1); if (p1) { r = rcexpr(optim(p), table, reg); *treep = p1; return(r+1); } return(0); } sdelay(ap) struct tnode **ap; { register struct tnode *p, *p1; p = *ap; /***/ if ((p->op==INCAFT||p->op==DECAFT) && p->tr1->op==NAME /***/ && p->tr1->class==REG) { *ap = ncopy(p->tr1); return(p); } if (p->op==STAR || p->op==PLUS) if (p1=sdelay(&p->trval; long lval; /***/ register val; tree = atree; type = atype; if (type==CHAR) { /***/ printf("\tdb\t"); if (tree->type&XTYPE) goto illinit; } /***/ else /***/ printf("\tdc\t"); if (type&XTYPE) type = INT; switch (type) { case INT: case UNSIGN: /***/ case SHORT: /***/ case CHAR: if (tree->op==FTOI) { if (tree->tr1->op!=FCON && tree->tr1->op!=SFCON) goto illinit; tree = tree->tr1; tree->value = tree->fvalue; tree->op = CON; } else if (tree->op==LTOI) { if (tree->tr1n", lval); return; ***/ } illinit: error("Illegal initialization"); } /*** movreg(r0, r1, tree) struct tnode *tree; { register char *s; if (r0==r1) return; if (tree->type==LONG) { s = "mov r%d,r%d\nmov r%d,r%d\n"; if (r0 < r1) printf(s, r0+1,r1+1,r0,r1); else printf(s, r0,r1,r0+1,r1+1); return; } printf("mov%c r%d,r%d\n", isfloat(tree), r0, r1); } ***/ movreg(rsource, rdest, tree) struct tnode *tree; { register r1, r2, modf; r1 = rdest; r2 = rsource; if ((modf = ishfloat(treef (i<0) /***/ printf("L.%d%d(r14)", fautolen, i); /***/ else /***/ printf("L.%d+%d(r14)", fautolen, i); /***/ return; /***/ } if (i) { /***/ printf("%d", i); if (p->class!=OFFS) putchar('+'); if (p->class==REG) regerr(); } /***/ else /***/ if (p->class==OFFS) /***/ putchar('0'); switch(p->class) { case SOFFS: case XOFFS: pbase(p); case OFFS: printf("(r%d)", p->regno); return; case EXTERN: case STATIC: pbase(p); return; case REG: printfp; at = p->type; st = ast; if (st==0) /* word, byte */ /***/ return(at!=CHAR && at!=INT && at!=UNSIGN && at!=SHORT && atop==NAME && p->class==REG && op==ASSIGN && st==CHAR) return(0); return(st != at); } prins(op, c, itable) struct instab *itable; { register->type==CHAR||isfloat(p->tr2)) return(0); if (p->op==ASSIGN) switch (p->tr2->op) { case TIMES: if (!ispow2(p->tr2)) break; p->tr2 = pow2(p->tr2); case PLUS: case MINUS: case AND: case ANDN: case OR: case EXOR: case LSHIFT: case RSHIFT: p1 = p->tr2->tr2; if (xdcalc(p1, 16) > 12 || p1->op==NAME &&(p1->nloc==p->tr1->nloc || p1->regno==p->tr1->nloc)) return(0); p1 = p->tr2; p->tr2 = p1->tr1; if (p1->tr1->op!=NAME || p1-1)) return(p1); if (p->op==PLUS) return(sdelay(&p->tr2)); return(0); } /* * Copy a tree node for a register variable. * Used by sdelay because if *reg-- is turned * into *reg; reg-- the *reg will in turn * be changed to some offset class, accidentally * modifying the reg--. */ ncopy(ap) struct tname *ap; { register struct tname *p, *q; p = ap; if (p->class!=REG) return(p); q = getblk(sizeof(*p)); q->op = p->op; q->type = p->type; q->class = p->class; q->offset = p->offset; q->nloc ->op!=LCON) goto illinit; tree = tree->tr1; lval = tree->lvalue; tree->op = CON; tree->value = lval; } /***/ if (tree->op == CON) { /***/ val = tree->value; /***/ if (type==SHORT) { /***/ if (val < -0x8000 || val > 0xffff) /***/ goto illinit; /***/ printf("x'%x'\n", val&0xffff); /***/ } else { /***/ if (type==CHAR) { /***/ if (val < -0x80 || val > 0xff) /***/ goto illinit; /***/ val =& 0xff; /***/ } /***/ psoct(val); /***/ putchar('\n'); /***/ } )) == 'e') { r1 =* 2; r2 =* 2; } printf("\tl%cr\tr%d,r%d\n", modf, r1, r2); } /*** *** Adjust stack pointer up or down to ns ***/ setstk(ns) { register op, offset; register char *s; op = 's'; if ((offset = (ns-pstack)*NCPW) < 0) { op = 'a'; offset = -offset; } s = (offset<16? "is" : (offset>>15? "ai" : "hi")); printf("\t%c%s\tsp,%d\n", op, s, offset); pstack = ns; } ("r%d", p->nloc); return; } error("Compiler error: pname"); return; case AMPER: /*** putchar('$'); ***/ p = p->tr1; if (p->op==NAME && p->class==REG) regerr(); goto loop; /*** case AUTOI: printf("(r%d)%c", p->nloc, flag==1?0:'+'); return; case AUTOD: printf("%c(r%d)", flag==2?0:'-', p->nloc); return; case STAR: p = p->tr1; putchar('*'); goto loop; ***/ } error("pname called illegally"); } regerr() { error("Illegal use of register"); } pbase(ap) struct tnode * struct instab *insp; register char *ip; for (insp=itable; insp->op != 0; insp++) { if (insp->op == op) { ip = c? insp->str2: insp->str1; if (ip==0) break; printf("%s", ip); return; } } error("No match' for op %d", op); } collcon(ap) struct tnode *ap; { register op; register struct tnode *p; p = ap; /*** if (p->op==STAR) { if (p->type==LONG+PTR) /* avoid *x(r); *x+2(r) */ /*** return(0); p = p->tr1; } ***/ if (p->op==PLUS) { op = p->tr2->op; /***/ if (op==CON || (o$*06%+17>DJ9?EK:@FL;AGM<BHN=CIOPV\bQW]c .data\n\ L%d:\ "}; ***/ char dirsw[] {"\n\ bp L%d\n\ ldar r1,r0\n\ bm L%d\n\ slaa r1,ladc\n\ lda r1,L%d(r1)\n\ br r1\n\ " }; char simpsw[] {"\ ldai r1,L%d-adc\n\ sta r0,L%d-adc\n\ L%d ais r1,adc\n\ ca r0,0(r1)\n\ bne L%d\n\ lda r1,L%d-L%d(r1)\n\ br r1\n\ " }; char hashsw[] {"*hash switch??\n"}; pswitch(afp, alp, deflab) struct swtab *afp, *alp; { int ncase, i, j, tabs, worst, best, range; register struct swtab *swp, *fp, *lp; int *poctab; fp = afp; lp = alp; if (fp==lp) { /***/ prinisn+tabs+1, isn+1, isn); isn++; for (i=0; i<=tabs; i++) printf("L%d\n", isn+i); for (i=0; iswval, tabs) == i) printf("%o\n", ldiv(0, swp->swval, tabs)); } printf("L%d:", isn++); for (i=0; iswval, tabs) == i) printf("L%d\n", swp->swlab); } ***/ esw: /***/ stext(); } sort(afp, alp) struct swtab *afp, *alp; { er struct tnode *tree; lbl = albl; reg = areg; again: if ((tree=atree)==0) return; switch(tree->op) { case LOGAND: if (cond) { cbranch(tree->tr1, l1=isn++, 0, reg); cbranch(tree->tr2, lbl, 1, reg); label(l1); } else { cbranch(tree->tr1, lbl, 0, reg); cbranch(tree->tr2, lbl, 0, reg); } return; case LOGOR: if (cond) { cbranch(tree->tr1, lbl, 1, reg); cbranch(tree->tr2, lbl, 1, reg); } else { cbranch(tree->tr1, l1=isn++, 1, reg); cbranch(tree->tr2, lbl, 0, reg)optim(tnode(COMPL, LONG, tree->tr2)); } doitover: if (cexpr(tree, cctab, reg) < 0) { if (tree->op==TAND) { tree->op = ANDN; tree->tr2 = optim(tnode(COMPL, LONG, tree->tr2)); goto doitover; } if (isrel) { tree->op = MINUS; tree->type = LONG; tree = optim(tree); } /*** printf("ashc $0,r%d\n", rcexpr(tree, regtab, reg)); ***/ branch(xlab1, op, 0); } xlab1 = xl1; xlab2 = xl2; xop = xo; xzero = xz; } /* * Tables for finding out how best to do long comparisons. * First ster struct tnode **sp; register t, op; /***/ register t1; static char s[9]; register struct swtab *swp; double atof(); /***/ static char numbuf[64]; struct tname *np; struct xtname *xnp; struct ftconst *fp; struct lconst *lp; int lbl, cond; curbase = funcbase; sp = expstack; for (;;) { if (sp >= &expstack[20]) error("Stack botch"); op = getw(ascbuf); if ((op&0177400) != 0177000) { error("Intermediate file error"); exit(1); } lbl = 0; switch(op =& 0377) { case SINIT: /***p==AMPER /***/ && p->tr2->tr1->class!=OFFS)) return(1); } return(0); } isfloat(at) struct tnode *at; { register struct tnode *t; t = at; if ((opdope[t->op]&RELAT)!=0) t = t->tr1; if (t->type==FLOAT || t->type==DOUBLE) { nfloat = 1; /***/ return('e'); } return(0); } ishfloat(t) /***/ struct tnode *t; /***/ { /***/ /***/ register c; /***/ if (c = isfloat(t)) /***/ return(c); #ifdef HALFW /***/ return('h'); #endif #ifndef HALFW /***/ return(0); #endif } /***/ oddreg(t, atf(" b L%d\n", deflab); return; } isn++; if (sort(fp, lp)) return; ncase = lp-fp; lp--; range = lp->swval - fp->swval; /* direct switch */ if (range>0 && range <= 3*ncase) { /***/ printf("* dirsw\n"); /***/ if (fp->swval) { /***/ printf(" sai r0,"); /***/ psoct(fp->swval); /***/ putchar('\n'); /***/ } /***/ printf(" cai r0,"); /***/ psoct(range); /***/ printf(dirsw, deflab, deflab, isn); /***/ sdata(); /***/ label(isn); isn++; for (i=fp->swval; i<=lp->swval; i++) { if (i==fp register struct swtab *cp, *fp, *lp; int intch, t; fp = afp; lp = alp; while (fp < --lp) { intch = 0; for (cp=fp; cpswval == cp[1].swval) { error("Duplicate case (%d)", cp->swval); return(1); } if (cp->swval > cp[1].swval) { intch++; t = cp->swval; cp->swval = cp[1].swval; cp[1].swval = t; t = cp->swlab; cp->swlab = cp[1].swlab; cp[1].swlab = t; } } if (intch==0) break; } return(0); } ispow2(atree) { register int d; r; label(l1); } return; case EXCLA: cbranch(tree->tr1, lbl, !cond, reg); return; case SEQNC: rcexpr(tree->tr1, efftab, reg); atree = tree->tr2; goto again; case ITOL: tree = tree->tr1; break; } op = tree->op; if (opdope[op]&RELAT && tree->tr1->op==ITOL && tree->tr2->op==ITOL) { tree->tr1 = tree->tr1->tr1; tree->tr2 = tree->tr2->tr1; } if (tree->type==LONG || opdope[op]&RELAT&&tree->tr1->type==LONG) { longrel(tree, lbl, cond, reg); return; } rcexpr(tree, cctab, rdimen is whether or not the comparison is with 0. * Second is which test: e.g. a>b-> * cmp a,b * bgt YES (first) * blt NO (second) * cmp a+2,b+2 * bhi YES (third) * NO: ... * Note some tests may not be needed. */ char lrtab[2][3][6] { 0, NEQUAL, LESS, LESS, GREAT, GREAT, NEQUAL, 0, GREAT, GREAT, LESS, LESS, EQUAL, NEQUAL, LESSEQP,LESSP, GREATQP,GREATP, 0, NEQUAL, LESS, LESS, GREATEQ,GREAT, NEQUAL, 0, GREAT, 0, 0, LESS, EQUAL, NEQUAL, EQUAL, 0, 0, NEQUAL, }; xlongrel(f) { register int o/ printf(" dc "); /***/ psoct(getw(ascbuf)); /***/ putchar('\n'); break; case EOF: return; case BDATA: if (getw(ascbuf) == 1) { /***/ printf(" db "); /***/ for (t=1; ; t++) { /***/ psoct(getw(ascbuf)); if (getw(ascbuf) != 1) break; /***/ if ((t&07) == 0) /***/ printf("\n db "); /***/ else /***/ putchar(','); } printf("\n"); } break; case PROG: /***/ stext(); break; case DATA: /***/ sdata(); break; case BSS: #ifdef unix /***/ printf(" bss\n")reg) struct tnode *t; { register reg; reg = areg; if (!isfloat(t)) switch(t->op) { case LLSHIFT: case ASLSHL: return((reg+1)&~01); case DIVIDE: case MOD: case ASDIV: case ASMOD: case PTOI: case ULSH: case ASULSH: /***/ case TIMES: /***/ case ASTIMES: reg++; /*** case TIMES: case ASTIMES: ***/ return(reg|1); } return(reg); } arlength(t) { if (t>=PTR) /***/ return(NCPW); switch(t) { case INT: case CHAR: case UNSIGN: /***/ case SHORT: /***/ return(NCPW); ->swval) { /***/ printf(" dc L%d\n", fp->swlab); fp++; } else /***/ printf(" dc L%d\n", deflab); } goto esw; } /* simple switch */ /*** if (ncase<8) { ***/ { i = isn++; j = isn++; /***/ printf(simpsw, i, j, isn, isn, j, i); /***/ sdata(); /***/ label(i); isn++; /***/ for (; fp<=lp; fp++) { /***/ printf(" dc "); /***/ psoct(fp->swval); /***/ putchar('\n'); /***/ } /***/ printf(" ds adc\nL%d equ *\n", j); for (fp = afp; fp<=lp; fp++) /***/ printf(" dc L%d\n", fp->swlaegister struct tnode *tree; tree = atree; if (!isfloat(tree) && tree->tr2->op==CON) { d = tree->tr2->value; if (d>1 && (d&(d-1))==0) return(d); } return(0); } pow2(atree) struct tnode *atree; { register int d, i; register struct tnode *tree; tree = atree; if (d = ispow2(tree)) { for (i=0; (d=>>1)!=0; i++); tree->tr2->value = i; switch (tree->op) { case TIMES: tree->op = LSHIFT; break; case ASTIMES: tree->op = ASLSH; break; case DIVIDE: /***/ case PTOI: /*** teg); op = tree->op; if ((opdope[op]&RELAT)==0) op = NEQUAL; else { l1 = tree->tr2->op; if ((l1==CON || l1==SFCON) && tree->tr2->value==0) op =+ 200; /* special for ptr tests */ /*** else op = maprel[op-EQUAL]; ***/ } /*** if (isfloat(tree)) printf("cfcc\n"); ***/ branch(lbl, op, !cond); } branch(lbl, aop, c) { register op; /***/ putchar('\t'); if(op=aop) /***/ prins(op, c, brtab); else /***/ putchar('b'); /***/ printf("\tL%d\n", lbl); } longrel(atree, lbl, cond, reg) struct tp, bno; op = xop; if (f==0) { if (bno = lrtab[xzero][0][op-EQUAL]) branch(xlab1, bno, 0); if (bno = lrtab[xzero][1][op-EQUAL]) { xlab2 = isn++; branch(xlab2, bno, 0); } if (lrtab[xzero][2][op-EQUAL]==0) return(1); } else { branch(xlab1, lrtab[xzero][2][op-EQUAL], 0); if (xlab2) label(xlab2); } return(0); } label(l) { /***/ printf("L%d equ *\n", l); } /*** popstk(a) { if (a) printf(" aai sp,%d\n", a); } ***/ error(s, p1, p2, p3, p4, p5, p6) { register f; extern fout; ; #else /***/ sdata(); #endif break; case SYMDEF: outname(s); /*** printf(".globl%s%s\n", s[0]?" _":"", s); ***/ /***/ if (s[0]) /***/ printf(" entry %s\n", s); break; /***/ case GLOBAL: /***/ outname(s); /***/ printf(" extrn %s\n", s); /***/ break; case RETRN: /***/ printf("\tlm\tr8,L.%d-%d(r14)\n\taai\tsp,L.%d\n", fautolen, 8*NCPW, fautolen); /***/ printf(" br rf\n"); break; case CSPACE: /***/ outname(s); /***/ t = getw(ascbuf); #ifdef unix /***/ printf("%s\tcomn\n\tds\t%case LONG: /***/ return(2*NCPW); case FLOAT: case DOUBLE: /***/ return(4); } return(1024); } /* * Strings for switch code. */ /*** char dirsw[] {"\ cmp r0,$%o\n\ jhi L%d\n\ asl r0\n\ jmp *L%d(r0)\n\ .data\n\ L%d:\ " }; char simpsw[] {"\ mov $L%d,r1\n\ mov r0,L%d\n\ L%d:cmp r0,(r1)+\n\ jne L%d\n\ jmp *L%d-L%d(r1)\n\ .data\n\ L%d:\ "}; char hashsw[] {"\ mov r0,r1\n\ clr r0\n\ div $%o,r0\n\ asl r1\n\ add $L%d,r1\n\ mov r0,*(r1)+\n\ mov (r1)+,r1\n\ L%d:cmp r0,-(r1)\n\ jne L%d\n\ jmp *L%d-L%d(r1)\n\b); /***/ printf(" dc L%d\n", deflab); goto esw; } /* hash switch */ /*** Hash switch temporarily removed best = 077777; poctab = getblk(((ncase+2)/2) * sizeof(*poctab)); for (i=ncase/4; i<=ncase/2; i++) { for (j=0; jswval, i)]++; worst = 0; for (j=0; jworst) worst = poctab[j]; if (i*worst < best) { tabs = i; best = i*worst; } } i = isn++; printf(hashsw, tabs, isn, i, i, ree->op = ULSH; tree->tr2->value = -i; ***/ tree->op = RSHIFT; break; case ASDIV: /*** tree->op = ASULSH; tree->tr2->value = -i; ***/ tree->op = ASRSH; break; case MOD: tree->op = AND; tree->tr2->value = (1<op = ASAND; tree->tr2->value = (1<op]&RELAT) { isrel++; op = tree->op; } else op = NEQUAL; if (!cond) op = notrel[op-EQUAL]; xl1 = xlab1; xl2 = xlab2; xo = xop; xlab1 = lbl; xlab2 = 0; xop = op; xz = xzero; xzero = !isrel || tree->tr2->op==ITOL && tree->tr2->tr1->op==CON && tree->tr2->tr1->value==0; if (tree->op==ANDN) { tree->op = TAND; tree->tr2 = nerror++; flush(); f = fout; fout = 1; printf("%d: ", line); printf(s, p1, p2, p3, p4, p5, p6); putchar('\n'); flush(); fout = f; } psoct(an) { register int n, sign; sign = 0; /***/ if ((n = an) < 0 && n >= -0177777) { /*** Interdata CAL bug ***/ n = -n; sign = '-'; } #ifdef HALFW /***/ printf("%cx'%x'", sign, n); #endif #ifndef HALFW /***/ printf("%cy'%x'", sign, n); #endif } /* * Read in an intermediate file. */ getree() { LTYPE itol(); /***/ static struct tnode *expstack[20]; regid\n\tends\n", s, t); #else /***/ sdata(); /***/ printf(" entry %s\n%s\tequ\t*", s, s); /***/ printf(" %d bytes\n", t); /***/ if (t1 = t/(8*NCPW)) /***/ printf(" do %d\n dc 0,0,0,0,0,0,0,0\n", t1); /***/ t =% 8*NCPW; /***/ if (t1 = t/NCPW) { /***/ for (printf(" dc 0"); --t1; ) /***/ printf(",0"); /***/ putchar('\n'); /***/ } /***/ if (t =% NCPW) { /***/ for (printf(" db 0"); --t; ) /***/ printf(",0"); /***/ putchar('\n'); /***/ } #endif break; case SSPACE: #ifdef unix /***/ printf("\tds\t%d\n", getw(ascbuf)); #else /***/ printf("\tdo\t%d\n\tdb\t0\n", getw(ascbuf)); #endif break; case EVEN: /***/ printf(" align adc\n"); break; case SAVE: /***/ fautolen++; /***/ pstack = 2; /***/ ntemp = maxtemp = 2; /***/ printf("\tsai\tsp,L.%d\n\tstm\tr8,L.%d-%d(sp)\n", /***/ fautolen, fautolen, 8*NCPW); /***/ printf("\tldar\tr14,sp\n"); break; case SETSTK: /***/ t = getw(ascbuf)+NCPW*maxtemp; /***/ printf("L.%d equ %d\n", fautolen, t); break; case PROFIL: /***/ t = gscbuf); op = getw(ascbuf); if (t==0 && op>=0 || t == -1 && op<0) { *sp++ = tnode(ITOL, LONG, tconst(op)); break; } lp = getblk(sizeof(*lp)); lp->op = LCON; lp->type = LONG; lp->lvalue = itol(t, op); *sp++ = lp; break; case FCON: t = getw(ascbuf); outname(numbuf); fp = getblk(sizeof(*fp)); fp->op = FCON; fp->type = t; fp->value = isn++; fp->fvalue = atof(numbuf); *sp++ = fp; break; case FSEL: *sp = tnode(FSEL, getw(ascbuf), *--sp, NULL); t = getw(ascbuf); (char *instab[] { 14,"d",0, 30,"a",0, 31,"s",0, 32,"a",0, 33,"s",0, 35,"ldai",0, 37,"s",0, 38,"x",0, 40,"a",0, 41,"s",0, 42,"m",0, 43,"d",0, 44,"d",0, 45,"sral",0, 46,"slal",0, 47,"n","t", 48,"o",0, 49,"x",0, 60,"c","cl", 61,"c","cl", 62,"c","cl", 63,"c","cl", 64,"c","cl", 65,"c","cl", 66,"cl","cl", 67,"cl","cl", 68,"cl","cl", 69,"cl","cl", 70,"a",0, 71,"s",0, 72,"m",0, 73,"d",0, 74,"d",0, 75,"sral",0, 76,"slal",0, 77,"n",0, 78,"o",0, dc 106,load dc 0 pure * incaft,decaft incaft: %r,c F IB2 A1,A2 %a,c F ldar rf,R IB2 rf,A2 stB1 rf,A1 %e*,c F1* lB1 R,#1(R1) ldar rf,R IB2 rf,A2 stB1 rf,#1(R1) %n*,c F2* lB1 rf,#1(R) P- sta rf,P IB2 rf,A2 stB1 rf,#1(R) lda R,P+ * minus unary negg: %aw,n %af,n sBFr R*,R* IB1 R*,A1 %ew*,n F1* sBFr R*,R* IB1 R*,#1(R1) %nf*,n F2* sBFr R*,R* sB1 R*,#1(R) %e,n F1 sBFr R*,R* IBFr R*,R1* %n,n FS sBFr R,R Ia R,P+ %nf,n FS sBFr R*,R* IBF R*,P+ * complement compl: %aw,n lcs R,1 IlB2 rf,A2 Iar R-,rf ldar A1,R %r,aw F IB2 R-,A2 ldar A1,R %r,e F S1 Iar R-,R1 ldar A1,R %r,n SS F Ia R-,P+ ldar A1,R %a,c F lB2 rf,A2 Iar R-,rf stB1 R,A1 %a,aw F IB2 R-,A2 stB1 R,A1 %a,e F S1 Iar R-,R1 stB1 R,A1 %a,n SS F Ia R-,P+ stB1 R,A1 %e*,c F1* lB1 R,#1(R1) IB2 R-,A2 stB1 R,#1(R1) %e*,n SS F1* lB1 R,#1(R1) Ia R-,P+ stB1 R,#1(R1) %n*,c SS F* ldar rf,R lB1 R,#1(rf) Ia R-,P+ stB1 R,#1(rf) %n*,aw F* ldar R1,R lB1 R,#1(R1) IB2 R-,A2 stB1 R,#1(R1) %n*,n SS F* ldar stB1 R,A1 %a,n SS F lda rf,P+ I R,0(rf) stB1 R,A1 %n*,c F* ldar rf,R lB1 R,#1(rf) I R,A2 stB1 R,#1(rf) %n*,r F* ldar rf,R lB1 R,#1(rf) I R,0(A2) stB1 R,#1(rf) %n*,e F* S1 ldar rf,R lB1 R,#1(rf) I R,0(R1) stB1 R,#1(rf) %n*,n SS F* ldar rf,R lB1 R,#1(rf) lda R1,P+ I R,0(R1) stB1 R,#1(rf) * assign assign: %r,n S ldar A1,R %a,n %af,nf S stB1 R*,A1 %e*,n %ef*,nf S F1* stB1 R*,#1(R1) %n*,n %nf*,nf SS F* ldar rf,R lBF R*,P+ stB1 R*,#1(rf) * integer -> float itof: %n,n F flr Retw(ascbuf); /***/ printf("\tla\tr1,L%d\n\tbal\trf,mcount\n", t); #ifdef unix /***/ printf(" bss\nL%d\tdas\t1\n pure\n", t); #else /***/ sdata(); /***/ printf("L%d\tdas\t1\n", t); /***/ stext(); #endif break; case SNAME: t = outname(s); /***/ printf("* %s = L%d\n", t, getw(ascbuf)); break; case ANAME: t = outname(s); /***/ printf("* %s = %d\n", t, getw(ascbuf)); break; case RNAME: t = outname(s); /***/ printf("* %s = r%d\n", t, getw(ascbuf)); break; case SWIT: t = getw(ascb*sp++)->tr2 = tnode(COMMA, INT, tconst(getw(ascbuf)), tconst(t)); break; case NULLOP: *sp++ = tnode(0, 0, NULL, NULL); break; case LABEL: label(getw(ascbuf)); break; case NLABEL: t = outname(s); /***/ printf("%s equ *\n", t); break; case RLABEL: t = outname(s); /***/ printf(" title %s\n%s\tequ\t*\n", t, t); break; case BRANCH: branch(getw(ascbuf), 0); break; case SETREG: /*** nreg = getw(ascbuf)-1; ***/ getw(ascbuf); break; default: if (opdope[op]&BINARY) { i 79,"x",0, 80,"st",0, 98,"bal",0, 99,"bal",0, 102,"b",0, 106,"l",0, 260,"c","cl", 261,"c","cl", 262,"c","cl", 263,"c","cl", 264,"c","cl", 265,"c","cl", 266,"c","cl", 267,"c","cl", 268,"c","cl", 269,"c","cl", 0 }; char *brtab[] { 60,"be","bne", 61,"bne","be", 62,"bnp","bp", 63,"bl","bnl", 64,"bnl","bl", 65,"bp","bnp", 66,"bnp","bp", 67,"bl","bnl", 68,"bnl","bl", 69,"bp","bnp", 260,"be","bne", 261,"bne","be", 262,"bnp","bp", 263,"bm","bnm", 264,B1 R,A1 %ew*,n F1* lcs R,1 IB1 R,#1(R1) %n,n F Iai R,-1 * plus,minus, and, or, exor plus: %[ADD1] %n,aw %nf,af F IB2 R*,A2 %[ADD2] %n,ew* %nf,ef* F S1* IB2 R*,#2(R1) %[ADD4] %n,e %nf,ef F S1 IBFr R*,R1* %[ADD5] %n,n %nf,nf SS F IBF R*,P+ * times times: %n,c F lB2 rf,A2 Iar R-,rf %n,aw F IB2 R-,A2 %n,ew* F S1* Ia R-,#2(R1) %n,e F S1 Iar R-,R1 %n,n SS F Ia R-,P+ %nf,af % [ADD1] %nf,nf* % [ADD2] %nf,ef % [ADD4] %nf,nf % [ADD5] * divide,mod divide: %n,c F lB2 rf,A2 T I rf,R lB1 R,#1(rf) Ia R-,P+ stB1 R,#1(rf) %af,af % [ADDA1] %af,ef* % [ADDA2] %af,ef % [ADDA3] %af,nf % [ADDA4] %ef*,af % [ADDE1] %ef*,ef % [ADDE3] %ef*,nf % [ADDE4] * asdiv,asmod asdiv: %r,c F T lB2 rf,A2 Iar R-,rf ldar A1,R: %r,aw F T IB2 R-,A2 ldar A1,R: %r,n SS F T Ia R-,P+ ldar A1,R: %a,c F T lB2 rf,A2 Iar R-,rf stB1 R:,A1 %a,aw F T IB2 R-,A2 stB1 R:,A1 %a,n SS F T Ia R-,P+ stB1 R:,A1 %n*,c SS F* ldar rf,R lB1 R,#1(rf) T Ia R-,P+ stB1 R:,#1(rf) %n*,R * float -> integer ftoi: %nf,n F fxr R,R* * call1,call2 call: %a,n I rf,A1 %n*,n F2* I rf,#1(R) %n,n F Ir rf,R * jump jump: %a,n I A1 %n,n F2* I #1(R) * load load: %a,n %af,n IB1 R*,A1 %n*,n %nf*,n F2* IB1 R*,#1(R) * load address amper: %a,n %af,n I R,A1 * field assignment - rhs already shifted & masked fsela: %a,aw F nai R,Z oB2 R,A2 stB1 R,A1 %a,ew* F S1* nai R,Z oB2 R,#2(R1) stB1 R,A1 %a,n S lB1 rf,A1 nai rf,Z oar R,rf stB1 R,A1 %e*,aw F1* lB1 R,#1(R1) nai R,Z oB2 Ruf); line = getw(ascbuf); curbase = funcbase; while(swp=getblk(sizeof(*swp)), swp->swlab = getw(ascbuf)) swp->swval = getw(ascbuf); pswitch(funcbase, swp, t); break; case CBRANCH: lbl = getw(ascbuf); cond = getw(ascbuf); case EXPR: line = getw(ascbuf); if (sp != &expstack[1]) { error("Expression input botch"); exit(1); } nstack = 0; /***/ printf("*@%d\n", line); *sp = optim(*--sp); if (lbl) cbranch(*sp, lbl, cond, 0); else rcexpr(*sp, efftab, 0); curbase = fuf (sp < &expstack[1]) { error("Binary expression botch"); exit(1); } t = *--sp; *sp++ = tnode(op, getw(ascbuf), *--sp, t); } else { sp[-1] = tnode(op, getw(ascbuf), sp[-1]); } break; } } } outname(s) { register char *p, c; register n; p = s; n = 0; while (c = getc(ascbuf)) { #ifndef unix /*** *** Change '_' within names to '.' to make legal Interdata *** CAL identifiers ***/ /***/ if (c == '_') /***/ c = '.'; #endif *p++ = c; n++; } do { *p++ = 0; } "bnm","bm", 265,"bp","bnp", 266,"bnp","bp", 267,"bm","bnm", 268,"bnm","bm", 269,"bp","bnp", 0 }; ar R-,rf %n,aw F T IB2 R-,A2 %n,ew* F S1* T Ia R-,#2(R1) %n,e F S1 T Iar R-,R1 %n,n SS F T Ia R-,P+ %nf,af % [ADD1] %nf,nf* % [ADD2] %nf,ef % [ADD4] %nf,nf % [ADD5] * rshift,lshift rshift: %n,c F I R,A2 %n,r F I R,0(A2) %n,e F S1 I R,0(R1) %n,n SS F lda rf,P+ I R,0(rf) * asplus,asminus, assand, asor, asxor, incbef, decbef asplus: %r,aw F IB2 R,A2 ldar A1,R %r,ew* F S1* IB2 R,#2(R1) ldar A1,R %r,e F S1 Iar R,R1 ldar A1,R %r,n SS F Ia R,P+ ldar A1,R %[ADDA1] %a,aw*,aw F* ldar rf,R lB1 R,#1(rf) T IB2 R-,A2 stB1 R:,#1(rf) %n*,n SS F* ldar rf,R lB1 R,#1(rf) T Ia R-,P+ stB1 R:,#1(rf) %af,af % [ADDA1] %af,ef* % [ADDA2] %af,ef % [ADDA3] %af,nf % [ADDA4] %ef*,af % [ADDE1] %ef*,ef % [ADDE3] %ef*,nf % [ADDE4] * aslsh,asrsh asrsh: %r,c F I R,A2 ldar A1,R %r,r F I R,0(A2) ldar A1,R %r,e F S1 I R,0(R1) ldar A1,R %r,n SS F lda rf,P+ I R,0(rf) ldar A1,R %a,c F I R,A2 stB1 R,A1 %a,r F I R,0(A2) stB1 R,A1 %a,e F S1 I R,0(R1),A2 stB1 R,#1(R1) %e*,n S F1* lB1 rf,#1(R1) nai rf,Z oar R,rf stB1 R,#1(R1) entry cctab impur align adc cctab equ * dc 30,cmisc dc 31,cmisc dc 37,cmisc dc 38,cmisc dc 40,cmisc dc 41,cmisc dc 45,cmisc dc 46,cmisc dc 47,tand dc 48,cmisc dc 51,cmisc dc 52,cmisc dc 49,cmisc dc 60,equal dc 61,equal dc 62,equal dc 63,equal dc 64,equal dc 65,equal dc 66,equal dc 67,equal dc 68,equal dc 69,equal dc 70,cmisc dc 71,cmisc dc 77,cmisc dc 78,cmisc dc 79,cmisc dc 80,cassign dc 1ncbase; break; case NAME: t = getw(ascbuf); if (t==EXTERN) { np = getblk(sizeof(*xnp)); np->type = getw(ascbuf); outname(np->name); } else { np = getblk(sizeof(*np)); np->type = getw(ascbuf); np->nloc = getw(ascbuf); } np->op = NAME; np->class = t; np->regno = 0; np->offset = 0; *sp++ = np; break; case CON: getw(ascbuf); /* ignore type, assume int */ *sp++ = tconst(getw(ascbuf)); break; case LCON: getw(ascbuf); /* ignore type, assume long */ t = getw(awhile (n++ < 8); return(s); } stext() { #ifndef HALFW /***/ printf(" pure\n"); #endif } sdata() { #ifndef HALFW /***/ printf(" impur\n"); #endif } entry regtab impur align adc regtab equ * dc 14,divide dc 16,fsela dc 30,asplus dc 31,asplus dc 32,incaft dc 33,incaft dc 35,amper dc 37,negg dc 38,compl dc 40,plus dc 41,plus dc 42,times dc 43,divide dc 44,divide dc 45,rshift dc 46,rshift dc 47,plus dc 48,plus dc 49,plus dc 51,itof dc 52,ftoi dc 70,asplus dc 71,asplus dc 72,astimes dc 73,asdiv dc 74,asdiv dc 75,asrsh dc 76,asrsh dc 77,asplus dc 78,asplus dc 79,asplus dc 80,assign dc 98,call dc 99,call dc 102,jump %af,af F IB2 R*,A2 stB1 R*,A1 %[ADDA2] %a,ew* %af,ef* F S1* IB2 R*,#2(R1) stB1 R*,A1 %[ADDA3] %a,e %af,ef F S1 IBFr R*,R1* stB1 R*,A1 %[ADDA4] %a,n %af,nf SS F IBF R*,P+ stB1 R*,A1 %[ADDE1] %e*,aw %ef*,af F1* lB1 R*,#1(R1) IB2 R*,A2 stB1 R*,#1(R1) %[ADDE3] %e*,e %ef*,ef F* S1 ldar rf,R lB1 R*,#1(rf) IBFr R*,R1* stB1 R*,#1(rf) %[ADDE4] %e*,n %ef*,nf SS F1* lB1 R*,#1(R1) IBF R*,P+ stB1 R*,#1(R1) %n*,n SS F* ldar rf,R lB1 R,#1(rf) Ia R,P+ stB1 R,#1(rf) * astimes astimes: %r,c F dSY_eTZ`U[aghnt06,cload dc 260,equal dc 261,equal dc 262,equal dc 263,equal dc 264,equal dc 265,equal dc 266,equal dc 267,equal dc 268,equal dc 269,equal dc 0 pure * relationals equal: %c,c F IB2 R,A2 %r,z ldar A1,A1 %r,aw IB2 A1,A2 %r,a I'B2 A1,A2 %r,nw* S2* IB2 A1,#2(R) %r,n* S2* I'B2 A1,#2(R) %r,n S Iar A1,R %aw,z F %nw*,z F2* lda R,#1(R) %n,z F ldar R,R %n,aw %nf,af % [ADD1] %n,ew* % [ADD2] %nf,nf* % [ADD2] %n,ew %nf,ef % [ADD4] %n,a F I'B2 R,A2 %n,e* F S1* I'B2 R,#2(R1) %n,n %nf,nf % [ADD5] * assignment cassign: %[ASS1] %r,aw lB2 A1,A2 %[ASS2] %r,nw* S2* lB2 A1,#2(R) %r,n H * test value cload: %aw,n %af,n %nw*,n %nf*,n H * 'and' for condition code only tand: %r,c I'B2 A1,A2 %aw,c S IB1 R,A1 %n,n H * ops for which regtab sets the condition code correctly cmisc: %n,n %nf,nf H entry efftab impur align adc efftab equ * dc 30,easplus dc 31,edec dc 32,easplus dc 33,edec dc 70,easplus dc 71,edec dc 75,easrsh dc 76,easrsh dc 77,edec dc 78,edecor("Illegal storage class"); do { defsym = 0; paraml = 0; parame = 0; if (sclass==TYPEDEF) { decl1(TYPEDEF, &typer, 0, NULL); continue; } decl1(EXTERN, &typer, 0, NULL); if ((ds=defsym)==0) return; funcsym = ds; if ((ds->type&XTYPE)==FUNC) { if ((peeksym=symbol())==LBRACE || peeksym==KEYW || (peeksym==NAME && csym->hclass==TYPEDEF)) { funcblk.type = decref(ds->type); setinit(ds); #ifndef unix strflg++; #endif outcode("BS", SYMDEF, sclass==EXTERN?ds->name:""; label(sloc+1); ***/ retlab = isn++; blklev = 0; if ((peeksym = symbol()) != LBRACE) error("Compound statement required"); statement(); outcode("BNB", LABEL, retlab, RETRN); /*** label(sloc); ***/ outcode("BN", SETSTK, -maxauto); /*** branch(sloc+1); ***/ if (cb < maxdecl) cb = maxdecl; curbase = funcbase = cb; } /* * Process the initializers for an external definition. */ cinit(anp, flex, sclass) struct hshtab *anp; { register struct phshtab *np; register nel, ninit; int width, isarrait =+ nchstr; o = symbol(); break; } else if (np->type==STRUCT) strinit(np, sclass); else if ((np->type&ARRAY)==ARRAY || peeksym==LBRACE) cinit(np, 0, sclass); else { initflg++; s = tree(); initflg = 0; if (np->hflag&FFIELD) error("No field initialization"); *cp++ = nblock(np); *cp++ = s; build(ASSIGN); if (sclass==AUTO||sclass==REG) rcexpr(*--cp); else rcexpr(block(INIT,np->type,NULL,NULL,(*--cp)->tr2)); } ninit++; } while ((o=symbol())==COMMA & /* * Process one statement in a function. */ statement() { register o, o1, o2; int o3; struct tnode *np; int sauto, sreg; stmt: switch(o=symbol()) { case EOF: error("Unexpected EOF"); case SEMI: return; case LBRACE: sauto = autolen; sreg = regvar; blockhead(); while (!eof) { if ((o=symbol())==RBRACE) { autolen = sauto; if (sreg!=regvar) outcode("BN", SETREG, sreg); regvar = sreg; blkend(); return; } peeksym = o; statement(); } error("Missing+; label(o3 = isn++); statement(); label(contlab); contlab = o1; if ((o=symbol())==KEYW && cval==WHILE) { cbranch(tree(), o3, 1); label(brklab); brklab = o2; goto semi; } goto syntax; case CASE: o1 = conexp(); if ((o=symbol())!=COLON) goto syntax; if (swp==0) { error("Case not in switch"); goto stmt; } if(swp>=swtab+SWSIZ) { error("Switch table overflow"); } else { swp->swlab = isn; (swp++)->swval = o1; label(isn++); } dc 79,edec dc 80,eassign dc 0 pure * asplus, incaft, incbef easplus: %[EAS1] %r,aw IB2 A1,A2 %[EAS2] %r,nw* S2* IB2 A1,#2(R) %[EAS3] %r,n S Iar A1,R %[EAS4] %aw,c S IB1m R,A1 %aw,r IB1m A2,A1 %aw,n % [EAS4] %a,aw % [ADDA1] %nw*,c F2* lB2 rf,A2 IB1m rf,#1(R) %nw*,r F2* IB1m A2,#1(R) %ew*,n S F1* IB1m R,#1(R1) %nw*,e F2* S1 IB1m R1,#1(R) %[EAS5] %n*,aw F2* lB1 rf,#1(R) IB2 rf,A2 stB1 rf,#1(R) * decbef, decaft, asminus, asor, etc. edec: %r,aw % [EAS1] %r,nw* % [EAS2] %r,n % [EA); #ifndef unix strflg = 0; #endif cfunc(); return; } if (paraml) error("Inappropriate parameters"); } else if ((o=symbol())==COMMA || o==SEMI) { peeksym = o; o = (length(ds)+ALIGN) & ~ALIGN; if (sclass==STATIC) { setinit(ds); outcode("BSBBSBN", SYMDEF, "", BSS, NLABEL, ds->name, SSPACE, o); } else if (scflag) { /*** *** only allow one external definition *** unless '-m' flag specified ***/ /***/ if (!mflag) { /***/ setinit(ds); /***/ y, o, brace, realtype, *cb; struct tnode *s; cb = funcbase; np = gblock(sizeof(*np)); funcbase = curbase; cpysymb(np, anp); realtype = np->type; isarray = 0; if ((realtype&XTYPE) == ARRAY) isarray++; else flex = 0; width = length(np); nel = 1; /* * If it's an array, find the number of elements. * temporarily modify to look like kind of thing it's * an array of. */ if (sclass==AUTO) if (isarray || realtype==STRUCT) error("No auto. aggregate initialization"); if (isarray) { n& (ninitnel) { if (flex && nel==0) { np->subsp[-1] = ninit; } else error("Too many initializers: %.8s", anp->name); nel = ninit; } curbase = funcbase = cb; return(nel*wi '}'"); return; case KEYW: switch(cval) { case GOTO: if (o1 = simplegoto()) branch(o1); else dogoto(); goto semi; case RETURN: doret(); goto semi; case IF: np = pexpr(); o2 = 0; if ((o1=symbol())==KEYW) switch (cval) { case GOTO: if (o2=simplegoto()) goto simpif; cbranch(np, o2=isn++, 0); dogoto(); label(o2); goto hardif; case RETURN: if (nextchar()==';') { o2 = retlab; goto simpif; } cbranch(np, o1=isn++, goto stmt; case SWITCH: o1 = brklab; brklab = isn++; np = pexpr(); chkw(np, -1); rcexpr(block(RFORCE,0,NULL,NULL,np)); pswitch(); brklab = o1; return; case DEFAULT: if (swp==0) error("Default not in switch"); if (deflab) error("More than 1 'default'"); if ((o=symbol())!=COLON) goto syntax; label(deflab = isn++); goto stmt; case FOR: o1 = contlab; o2 = brklab; contlab = isn++; brklab = isn++; if (o=forstmt()) goto syntax; laS3] %a,aw % [ADDA1] %n*,c % [EAS5] * aslsh, asrsh easrsh: %r,c I A1,A2 %r,r I A1,0(A2) %r,n S2 I A1,0(R) * assign eassign: %r,a % [ASS1] %r,n* % [ASS2] %r,n S ldar A1,R %a,c S stB1 R,A1 %n*,c F2* lB2 rf,A2 stB1 rf,#1(R) %a,r stB1 A2,A1 %n*,r F2* stB1 A2,#1(R) entry sptab impur align adc sptab equ * dc 106,sload dc 0 pure * put register variable on stack sload: %c,n F stBF R,P %r,n stBF A1,P outcode("BBSBSBN", BSS, SYMDEF, /***/ ds->name, NLABEL, ds->name, SSPACE, o); /***/ } else /***/ outcode("BSN", CSPACE, ds->name, o); } } else { if (o!=ASSIGN) peeksym = o; setinit(ds); if (sclass==EXTERN) outcode("BS", SYMDEF, ds->name); outcode("BBS", DATA, NLABEL, ds->name); cb = funcbase; if (cinit(ds, 1, sclass) & ALIGN) outcode("B", EVEN); if (maxdecl > cb) cb = maxdecl; funcbase = cb; } } while ((o=symbol())==COMMA); if (o==SEMI) return; p->type = decref(realtype); np->subsp++; if (width==0 && flex==0) error("0-length row: %.8s", anp->name); o = length(np); nel = (unsigned)width / o; width = o; } brace = 0; if ((peeksym=symbol())==LBRACE && (isarray || np->type!=STRUCT)) { peeksym = -1; brace++; } ninit = 0; do { if ((o=symbol())==RBRACE) break; peeksym = o; if (o==STRING && realtype==ARRAY+CHAR) { if (sclass==AUTO) error("No strings in automatic"); peeksym = -1; putstr(0, flex?10000:nel); nindth); } /* * Initialize a structure */ strinit(np, sclass) struct tnode *np; { register struct hshtab **mlp; static zerloc; register int o, brace; if ((mlp = np->strp->memlist)==NULL) { mlp = &zerloc; error("Undefined structure initialization"); } brace = 0; if ((o = symbol()) == LBRACE) brace++; else peeksym = o; do { if ((o=symbol()) == RBRACE) break; peeksym = o; if (*mlp==0) { error("Too many structure initializers"); cinit(&funcblk, 0, sclass); } else cinit(*mlp0); doret(); label(o1); o2++; goto hardif; case BREAK: o2 = brklab; goto simpif; case CONTIN: o2 = contlab; simpif: chconbrk(o2); cbranch(np, o2, 1); hardif: if ((o=symbol())!=SEMI) goto syntax; if ((o1=symbol())==KEYW && cval==ELSE) goto stmt; peeksym = o1; return; } peeksym = o1; cbranch(np, o1=isn++, 0); statement(); if ((o=symbol())==KEYW && cval==ELSE) { o2 = isn++; branch(o2); label(o1); statemebel(brklab); contlab = o1; brklab = o2; return; case ELSE: error("Inappropriate 'else'"); statement(); return; } error("Unknown keyword"); goto syntax; case NAME: if (nextchar()==':') { peekc = 0; o1 = csym; if (o1->hclass>0) { if (o1->hblklev==0) { pushdecl(o1); o1->hoffset = 0; } else { defsym = o1; redec(); goto stmt; } } o1->hclass = STATIC; o1->htype = ARRAY; o1->hflag =| FLABL; if (o1->hoffset==0) o1->hoffs# /* C compiler * * */ #include "c0.h" /* * Process a single external definition */ extdef() { register o; int sclass, scflag, *cb; struct hshtab typer; register struct hshtab *ds; if(((o=symbol())==EOF) || o==SEMI) return; peeksym = o; sclass = 0; blklev = 0; if (getkeywords(&sclass, &typer)==0) { sclass = EXTERN; if (peeksym!=NAME) goto syntax; } scflag = 0; if (sclass==DEFXTRN) { scflag++; sclass = EXTERN; } if (sclass!=EXTERN && sclass!=STATIC && sclass!=TYPEDEF) errsyntax: if (o==RBRACE) { error("Too many }'s"); peeksym = 0; return; } error("External definition syntax"); errflush(o); statement(); } /* * Process a function definition. */ cfunc() { register int *cb; register sloc; /*** sloc = isn; isn =+ 2; ***/ outcode("BBS", PROG, RLABEL, funcsym->name); cb = curbase; /***/ regvar = 14; autolen = STAUTO; maxauto = STAUTO; blklev = 1; declist(ARG); outcode("B", SAVE); if (proflg) outcode("BN", PROFIL, isn++); funchead(); /*** branch(sloc)ziou{jpvkqw}lrx~msy++, 0, sclass); if (*mlp == &structhole) { outcode("B", EVEN); mlp++; } } while ((o=symbol())==COMMA && (*mlp || brace)); if (sclass!=AUTO && sclass!=REG) { if (*mlp) outcode("BN", SSPACE, np->strp->ssize - (*mlp)->hoffset); outcode("B", EVEN); } if (o!=RBRACE || brace==0) peeksym = o; } /* * Mark already initialized */ setinit(anp) struct hshtab *anp; { register struct hshtab *np; np = anp; if (np->hflag&FINIT) error("%s multiply defined", np->name); np->hflag =| FINIT; } nt(); label(o2); return; } peeksym = o; label(o1); return; case WHILE: o1 = contlab; o2 = brklab; label(contlab = isn++); cbranch(pexpr(), brklab=isn++, 0); statement(); branch(contlab); label(brklab); contlab = o1; brklab = o2; return; case BREAK: chconbrk(brklab); branch(brklab); goto semi; case CONTIN: chconbrk(contlab); branch(contlab); goto semi; case DO: o1 = contlab; o2 = brklab; contlab = isn++; brklab = isn+et = isn++; label(o1->hoffset); goto stmt; } } peeksym = o; rcexpr(tree()); semi: if ((o=symbol())==SEMI) return; syntax: error("Statement syntax"); errflush(o); } /* * Process a for statement. */ forstmt() { register int l, o, sline; int sline1, *ss; struct tnode *st; if ((o=symbol()) != LPARN) return(o); if ((o=symbol()) != SEMI) { /* init part */ peeksym = o; rcexpr(tree()); if ((o=symbol()) != SEMI) return(o); } label(contlab); if ((o=symbol()) != SEMI) { /* test part */ peeksym = o; cbranch(tree(), brklab, 0); if ((o=symbol()) != SEMI) return(o); } if ((peeksym=symbol()) == RPARN) { /* incr part */ peeksym = -1; statement(); branch(contlab); return(0); } l = contlab; contlab = isn++; st = tree(); sline = line; if ((o=symbol()) != RPARN) return(o); ss = funcbase; funcbase = curbase; statement(); sline1 = line; line = sline; label(contlab); rcexpr(st); line = sline1; if (ss < maxdecl) ss = maxdecl; curbase = funcbase = ss; br>htype&XTYPE) == ARRAY) { cs->htype =- (ARRAY-PTR); /* set ptr */ cs->subsp++; /* pop dims */ } pl =+ rlength(cs); if (cs->hclass==AREG && (hreg.hoffset=goodreg(cs))>=0) { bstack[0] = &areg; bstack[1] = nblock(cs); cp = &bstack[2]; areg.type = cs->htype; cs->hclass = AUTO; build(ASSIGN); rcexpr(bstack[0]); cs->hoffset = hreg.hoffset; cs->hclass = REG; } else cs->hclass = AUTO; prste(cs); } for (cs=hshtab; csname[0] == '\0') cs); } /* * write out special definitions of local symbols for * benefit of the debugger. None of these are used * by the assembler except to save them. */ prste(acs) struct hshtab *acs; { register struct hshtab *cs; register nkind; cs = acs; switch (cs->hclass) { case REG: nkind = RNAME; break; case AUTO: nkind = ANAME; break; case STATIC: nkind = SNAME; break; default: return; } outcode("BSN", nkind, cs->name, cs->hoffset); } /* * In case of error, skip to the next * (1); } if((fin=open(argv[1],0))<0) { error("Can't find %s", argv[1]); exit(1); } if (fcreat(argv[2], obuf)<0 || fcreat(argv[3], sbuf)<0) { error("Can't create temp"); exit(1); } /***/ while (argc>4 && argv[4][0] == '-') { /***/ if ((i=argv[4][1]) == 'p') /***/ proflg++; /***/ else if (i == 'm') /***/ mflag++; /***/ else /***/ break; /***/ /***/ argv++; argc--; /***/ } /* * The hash table locations of the keywords * are marked; if an identifier hashes to one of * these locationsblklev = blklev; sp = symbuf; for (np=rp->name; spkwname); kp++) { p1 = wp; while (*p1 == *p2++) if (*p1++ == '\0') { cval = kp->kwval; return(1); } } *wp = firstc; retunore newlines */ inhdr = 1; c = getchar(); goto loop; case NEWLN: if (!inhdr) line++; inhdr = 0; case SPACE: c = getchar(); goto loop; case EOF: eof++; return(0); case PLUS: return(subseq(c,PLUS,INCBEF)); case MINUS: return(subseq(c,subseq('>',MINUS,ARROW),DECBEF)); case ASSIGN: c = spnextchar(); peekc = 0; if (c=='=') return(EQUAL); if (c==' ') return(ASSIGN); if (c=='<' || c=='>') { if (spnextchar() != c) { peeksym = ctab[c]; return(ASSIGN); anch(l); return(0); } /* * A parenthesized expression, * as after "if". */ struct tnode * pexpr() { register o, t; if ((o=symbol())!=LPARN) goto syntax; t = tree(); if ((o=symbol())!=RPARN) goto syntax; return(t); syntax: error("Statement syntax"); errflush(o); return(0); } /* * The switch statement, which involves collecting the * constants and labels for the cases. */ pswitch() { register struct swtab *cswp, *sswp; int dl, swlab; cswp = sswp = swp; if (swp==0) cswp = swp = swt continue; if (cs->hclass == ARG || cs->hclass==AREG) error("Not an argument: %.8s", cs->name); } outcode("BN", SETREG, regvar); } blockhead() { register r; r = regvar; blklev++; declist(0); if (r != regvar) outcode("BN", SETREG, regvar); } /* * After the end of a block, delete local * symbols; save those that are external. * Also complain about undefined labels. */ blkend() { register struct hshtab *cs, *ncs; struct hshtab *endcs; register i; blklev--; for (cs=hshtab; cs->name[0statement delimiter. */ errflush(ao) { register o; o = ao; while(o>RBRACE) /* ; { } */ o = symbol(); peeksym = o; } , it is looked up in in the keyword * table first. */ for (ip=kwtab; (sp = ip->kwname); ip++) { i = 0; while (*sp) i =+ *sp++; hshtab[i%HSHSIZ].hflag = FKEYW; } coremax = funcbase = curbase = sbrk(0); while(!eof) extdef(); outcode("B", EOF); strflg++; /*** *** Write external definitions for undefined extrns ***/ /***/ for (cs=hshtab; csname[0] && cs->hclass==EXTERN && !(cs->hflag&FINIT)) /***/ outcode("BS", GLOBAL, cs->name); /*** *** If profirn(0); } /* * Return the next symbol from the input. * peeksym is a pushed-back symbol, peekc is a pushed-back * character (after peeksym). * mosflg means that the next symbol, if an identifier, * is a member of structure or a structure tag, and it * gets a "." prepended to it to distinguish * it from other identifiers. */ symbol() { register c; register char *sp; register tline; if (peeksym>=0) { c = peeksym; peeksym = -1; if (c==NAME) mosflg = 0; return(c); } if (peekc) { c = } peekc = 0; return(c=='<'? ASLSH: ASRSH); } if (ctab[c]>=PLUS && ctab[c]<=EXOR) { if (spnextchar() != ' ' && (c=='-' || c=='&' || c=='*')) { error("Warning: =%c operator assumed", c); nerror--; } c = ctab[c]; return(c+ASPLUS-PLUS); } peekc = c; return(ASSIGN); case LESS: if (subseq(c,0,1)) return(LSHIFT); return(subseq('=',LESS,LESSEQ)); case GREAT: if (subseq(c,0,1)) return(RSHIFT); return(subseq('=',GREAT,GREATEQ)); case EXCLA: return(subseq('=',ab; branch(swlab=isn++); dl = deflab; deflab = 0; statement(); branch(brklab); label(swlab); if (deflab==0) deflab = brklab; outcode("BNN", SWIT, deflab, line); for (; cswp < swp; cswp++) outcode("NN", cswp->swlab, cswp->swval); outcode("0"); label(brklab); deflab = dl; swp = sswp; } /* * funchead is called at the start of each function * to process the arguments, which have been linked in a list. * This list is necessary because in * f(a, b) float b; int a; ... * the names are seen b] && csname[0]) { if (cs->hblklev <= blklev) continue; /*** The test below has been changed since it caused *** EXTERN declarations in inner blocks of functions *** not to be retained to the end of the file. ***/ if ((cs->hclass!=EXTERN /*** || blklev!=0 ***/) && ((cs->hflag&FLABL)==0 || blklev==0)) { if (cs->hclass==0) error("%.8s undefined", cs->name); if ((ncs = cs->hpdown)==NULL) { cs->name[0] = '\0'; hshused-# /* C compiler * * * * Called from cc: * c0 source temp1 temp2 [ -m ] [ -p ] * temp1 gets most of the intermediate code; * strings are put on temp2, which c1 reads after temp1. */ #include "c0.h" int isn 1; int peeksym -1; int line 1; struct tnode funcblk { NAME, 0, NULL, NULL, NULL, NULL }; struct kwtab { char *kwname; int kwval; } kwtab[] { "int", INT, "char", CHAR, "float", FLOAT, "double", DOUBLE, "struct", STRUCT, /***/ "long", INT, "unsigned", UNSIGN, "union", UNION, /***/ "sling is on, we need 'mcount' subroutine as external ***/ /***/ if (proflg) /***/ outcode("BS", GLOBAL, "mcount"); outcode("B", EOF); fflush(obuf); fflush(sbuf); exit(nerror!=0); } /* * Look up the identifier in symbuf in the symbol table. * If it hashes to the same spot as a keyword, try the keyword table * first. An initial "." is ignored in the hash. * Return is a ptr to the symbol table entry. */ lookup() { int ihash; register struct hshtab *rp; register char *sp, *np; ihash = 0; sp =EXCLA,NEQUAL)); case BSLASH: if (subseq('/', 0, 1)) return(MAX); goto unkn; case DIVIDE: if (subseq('\\', 0, 1)) return(MIN); if (subseq('*',1,0)) return(DIVIDE); while ((c = spnextchar()) != EOF) { peekc = 0; if (c=='*') { if (spnextchar() == '/') { peekc = 0; c = getchar(); goto loop; } } } eof++; error("Nonterminated comment"); return(0); case PERIOD: case DIGIT: peekc = c; return(getnum()); case DQUOTE: cval = isn++; return(STRIefore the types. */ /* * Structure resembling a block for a register variable. */ struct hshtab hreg { REG, 0, 0, NULL, NULL, 0 }; struct tnode areg { NAME, 0, NULL, NULL, &hreg}; funchead() { register pl; register struct hshtab *cs; struct tnode *bstack[2]; pl = STARG; while(paraml) { parame->hoffset = 0; cs = paraml; paraml = paraml->hoffset; if (cs->htype==FLOAT) cs->htype = DOUBLE; /***/ if (cs->htype==CHAR || cs->htype==SHORT) /***/ cs->htype = INT; cs->hoffset = pl; if ((cs--; cs->hflag =& ~(FFIELD|FLABL); } else { cpysymb(cs, ncs); } continue; } /* * Retained name; must rehash. */ for (i=0; iname[i]; lookup(); if ((ncs=csym) != cs) { cs->name[0] = '\0'; hshused--; i = ncs->hflag; cpysymb(ncs, cs); ncs->hflag =| i&FKEYW; cs->hflag =& ~(FFIELD|FLABL); } if (ncs->hblklev>1 || (ncs->hblklev>0 && ncs->hclass==EXTERN)) ncs->hblklev--; } while ((cs = (cs<&hshtab[HSHSIZ-1])? ++cs: hshtab) != endhort", SHORT, "auto", AUTO, "extern", EXTERN, "static", STATIC, "register", REG, "goto", GOTO, "return", RETURN, "if", IF, "while", WHILE, "else", ELSE, "switch", SWITCH, "case", CASE, "break", BREAK, "continue", CONTIN, "do", DO, "default", DEFAULT, "for", FOR, "sizeof", SIZEOF, "typedef", TYPEDEF, 0, 0, }; main(argc, argv) char **argv; { extern fin; register char *sp; register i; register struct kwtab *ip; /***/ struct hshtab *cs; if(argc<4) { error("Arg count"); exit symbuf; while (sphflag&FKEYW) if (findkw()) return(KEYW); while (*(np = rp->name)) { for (sp=symbuf; sp= &hshtab[HSHSIZ]) rp = hshtab; } if(++hshused >= HSHSIZ) { error("Symbol table overflow"); exit(1); } rp->hclass = 0; rp->htype = 0; rp->hoffset = 0; rp->subsp = NULL; rp->strp = NULL; rp->hpdown = NULL; rp->h peekc; peekc = 0; } else if (eof) return(EOF); else c = getchar(); loop: switch(ctab[c]) { case SHARP: if ((c=symbol())!=CON) { error("Illegal #"); return(c); } tline = cval; while (ctab[peekc]==SPACE) peekc = getchar(); if (peekc=='"') { sp = filename; while ((c = mapch('"')) >= 0) *sp++ = c; *sp++ = 0; } else if (peekc !='\n') error("Illegal #"); peekc = 0; while (getchar()!='\n' && eof==0); line = tline; return(symbol()); case INSERT: /* igNG); case SQUOTE: return(getcc()); case LETTER: sp = symbuf; while(ctab[c]==LETTER || ctab[c]==DIGIT) { if (sp= 0) if(cc++ < LNCPW) /*** *ccp++ = c; ***/ /***/ cval = (cval<<8) | c; if (cc>LNCPW) error("Long character constant"); /*** if (cc==1) { realc = cval; cval = rea if (cs->hclass==TYPEDEF) goto atype; if (cs->hclass==0 && cs->htype==0) if(nextchar()=='(') { /* set function */ cs->hclass = EXTERN; cs->htype = FUNC; } else { cs->hclass = STATIC; error("%.8s undefined; func. %.8s", cs->name, funcsym->name); if (initflg) { cs->hclass = EXTERN; error("(Warning only)"); nerror =- 2; } } *cp++ = nblock(cs); goto tand; case FCON: *cp++ = fblock(DOUBLE, copnum(cval)); goto tand; case LCON: cs = gblock(siies */ if (andflg==0) goto syntax; andflg = 0; oponst: p = (opdope[o]>>9) & 077; if (initflg && (o==COMMA||(o==COLON && *op!=QUEST))) p = 05; opon1: ps = *pp; if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) { switch (o) { case INCAFT: case DECAFT: p = 37; break; case LPARN: case LBRACK: case CALL: p = 04; } if (op >= &opst[SSIZE-1]) { error("expression overflow"); exit(1); } *++op = o; *++pp = p; goto advanc; } --pp; switch (os = *op--) { case SEOF: peek# /* * C compiler * * */ #include "c0.h" /* * Called from tree, this routine takes the top 1, 2, or 3 * operands on the expression stack, makes a new node with * the operator op, and puts it on the stack. * Essentially all the work is in inserting * appropriate conversions. */ build(op) { register int t1; int t2, t; register struct tnode *p1, *p2; struct tnode *p3; int dope, leftc, cvn, pcvn; /* * a[i] => *(a+i) */ if (op==LBRACK) { build(PLUS); op = STAR; } dope = opdope[op]; then * is tacked on to access the member. */ case ARROW: if (p2->op!=NAME || p2->tr1->hclass!=MOS) { error("Illegal structure ref"); *cp++ = p1; return; } if (t2==INT && p2->tr1->hflag&FFIELD) t2 = UNSIGN; t = incref(t2); chkw(p1, -1); setype(p1, t, p2); *cp++ = block(PLUS,t,p2->subsp,p2->strp,p1,cblock(p2->tr1->hoffset)); build(STAR); if (p2->tr1->hflag&FFIELD) *cp++ = block(FSEL,UNSIGN,NULL,NULL,*--cp,p2->tr1->hstrp); return; } if ((dope&LVALUE)!=0) chklval(p1); <2) + lcval)<<1; else lcval =<< 4; if ('0'<=c && c<='9') c =- '0'; else if ('a'<=c && c<='f') c =- 'a'-10; else c =- 'A'-10; lcval =+ c; ndigit++; continue; } if (c=='.') { if (base==16 || sym==FCON) error(nsyn); sym = FCON; continue; } if (ndigit==0) { sym = DOT; break; } if ((c=='e'||c=='E') && expseen==0) { expseen++; sym = FCON; if (base==16) error(nsyn); *np++ = c = getchar(); if (c!='+'&&c!='-'&&('0'>c||c>'9')) lc; } ***/ return(CON); } /* * Read a character in a string or character constant, * detecting the end of the string. * It implements the escape sequences. */ mapch(ac) { register int a, c, n; static mpeek; c = ac; if (a = mpeek) mpeek = 0; else a = getchar(); loop: if (a==c) return(-1); switch(a) { case '\n': case '\0': error("Nonterminated string"); peekc = a; return(-1); case '\\': switch (a=getchar()) { case 't': return('\t'); case 'n': return('\n'); casezeof(*lcp)); cs->op = LCON; cs->type = LONG; cs->lvalue = lcval; *cp++ = cs; goto tand; case CON: *cp++ = cblock(cval); goto tand; /* fake a static char array */ case STRING: putstr(cval, 0); cs = gblock(sizeof(*cs)); cs->hclass = STATIC; cs->hoffset = cval; *cp++ = block(NAME, ARRAY+CHAR, &nchstr, NULL, cs); tand: if(cp>=cmst+CMSIZ) { error("Expression overflow"); exit(1); } if (andflg) goto syntax; andflg = 1; goto advanc; case KEYW: atype: if (*op !=sym = o; build(0); /* flush conversions */ return(*--cp); case COMMA: if (*op != CALL) os = SEQNC; break; case CALL: if (o!=RPARN) goto syntax; build(os); goto advanc; case MCALL: *cp++ = NULL; /* empty arglist */ os = CALL; break; case INCBEF: case INCAFT: case DECBEF: case DECAFT: *cp++ = cblock(1); break; case LPARN: if (o!=RPARN) goto syntax; goto advanc; case LBRACK: if (o!=RBRACK) goto syntax; build(LBRACK); goto advanc; } build(os); got if ((dope&BINARY)!=0) { p2 = chkfun(disarray(*--cp)); t2 = p2->type; } p1 = *--cp; /* * sizeof gets turned into a number here. */ if (op==SIZEOF) { *cp++ = cblock(length(p1)); return; } if (op!=AMPER) { p1 = disarray(p1); if (op!=CALL) p1 = chkfun(p1); } t1 = p1->type; pcvn = 0; t = INT; switch (op) { case CAST: if ((t1&XTYPE)==FUNC || (t1&XTYPE)==ARRAY) error("Disallowed conversion"); break; /* end of expression */ case 0: *cp++ = p1; return; /* no-conversio if ((dope&LWORD)!=0) chkw(p1, LONG); if ((dope&RWORD)!=0) chkw(p2, LONG); if ((dope&BINARY)==0) { if (op==ITOF) t1 = DOUBLE; else if (op==FTOI) t1 = INT; if (!fold(op, p1, 0)) *cp++ = block(op,t1,p1->subsp,p1->strp,p1); return; } cvn = 0; if (t1==STRUCT || t2==STRUCT) { error("Unimplemented structure operation"); t1 = t2 = INT; } cvn = cvtab[lintyp(t1)][lintyp(t2)]; leftc = (cvn>>4)&017; cvn =& 017; t = leftc? t2:t1; /***/ if ((t==INT||t==CHAR||t==SHORT) && (t1==UNSIGN||tbreak; } else if (c=='x' || c=='X') { if (base!=8 || lcval!=0 || sym!=CON) error(nsyn); base = 16; } else if ((c=='l' || c=='L') && sym==CON) { c = getchar(); sym = LCON; break; } else break; } peekc = c; if (sym==FCON) { np[-1] = 0; cval = np-numbuf; return(FCON); } /*** if (sym==CON && (lcval<0 || lcval>MAXINT&&base==10 || (lcval>>1)>MAXINT)) { sym = LCON; } ***/ cval = lcval; return(sym); } /* * If the next input character is c, return b and advance. * Other 'b': return('\b'); case 'f': return('\014'); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': n = 0; c = 0; while (++c<=3 && '0'<=a && a<='7') { n =<< 3; n =+ a-'0'; a = getchar(); } mpeek = a; return(n); case 'r': return('\r'); case '\n': if (!inhdr) line++; inhdr = 0; a = getchar(); goto loop; } } return(a); } /* * Read an expression and return a pointer to its tree. * It's the classical bottom-up, LPARN || andflg) goto syntax; peeksym = o; *cp++ = xprtype(gblock(sizeof(*xprtype()))); if ((o=symbol()) != RPARN) goto syntax; o = CAST; --op; --pp; if (*op == SIZEOF) { andflg = 1; *pp = 100; goto advanc; } goto oponst; case INCBEF: case DECBEF: if (andflg) o =+ 2; goto oponst; case COMPL: case EXCLA: case SIZEOF: if (andflg) goto syntax; goto oponst; case MINUS: if (!andflg) o = NEG; andflg = 0; goto oponst; case AND: case TIMES: if (o opon1; syntax: error("Expression syntax"); errflush(o); return(0); } struct hshtab * xprtype(atyb) struct hshtab *atyb; { register struct hshtab *tyb; struct hshtab typer; int sc; register char *md, *fb; struct tnode *scp; tyb = atyb; fb = funcbase; md = maxdecl; scp = cp; funcbase = curbase; sc = DEFXTRN; /* will cause error if class mentioned */ getkeywords(&sc, &typer); tyb->hclass = 0; tyb->hblklev = 0; decl1(&sc, &typer, 0, tyb); funcbase = fb; maxdecl = md; cp = scp; tyb->on operators */ case QUEST: if (p2->op!=COLON) error("Illegal conditional"); if (fold(QUEST, p1, p2)) return; case SEQNC: t = t2; case COMMA: case LOGAND: case LOGOR: *cp++ = block(op, t, NULL, NULL, p1, p2); return; case EXCLA: t1 = INT; break; case CALL: if ((t1&XTYPE) != FUNC) error("Call of non-function"); *cp++ = block(CALL,decref(t1),p1->subsp,p1->strp,p1,p2); return; case STAR: if (p1->op==AMPER ) { *cp++ = p1->tr1; return; } if ((t1&XTYPE) == FUNC2==UNSIGN)) t = UNSIGN; if (dope&ASSGOP || op==CAST) { t = t1; if (op==ASSIGN || op==CAST) { if (cvn==ITP||cvn==PTI) cvn = leftc = 0; else if (cvn==LTP) { if (leftc==0) cvn = LTI; else { cvn = ITL; leftc = 0; } } } if (leftc) cvn = leftc; leftc = 0; } else if (op==COLON || op==MAX || op==MIN) { if (t1>=PTR && t1==t2) cvn = 0; if (op!=COLON && (t1>=PTR || t2>=PTR)) op =+ MAXP-MAX; } else if (dope&RELAT) { if (op>=LESSEQ && (t1>=PTR||t2>=PTwise push back the character and return a. */ subseq(c,a,b) { if (spnextchar() != c) return(a); peekc = 0; return(b); } /* * Write out a string, either in-line * or in the string temp file labelled by * lab. */ putstr(lab, amax) { register int c, max; nchstr = 0; max = amax; if (lab) { strflg++; outcode("BNB", LABEL, lab, BDATA); max = 10000; } else outcode("B", BDATA); while ((c = mapch('"')) >= 0) { if (nchstr < max) { nchstr++; outcode("1N", c & 0377); } } if (nchstrpriority-driven scheme. * The initflg prevents the parse from going past * "," or ":" because those delimiters are special * in initializer (and some other) expressions. */ struct tnode * tree() { int *op, opst[SSIZE], *pp, prst[SSIZE]; register int andflg, o; register struct hshtab *cs; int p, ps, os; struct tnode *cmst[CMSIZ]; struct lnode *lcp; curbase = funcbase; op = opst; pp = prst; cp = cmst; *op = SEOF; *pp = 06; andflg = 0; advanc: switch (o=symbol()) { case NAME: cs = csym;andflg) andflg = 0; else if (o==AND) o = AMPER; else o = STAR; goto oponst; case LPARN: if (andflg) { o = symbol(); if (o==RPARN) o = MCALL; else { peeksym = o; o = CALL; andflg = 0; } } goto oponst; case RBRACK: case RPARN: if (!andflg) goto syntax; goto oponst; case DOT: case ARROW: mosflg++; break; case ASSIGN: if (andflg==0 && PLUS<=*op && *op<=EXOR) { o = *op-- + ASPLUS - PLUS; pp--; goto oponst; } break; } /* binarp = ETYPE; return(tyb); } char * copnum(len) { register char *s1, *s2, *s3; s1 = s2 = gblock((len+LNCPW-1) & ~(LNCPW-1)); s3 = numbuf; while (*s2++ = *s3++); return(s1); } ) error("Illegal indirection"); *cp++ = block(STAR, decref(t1), p1->subsp, p1->strp, p1); return; case AMPER: if (p1->op==STAR) { *cp++ = p1->tr1; return; } if (p1->op==NAME) { *cp++ = block(op,incref(t1),p1->subsp,p1->strp,p1); return; } error("Illegal lvalue"); break; /* * a.b goes to (&a)->b */ case DOT: *cp++ = p1; build(AMPER); p1 = *--cp; /* * In a->b, a is given the type ptr-to-structure element; * then the offset is added in without conversion; *R||(t1==UNSIGN||t2==UNSIGN) /***/ && (t==INT||t==CHAR||t==UNSIGN||t==SHORT))) op =+ LESSEQP-LESSEQ; if (cvn==ITP || cvn==PTI) cvn = 0; } if (cvn==PTI) { cvn = 0; if (op==MINUS) { t = INT; pcvn++; } else { if (t1!=t2 || t1!=(PTR+CHAR)) cvn = XX; } } if (cvn) { t1 = plength(p1); t2 = plength(p2); if (cvn==XX || (cvn==PTI&&t1!=t2)) error("Illegal conversion"); else if (leftc) p1 = convert(p1, t, cvn, t2); else p2 = convert(p2, t, cvn, t1); } if (dope&RELA->op!=ETYPE) return(block(AMPER,incref(t),p->subsp,p->strp,p)); return(p); } /* * A mention of an array is turned into * a pointer to the base of the array. */ struct tnode * disarray(ap) struct tnode *ap; { register int t; register struct tnode *p; p = ap; /* check array & not MOS and not typer */ if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->tr1->hclass==MOS || p->op==ETYPE) return(p); p->subsp++; *cp++ = p; setype(p, decref(t), p); build(AMPER); return(*--cp); } /* * make sualue = v; return(p); } /* * A block for a float or long constant */ struct fnode * fblock(t, string) char *string; { register struct fnode *p; p = gblock(sizeof(*p)); p->op = FCON; p->type = t; p->subsp = NULL; p->strp = NULL; p->cstr = string; return(p); } /* * Assign a block for use in the * expression tree. */ char * gblock(n) { register int *p; p = curbase; if ((curbase =+ n) >= coremax) { if (sbrk(1024) == -1) { error("Out of space"); exit(1); } coremax =+ 1024; } ret; *cp++ = p1; return(1); } /* * Compile an expression expected to have constant value, * for example an array bound or a case value. */ conexp() { register struct tnode *t; initflg++; if (t = tree()) if (t->op != CON) error("Constant required"); initflg--; curbase = funcbase; return(t->value); } : tptr->hflag =| FUNION; case STRUCT: tptr->hstrp = strdec(ismos, cval==UNION); cval = STRUCT; case INT: case CHAR: case FLOAT: case DOUBLE: if (tkw>=0) error("Type clash"); tkw = cval; break; default: peeksym = o; if (isadecl==0) return(0); if (tkw<0) tkw = INT; if (skw==0) skw = blklev==0? DEFXTRN: AUTO; if (unsignf) { if (tkw==INT) tkw = UNSIGN; else error("Misplaced 'unsigned'"); } if (longf) { if (tkw==FLOAT) ared", ssym->name); strp->ssize = elsize; *memlist++ = NULL; strp->memlist = gblock((memlist-mems)*sizeof(*memlist)); funcbase = curbase; for (o=0; &mems[o] != memlist; o++) strp->memlist[o] = mems[o]; memlist = savememlist; nmems = savenmems; if ((o = symbol()) != RBRACE) goto syntax; } return(strp); syntax: decsyn(o); return(0); } /* * Process a comma-separated list of declarators */ declare(askw, tptr, offset) struct hshtab *tptr; { register int o; register int skw, isunT) t = INT; if (t==FLOAT) t = DOUBLE; /***/ if (t==CHAR||t==SHORT) t = INT; if (op==CAST) { p2->type = t; p2->subsp = p1->subsp; p2->strp = p1->strp; if (t==INT && p1->type==CHAR) p2 = block(ITOC, INT, NULL, NULL, p2); *cp++ = p2; return; } if (fold(op, p1, p2)==0) { p3 = leftc?p2:p1; *cp++ = block(op, t, p3->subsp, p3->strp, p1, p2); } if (pcvn && t1!=(PTR+CHAR)) { p1 = *--cp; *cp++ = convert(p1, 0, PTI, plength(p1->tr1)); } } /* * Generate the appropriate conversion ore that p is a ptr to a node * with type int or char or 'okt.' * okt might be nonexistent or 'long' * (e.g. for <<). */ chkw(p, okt) struct tnode *p; { register int t; /***/ if ((t=p->type)!=INT && top==FSEL) p = p->tr1; if (p->op!=NAME && p->op!=STAR) error("Lvalue required"); } /* * reduce some forms of `constant op constant' * to a constant. More of this is done in the next pass * but this is used to allow constant expressions * to be used in switches and array bounds. */ fold(op, ap1, ap2) struct tnode *ap1, *ap2; { register struct tnode *p1; re# /* * C compiler, phase 1 * * * Handles processing of declarations, * except for top-level processing of * externals. */ #include "c0.h" /* * Process a sequence of declaration statements */ declist(sclass) { register sc, offset; struct hshtab typer; offset = 0; sc = sclass; while (getkeywords(&sclass, &typer)) { offset = declare(sclass, &typer, offset); sclass = sc; } return(offset+align(INT, offset, 0)); } /* * Read the keywords introducing a declaration statement * Store back th tkw = DOUBLE; else if (tkw==INT) tkw = LONG; else error("Misplaced 'long'"); } /***/ if (shortf) { /***/ if (tkw==INT) /***/ tkw = SHORT; /***/ else if (tkw != FLOAT) /***/ error("Misplaced 'short'"); /***/ } *scptr = skw; tptr->htype = tkw; return(1); } isadecl++; } } /* * Process a structure declaration; a subroutine * of getkeywords. */ struct str * strdec(mosf, unionf) { register elsize, o; register struct hshtab *ssym; int savebits; struct perator. */ struct tnode * convert(p, t, cvn, len) struct tnode *p; { register int op; op = cvntab[cvn]; if (opdope[op]&BINARY) { if (len==0) error("Illegal conversion"); return(block(op, t, NULL, NULL, p, cblock(len))); } return(block(op, t, NULL, NULL, p)); } /* * Traverse an expression tree, adjust things * so the types of things in it are consistent * with the view that its top node has * type at. * Used with structure references. */ setype(ap, at, anewp) struct tnode *ap, *anewp; {case LONG: return(2); default: return(3); } } /* * Report an error. */ error(s, p1, p2, p3, p4, p5, p6) { nerror++; if (filename[0]) printf("%s:", filename); printf("%d: ", line); printf(s, p1, p2, p3, p4, p5, p6); printf("\n"); } /* * Generate a node in an expression tree, * setting the operator, type, dimen/struct table ptrs, * and the operands. */ struct tnode * block(op, t, subs, str, p1,p2) int *subs; struct str *str; struct tnode *p1, *p2; { register struct tnode *p; p = gblocgister int v1, v2; p1 = ap1; if (p1->op!=CON) return(0); if (op==QUEST) { if (ap2->tr1->op==CON && ap2->tr2->op==CON) { p1->value = p1->value? ap2->tr1->value: ap2->tr2->value; *cp++ = p1; return(1); } return(0); } if (ap2) { if (ap2->op!=CON) return(0); v2 = ap2->value; } v1 = p1->value; switch (op) { case PLUS: v1 =+ v2; break; case MINUS: v1 =- v2; break; case TIMES: v1 =* v2; break; case DIVIDE: v1 =/ v2; break; case MOD: v1 =% v2; break; e storage class, and fill in the type * entry, which looks like a hash table entry. */ getkeywords(scptr, tptr) int *scptr; struct hshtab *tptr; { register skw, tkw, longf; int o, isadecl, ismos, unsignf; /***/ int shortf; isadecl = 0; /***/ shortf = longf = 0; unsignf = 0; tptr->htype = INT; tptr->hstrp = NULL; tptr->hsubsp = NULL; tkw = -1; skw = *scptr; ismos = skw==MOS||skw==MOU; for (;;) { mosflg = ismos && isadecl; o = symbol(); if (o==NAME && csym->hclass==TYPEDEF && tkw<0) { thshtab **savememlist; int savenmems; struct str *strp; struct hshtab *ds; struct hshtab *mems[NMEMS]; mosflg = 1; ssym = 0; if ((o=symbol())==NAME) { ssym = csym; mosflg = mosf; o = symbol(); if (o==LBRACE && ssym->hblklevhclass==0) { ssym->hclass = STRTAG; ssym->strp = gblock(sizeof(*strp)); funcbase = curbase; ssym->strp->ssize = 0; ssym->strp->memlist = NULL; } if (ssym->hclass != STRTAG) redec(); strp = ssym->strp; } else {ion; skw = askw; isunion = 0; if (skw==MOU) { skw = MOS; isunion++; mosflg = 1; if ((peeksym=symbol()) == SEMI) { o = length(tptr); if (o>offset) offset = o; } } do { o = decl1(skw, tptr, isunion?0:offset, NULL); if (isunion) { o =+ align(CHAR, o, 0); if (o>offset) offset = o; } else offset =+ o; } while ((o=symbol()) == COMMA); if (o!=SEMI && (o!=RPARN || skw!=ARG1)) decsyn(o); return(offset); } /* * Process a single declarator */ decl1(askw, atptr, offs register struct tnode *p, *newp; register t; p = ap; t = at; newp = anewp; for (;; p = p->tr1) { p->subsp = newp->subsp; p->strp = newp->strp; p->type = t; if (p->op==AMPER) t = decref(t); else if (p->op==STAR) t = incref(t); else if (p->op!=PLUS) break; } } /* * A mention of a function name is turned into * a pointer to that function. */ struct tnode * chkfun(ap) struct tnode *ap; { register struct tnode *p; register int t; p = ap; if (((t = p->type)&XTYPE)==FUNC && pk(sizeof(*p)); p->op = op; p->type = t; p->subsp = subs; p->strp = str; p->tr1 = p1; if (opdope[op]&BINARY) p->tr2 = p2; else p->tr2 = NULL; return(p); } struct tnode * nblock(ads) struct hshtab *ads; { register struct hshtab *ds; ds = ads; return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, ds)); } /* * Generate a block for a constant */ struct cnode * cblock(v) { register struct cnode *p; p = gblock(sizeof(*p)); p->op = CON; p->type = INT; p->subsp = NULL; p->strp = NULL; p->vcase AND: v1 =& v2; break; case OR: v1 =| v2; break; case EXOR: v1 =^ v2; break; case NEG: v1 = - v1; break; case COMPL: v1 = ~ v1; break; case LSHIFT: v1 =<< v2; break; case RSHIFT: v1 =>> v2; break; case EQUAL: v1 = v1==v2; break; case NEQUAL: v1 = v1!=v2; break; case LESS: v1 = v1v2; break; case LESSEQ: v1 = v1<=v2; break; case GREATEQ: v1 = v1>=v2; break; default: return(0); } p1->value = v1kw = csym->htype; tptr->hsubsp = csym->hsubsp; tptr->hstrp = csym->hstrp; isadecl++; continue; } switch (o==KEYW? cval: -1) { case AUTO: case STATIC: case EXTERN: case REG: case TYPEDEF: if (skw && skw!=cval) { if (skw==ARG && cval==REG) cval = AREG; else error("Conflict in storage class"); } skw = cval; break; case UNSIGN: unsignf++; break; case LONG: longf++; break; /***/ case SHORT: /***/ shortf++; /***/ break; case UNION strp = gblock(sizeof(*strp)); funcbase = curbase; strp->ssize = 0; strp->memlist = NULL; } mosflg = 0; if (o != LBRACE) { if (ssym==0) goto syntax; if (ssym->hclass!=STRTAG) error("Bad structure/union name"); peeksym = o; } else { ds = defsym; mosflg = 0; savebits = bitoffs; savememlist = memlist; savenmems = nmems; memlist = mems; nmems = 2; bitoffs = 0; elsize = declist(unionf?MOU:MOS); bitoffs = savebits; defsym = ds; if (strp->ssize) error("%.8s redeclet, absname) struct hshtab *atptr, *absname; { int t1, chkoff, a, elsize; register int skw; int type; register struct hshtab *dsym; register struct hshtab *tptr; struct tdim dim; struct field *fldp; int *dp; int isinit; /***/ int boff; skw = askw; tptr = atptr; chkoff = 0; mosflg = skw==MOS; dim.rank = 0; if (((peeksym=symbol())==SEMI || peeksym==RPARN) && absname==NULL) return(0); /* * Filler field */ if (peeksym==COLON && skw==MOS) { peeksym = -1; t1 = conexp(); elsize = align(tptr->htype, offset, t1); bitoffs =+ t1; return(elsize); } t1 = getype(&dim, absname); if (t1 == -1) return(0); if (tptr->hsubsp) { type = tptr->htype; for (a=0; type&XTYPE;) { if ((type&XTYPE)==ARRAY) dim.dimens[dim.rank++] = tptr->hsubsp[a++]; type =>> TYLEN; } } type = tptr->htype & ~TYPE; while (t1&XTYPE) { if (type&BIGTYPE) { typov(); type = t1 = 0; } type = type<> TYLEN; } type =| tptr->htype&TYPE; if (absname) defsym = absnLD) { /***/ if (dsym->hstrp->bitoffs!=boff || dsym->hstrp->flen!=t1) redec(); } else { dsym->hstrp = gblock(sizeof(*fldp)); funcbase = curbase; } dsym->hflag =| FFIELD; /***/ dsym->hstrp->bitoffs = boff; dsym->hstrp->flen = t1; bitoffs =+ t1; } else a = align(type, offset, 0); elsize =+ a; offset =+ a; if (++nmems >= NMEMS) { error("Too many structure members"); nmems =- NMEMS/2; memlist =- NMEMS/2; } if (a) *memlist++ = &structhole; if (chss = rs2->hclass; rs1->hflag = rs2->hflag; rs1->htype = rs2->htype; rs1->hoffset = rs2->hoffset; rs1->hsubsp = rs2->hsubsp; rs1->hstrp = rs2->hstrp; rs1->hblklev = rs2->hblklev; rs1->hpdown = rs2->hpdown; } /* * Read a declarator and get the implied type */ getype(adimp, absname) struct tdim *adimp; struct hshtab *absname; { static struct hshtab argtype; int type; register int o; register struct hshtab *ds; register struct tdim *dimp; ds = defsym; dimp = adimp; type = 0; switch(o=symbolfield considerations. */ align(type, offset, aflen) { register a, t, flen; char *ftl; flen = aflen; a = offset; t = type; ftl = "Field too long"; if (flen==0) { a =+ (NBPC+bitoffs-1) / NBPC; bitoffs = 0; } while ((t&XTYPE)==ARRAY) t = decref(t); /*** *** This should be fixed up to use a table of lengths ***/ /***/ switch (t) { /***/ /***/ case SHORT: /***/ a = (a+SZSHORT-1) & ~(SZSHORT-1); /***/ break; /***/ /***/ case LONG: /***/ a = (a+SZLONG-1) & ~(SZLONG-1); /***/ /***/ case DOUBLE# /* * C compiler * * */ #include "c0.h" /* * Reduce the degree-of-reference by one. * e.g. turn "ptr-to-int" into "int". */ decref(at) { register t; t = at; if ((t & ~TYPE) == 0) { error("Illegal indirection"); return(t); } return((t>>TYLEN) & ~TYPE | t&TYPE); } /* * Increase the degree of reference by * one; e.g. turn "int" to "ptr-to-int". */ incref(t) { return(((t&~TYPE)<type)&~TYPE) == 0) /* not a reference */ return(1); p->type = decref(t); l = length(p); p->type = t; return(l); } /*ame; dsym = defsym; if (dsym->hblklev < blklev) pushdecl(dsym); if (dim.rank == 0) dsym->subsp = NULL; else { dp = gblock(dim.rank*sizeof(dim.rank)); funcbase = curbase; for (a=0; ahtype&XTYPE) == ARRAY && dsym->subsp[a] && t1!=dsym->subsp[a]) redec(); } dsym->subsp = dp; } if ((type&XTYPE) == FUNC) { if (skw==AUTO) skw = EXTERN; if (skw!=EXTERN && absname==NULL) error("Bad func. storage class"); } ifkoff && dsym->hoffset != offset) redec(); dsym->hoffset = offset; *memlist++ = dsym; } if (skw==REG) if ((dsym->hoffset = goodreg(dsym)) < 0) skw = AUTO; dsym->hclass = skw; isinit = 0; if ((a=symbol())!=COMMA && a!=SEMI) isinit++; if (a!=ASSIGN) peeksym = a; if (skw==AUTO) { /* if (STAUTO < 0) { */ autolen =- rlength(dsym); dsym->hoffset = autolen; if (autolen < maxauto) maxauto = autolen; /* } else { */ /* dsym->hoffset = autolen; */ /* autolen =+ rlength(dsym)()) { case TIMES: type = getype(dimp, absname); if (type == -1) return(type); if (type&BIGTYPE) { typov(); type = 0; } return(type<offset) bitoffs=0; if (flen) { if (type==INT || type==UNSIGN) { if (flen > NBPW) error(ftl); if (flen+bitoffs > NBPW) { bitoffs = 0; a =+ NCPW; } } else if (type==CHAR) { if (flen > NBPC) error(ftl); if (flen+bitoffs > NBPC) { bitoffs = 0; a =+ 1; } } else error("Bad type for field") together with the cond. */ cbranch(t, lbl, cond) struct tnode *t; { treeout(t); outcode("BNNN", CBRANCH, lbl, cond, line); } /* * Write out a tree. */ rcexpr(atp) struct tnode *atp; { register struct tnode *tp; /* * Special optimization */ if ((tp=atp)->op==INIT && tp->tr1->op==CON) { if (tp->type==CHAR) { outcode("B1N0", BDATA, tp->tr1->value); return; } else if (tp->type==INT || tp->type==UNSIGN) { outcode("BN", SINIT, tp->tr1->value); return; } } treeout(tp); outcode(" * return the number of bytes in the object * whose tree node is acs. */ length(acs) struct tnode *acs; { register t, n; register struct tnode *cs; int nd; cs = acs; t = cs->type; n = 1; nd = 0; while ((t&XTYPE) == ARRAY) { t = decref(t); n =* cs->subsp[nd++]; } if ((t&~TYPE)==FUNC) return(0); if (t>=PTR) return(SZPTR*n); switch(t&TYPE) { case INT: case UNSIGN: return(SZINT*n); case CHAR: return(n); /***/ case SHORT: /***/ return(SZSHORT*n); case FLOAT: return(SZFLOAT* (!(dsym->hclass==0 || ((skw==ARG||skw==AREG) && dsym->hclass==ARG1) || (skw==EXTERN && dsym->hclass==EXTERN && dsym->htype==type))) if (skw==MOS && dsym->hclass==MOS && dsym->htype==type) chkoff = 1; else { redec(); goto syntax; } if (dsym->hclass && (dsym->htype&TYPE)==STRUCT && (type&TYPE)==STRUCT) if (dsym->hstrp != tptr->hstrp) { error("Warning: structure redeclaration"); nerror--; } dsym->htype = type; if (tptr->hstrp) dsym->hstrp = tptr->hstrp; if (skw==TYPEDEF); */ /* if (autolen > maxauto) */ /* maxauto = autolen; */ /* } */ if (isinit) cinit(dsym, 0, AUTO); } else if (skw==STATIC) { dsym->hoffset = isn; if (isinit) { outcode("BBN", DATA, LABEL, isn++); if (cinit(dsym, 1, STATIC) & ALIGN) outcode("B", EVEN); } else outcode("BBNBN", BSS, LABEL, isn++, SSPACE, rlength(dsym)); outcode("B", PROG); } else if (skw==REG && isinit) cinit(dsym, 0, REG); prste(dsym); syntax: return(elsize); } /* * Push down an outer-block declara ds = csym; getf: switch(o=symbol()) { case LPARN: if (blklev==0) { blklev++; ds = defsym; declare(ARG1, &argtype, 0); defsym = ds; blklev--; } else if ((o=symbol()) != RPARN) goto syntax; if (type&BIGTYPE) { typov(); type = 0; } type = type<rank>=5) { error("Rank too large"); dimp->rank = 4; } if ((o=symbol()) != RBRACK) { peeksym = o; cval = conexp(); defsym = ds; ; } return(a-offset); } /* * Complain about syntax error in declaration */ decsyn(o) { error("Declaration syntax"); errflush(o); } /* * Complain about a redeclaration */ redec() { error("%.8s redeclared", defsym->name); } /* * Determine if a variable is suitable for storage in * a register; if so return the register number */ goodreg(hp) struct hshtab *hp; { int type; type = hp->htype; /* * Special dispensation for unions */ if (type==STRUCT && length(hp)<=SZINT) type = INT; /***/ BN", EXPR, line); } treeout(atp) struct tnode *atp; { register struct tnode *tp; register struct hshtab *hp; if ((tp = atp) == 0) { outcode("B", NULLOP); return; } switch(tp->op) { case NAME: hp = tp->tr1; if (hp->hclass==TYPEDEF) error("Illegal use of type name"); outcode("BNN", NAME, hp->hclass==0?STATIC:hp->hclass, tp->type); if (hp->hclass==EXTERN) outcode("S", hp->name); else outcode("N", hp->hoffset); return; case LCON: outcode("BNNN", tp->op, tp->type, tp->lvaluen); case LONG: return(SZLONG*n); case DOUBLE: return(SZDOUB*n); case STRUCT: if ((t = cs->strp->ssize) == 0) error("Undefined structure"); return(n * t); } error("Compiler error (length)"); return(0); } /* * The number of bytes in an object, rounded up to a word. */ rlength(cs) struct tnode *cs; { return((length(cs)+ALIGN) & ~ALIGN); } /* * After an "if (...) goto", look to see if the transfer * is to a simple label. */ simplegoto() { register struct hshtab *csp; if ((peeksym= { dsym->hclass = TYPEDEF; return(0); } if (absname) return(0); if (skw==ARG1) { if (paraml==0) paraml = dsym; else parame->hoffset = dsym; parame = dsym; dsym->hclass = skw; return(0); } elsize = 0; if (skw==MOS) { elsize = length(dsym); if ((peeksym = symbol())==COLON) { elsize = 0; peeksym = -1; t1 = conexp(); a = align(type, offset, t1); /*** Assign bit fields left to right ***/ /***/ boff = (type==INT? NBPW : NBPC) - bitoffs - t1; if (dsym->hflag&FFIEtion * after redeclaration in an inner block. */ pushdecl(asp) struct phshtab *asp; { register struct phshtab *sp, *nsp; sp = asp; nsp = gblock(sizeof(*nsp)); maxdecl = funcbase = curbase; cpysymb(nsp, sp); sp->hclass = 0; sp->hflag =& ~(FNUND|FFIELD|FINIT|FLABL); sp->htype = 0; sp->hoffset = 0; sp->hblklev = blklev; sp->hpdown = nsp; } /* * Copy the non-name part of a symbol */ cpysymb(s1, s2) struct phshtab *s1, *s2; { register struct phshtab *rs1, *rs2; rs1 = s1; rs2 = s2; rs1->hcla if ((o=symbol())!=RBRACK) goto syntax; } else { if (dimp->rank!=0) error("Null dimension"); cval = 0; } dimp->dimens[dimp->rank++] = cval; if (type&BIGTYPE) { typov(); type = 0; } type = type<PTR || regvar<9) return(-1); return(--regvar); } ); return; case CON: outcode("BNN", tp->op, tp->type, tp->value); return; case FCON: outcode("BNF", tp->op, tp->type, tp->cstr); return; case STRING: outcode("BNNN", NAME, STATIC, tp->type, tp->tr1); return; case FSEL: treeout(tp->tr1); outcode("BNNN",tp->op,tp->type,tp->tr2->bitoffs,tp->tr2->flen); return; case ETYPE: error("Illegal use of type"); return; default: treeout(tp->tr1); if (opdope[tp->op]&BINARY) treeout(tp->tr2); outcode("BN", tp->op, tp->type); rsymbol())==NAME && nextchar()==';') { csp = csym; if (csp->hblklev == 0) pushdecl(csp); if (csp->hclass==0 && csp->htype==0) { csp->htype = ARRAY; csp->hflag =| FLABL; if (csp->hoffset==0) csp->hoffset = isn++; } if ((csp->hclass==0||csp->hclass==STATIC) && csp->htype==ARRAY) { peeksym = -1; return(csp->hoffset); } } return(0); } /* * Return the next non-white-space character */ nextchar() { while (spnextchar()==' ') peekc = 0; return(peekc); } /* * Return thntinue; case 'F': n = 1000; goto str; case 'S': n = NCPS; str: np = *ap++; while (n-- && *np) { putc(*np++&0177, bufp); } putc(0, bufp); anyerr =| errno; continue; case '1': putw(1, bufp); anyerr =| errno; continue; case '0': putw(0, bufp); anyerr =| errno; continue; case '\0': if (anyerr) { error("Write error on temp"); exit(1); } return; default: error("Botch in outcode"); } } 000400, /* short constant */ 000400, /* string */ 000400, /* float */ 000400, /* double */ 000400, /* long constant */ 000400, /* long constant <= 16 bits */ 000000, /* 27 */ 000000, /* 28 */ 000000, /* 29 */ 034203, /* ++pre */ 034203, /* --pre */ 034203, /* ++post */ 034203, /* --post */ 034220, /* !un */ 034202, /* &un */ 034220, /* *un */ 034200, /* -un */ 034220, /* ~un */ 036001, /* . (structure reference) */ 030101, /* + */ 030001, /* - */ 032101, /* * */ 032001, /* / */ 03200 XX: usually illegal * When FTI, LTI, FTL are added in they specify * that it is the left operand that should be converted. * For + this is done and the conversion is turned back into * ITF, ITL, LTF. * For = however the left operand can't be converted * and the specified conversion is applied to the rhs. */ char cvtab[4][4] { /* int double long ptr */ /* int */ 0, (FTI<<4)+ITF, (LTI<<4)+ITL, (ITP<<4)+ITP, /* double */ ITF, 0, LTF, XX, /* long */ ITL, (FTL<<4)+LTF, 0, (LTP<<4)+LTP, /* ptr */ ITTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, COMPL, UNKN }; /* && */ 000001, /* || */ 030001, /* &~ */ 001000, /* double -> long */ 001000, /* long -> double */ 001000, /* integer -> long */ 000000, /* long -> integer */ 022005, /* == */ 022005, /* != */ 024005, /* <= */ 024005, /* < */ 024005, /* >= */ 024005, /* > */ 024005, /*

p */ 024005, /* >=p */ 012213, /* =+ */ 012213, /* =- */ 012213, /* =* */ 012213, /* =/ */ 012213, /* =% */ 012253, /* =>> */ 012253, /* =<< */ 012253, /* =& */ 012253, /* =| */ e next character, translating all white space * to blank and handling line-ends. */ spnextchar() { register c; if ((c = peekc)==0) c = getchar(); if (c=='\t' || c=='\014') /* FF */ c = ' '; else if (c=='\n') { c = ' '; if (inhdr==0) line++; inhdr = 0; } else if (c=='\001') { /* SOH, insert marker */ inhdr++; c = ' '; } peekc = c; return(c); } /* * is a break or continue legal? */ chconbrk(l) { if (l==0) error("Break/continue error"); } /* * The goto statement. */ dogoto(# #include "c0.h" char filename[64]; char symbuf[NCPS+2]; int hshused; struct hshtab hshtab[HSHSIZ]; struct tnode **cp; struct swtab swtab[SWSIZ]; struct swtab *swp; int contlab; int brklab; int retlab; int deflab; int autolen; int peekc; int eof; char *funcbase; char *curbase; char *coremax; char *maxdecl; int maxauto; struct hshtab *defsym; struct hshtab *funcsym; int proflg; int mflag; /***/ struct hshtab *csym; int cval; LTYPE lcval; int nchstr; int nerror; struct hshtab **paraml; struct hshtab **para1, /* % */ 026061, /* >> */ 026061, /* << */ 020161, /* & */ 017161, /* | */ 017161, /* ^ */ 036001, /* -> */ 000000, /* int -> double */ 000000, /* double -> int */ 016001, /* && */ 015001, /* || */ 030001, /* &~ */ 000000, /* 56 */ 000000, /* 57 */ 000000, /* 58 */ 000000, /* 59 */ 022005, /* == */ 022005, /* != */ 024005, /* <= */ 024005, /* < */ 024005, /* >= */ 024005, /* > */ 024005, /*

p */ 024005, /* >=p */ 012213, /* =+ */ 012213, /* =-# /* * C second pass -- tables */ int line; char ascbuf[524]; /***/ int nerror; int nstack; int pstack; /***/ int ntemp; /***/ int maxtemp; /***/ int nfloat; char *funcbase; char *curbase; char *coremax; int fautolen; /***/ int xlab1, xlab2, xop, xzero; #include "c1.h" /* * Operator dope table-- see description in c0. */ int opdope[] { 000000, /* EOF */ 000000, /* ; */ 000000, /* { */ 000000, /* } */ 036000, /* [ */ 002000, /* ] */ 036000, /* ( */ 002000, /* ) */ 014201, /* : */ 007001, 012253, /* =^ */ 012213, /* = */ 030001, /* & for tests */ 032001, /* * (long) */ 032001, /* / (long) */ 032001, /* % (long) */ 012253, /* =& ~ */ 012213, /* =* (long) */ 012213, /* / (long) */ 012213, /* % (long) */ 000000, /* 89 */ 014201, /* ? */ 026061, /* long << */ 012253, /* long =<< */ 000101, /* max */ 000101, /* maxp */ 000101, /* min */ 000101, /* minp */ 000001, /* , */ 000000, /* 98 */ 000000, /* 99 */ 036001, /* call */ 036000, /* mcall */ 000000, /* goto */ 000000, /) { register struct tnode *np; *cp++ = tree(); build(STAR); chkw(np = *--cp, -1); rcexpr(block(JUMP,0,NULL,NULL,np)); } /* * The return statement, which has to convert * the returned object to the function's type. */ doret() { register struct tnode *t; if (nextchar() != ';') { t = tree(); *cp++ = &funcblk; *cp++ = t; build(ASSIGN); cp[-1] = cp[-1]->tr2; build(RFORCE); rcexpr(*--cp); } branch(retlab); } /* * Write a character on the error output. */ putchar(c) { /***/ char sc;me; int strflg; int mosflg; int initflg; int inhdr; char obuf[524]; /***/ char sbuf[524]; /***/ int regvar; int bitoffs; char numbuf[64]; struct hshtab **memlist; int nmems; struct hshtab structhole; int blklev; /* * info on operators: * 01-- is binary operator * 02-- left (or only) operand must be lvalue * 04-- is relational operator * 010-- is assignment-type operator * 020-- non-float req. on left * 040-- non-float req. on right * 0100-- is commutative * 0200-- is right, not left-as */ 012213, /* =* */ 012213, /* =/ */ 012213, /* =% */ 012253, /* =>> */ 012253, /* =<< */ 012253, /* =& */ 012253, /* =| */ 012253, /* =^ */ 012213, /* = */ 000000, /* 81 */ 000000, /* 82 */ 000000, /* 83 */ 000000, /* 84 */ 000000, /* 85 */ 000000, /* 86 */ 000000, /* 87 */ 000000, /* 88 */ 000000, /* 89 */ 014201, /* ? */ 034200, /* sizeof */ 000000, /* 92 */ 021101, /* min */ 021101, /* minp */ 021101, /* max */ 021101, /* maxp */ 007001, /* , */ 000000, /* 98 */ 000000, /* 9TP, XX, LTP, PTI, }; /* * relate conversion numbers to operators */ char cvntab[] { 0, ITOF, ITOL, LTOF, ITOP, PTOI, FTOI, LTOI, FTOL, LTOP, }; /* * character type table */ char ctab[] { EOF, INSERT, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, SPACE, NEWLN, UNKN, SPACE, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, SPACE, EXCLA, DQUOTE, SHARP, UNKN, MOD, AND, SQUOTE, LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, PERIOD, DIVIDE, DIG/* , */ 000000, /* field selection */ 000000, /* reverse field selection */ 000001, /* temporary field selection */ 000001, /* int->ptr */ 000001, /* ptr->int */ 000001, /* long->ptr */ 000001, /* field assignment */ 000001, /* >> unsigned */ 000001, /* >> unsigned */ 000000, /* 19 */ 000400, /* name */ 000400, /* short constant */ 000400, /* string */ 000400, /* float */ 000400, /* double */ 0000400, /* long const */ 000400, /* long const <= 16 bits */ 000400, /* autoi, *r++ */ 000400, /* jump cond */ 000000, /* branch cond */ 000400, /* set nregs */ 000000, /* 106 */ 000000, /* 107 */ 000000, /* 108 */ 000000, /* int->char */ 000000 /* force r0 */ }; char *opntab[] { 0, 0, 0, 0, 0, 0, 0, 0, ":", ",", "field select", 0, 0, "int->ptr", "ptr->int", "long->ptr", "field assign", ">>", ">>", 0, "name", "short constant", "string", "float", "double", "long constant", "long constant", "*r++", "*--r", 0, "++pre", "--pre", "++post", "--post", "!un", "&", sc = c&0177; write(1, &sc, 1); } /* * Coded output: * B: beginning of line; an operator * N: a number * S: a symbol (external) * 1: number 1 * 0: number 0 */ outcode(s, a) char *s; { extern errno; register *ap, *bufp; int n, anyerr; register char *np; bufp = obuf; if (strflg) bufp = sbuf; ap = &a; errno = 0; anyerr = 0; for (;;) switch(*s++) { case 'B': putw(*ap++ | (0376<<8), bufp); anyerr =| errno; continue; case 'N': putw(*ap++, bufp); anyerr =| errno; cosociative * 0400-- is leaf of tree * *0XX000-- XX is priority of operator */ int opdope[] { 000000, /* EOF */ 000000, /* ; */ 000000, /* { */ 000000, /* } */ 036000, /* [ */ 002000, /* ] */ 037000, /* ( */ 002000, /* ) */ 014201, /* : */ 007001, /* , */ 000001, /* field selection */ 034201, /* CAST */ 000000, /* ETYPE */ 000001, /* integer->ptr */ 000001, /* ptr->integer */ 000001, /* long->ptr */ 000000, /* 16 */ 000000, /* 17 */ 000000, /* 18 */ 000000, /* 19 */ 000400, /* name */ 9 */ 036001, /* call */ 036001, /* mcall */ 000000, /* goto */ 000000, /* jump cond */ 000000, /* branch cond */ 000000, /* 105 */ 000000, /* 106 */ 000000, /* 107 */ 000000, /* 108 */ 000000, /* char->int */ 000000 /* force r0 */ }; /* * conversion table: * FTI: float (or double) to integer * ITF: integer to float * ITP: integer to pointer * ITL: integer to long * LTI: long to integer * LTF: long to float * FTL: float to long * PTI: pointer to integer * LTP: long to ptr (ptr[long]) *IT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST, UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LBRACK, BSLASH, RBRACK, EXOR, LETTER, UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LE* autod, *--r */ 000000, /* 29 */ 034203, /* ++pre */ 034203, /* --pre */ 034203, /* ++post */ 034203, /* --post */ 034220, /* !un */ 034202, /* &un */ 034220, /* *un */ 034200, /* -un */ 034220, /* ~un */ 036001, /* . (structure reference) */ 030101, /* + */ 030001, /* - */ 032101, /* * */ 032001, /* / */ 032001, /* % */ 026061, /* >> */ 026061, /* << */ 020161, /* & */ 016161, /* | */ 016161, /* ^ */ 036001, /* -> */ 001000, /* int -> double */ 001000, /* double -> int */ 000001, "*", "-", "~", ".", "+", "-", "*", "/", "%", ">>", "<<", "&", "|", "^", "->", "int->double", "double->int", "&&", "||", "&~", "double->long", "long->double", "integer->long", "long->integer", "==", "!=", "<=", "<", ">=", ">", "p", ">=p", "=+", "=-", "=*", "=/", "=%", "=>>", "=<<", "=&", "=|", "=^", "=", "& for tests", "*", "/", "%", "=& ~", "=*", "=/", "=%", 0, "?", "<<", "=<<", "\\/", "\\/", "/\\", "/\\", 0, "call", "call", "call", 0, "goto", "jump cond", "branch cond", "set nregs", "load value", 0, 0, "int->char", "force register" }; ee->tr2); break; ***/ /* * On the PDP-11, int->ptr via multiplication * Longs are just truncated. */ case LTOP: tree->op = ITOP; tree->tr1 = unoptim(tnode(LTOI,INT,tree->tr1)); case ITOP: tree->op = TIMES; break; case MINUS: if (t = isconstant(tree->tr2)) { tree->op = PLUS; if (t->type==DOUBLE) /***/ /* Interdata FP representation */ /***/ t->value =^ (1<<31); else t->value = -t->value; } break; } op = tree->op; dope = opdope[op]; if (dope&LVALUE && tree->t ~tree->mask; return(optim(tree)); } if (tree->tr2->op==CON && tree->mask==tree->tr2->value) { tree->op = ASOR; return(optim(tree)); } case LTIMES: case LDIV: case LMOD: case LASTIMES: case LASDIV: case LASMOD: tree->degree = 10; break; case ANDN: if (isconstant(tree->tr2) && tree->tr2->value==0) { return(tree->tr1); } goto def; case CALL: tree->degree = 10; break; case QUEST: case COLON: tree->degree = max(d1, d2); break; /***/ case TIMES: case DIVIDE: ce->op==LSHIFT) tree->op = ULSH; else if (tree->op==ASLSH) tree->op = ASULSH; } goto again; ***/ constant: if (tree->tr1->op==CON && tree->tr2->op==CON) { const(op, &tree->tr1->value, tree->tr2->value); return(tree->tr1); } def: default: tree->degree = d1==d2? d1+islong(tree->type): max(d1, d2); break; } return(tree); } unoptim(atree) struct tnode *atree; { struct { int intx[4]; }; register struct tnode *subtre, *tree; register int *p; double static fv; struct { intp==STAR) return(subtre->tr1); /*** temporarily removed because it loses auto offsets if (subtre->op==NAME && subtre->class == OFFS) { p = tnode(PLUS, tree->type, subtre, tree); subtre->type = tree->type; tree->op = CON; tree->type = INT; tree->degree = 0; tree->value = subtre->offset; subtre->class = REG; subtre->nloc = subtre->regno; subtre->offset = 0; return(optim(p)); } ***/ break; case STAR: if (subtre->op==AMPER) return(subtre->tr1); if (subtre->op==NAMEN) { /***/ subtre->fvalue.intx[0] =^ (1<<31); return(subtre); } if (subtre->op == LCON) { subtre->lvalue = -subtre->lvalue; return(subtre); } } if (subtre->op == CON) switch(tree->op) { case NEG: subtre->value = -subtre->value; return(subtre); case COMPL: subtre->value = ~subtre->value; return(subtre); /*** case ITOF: fv = subtre->value; p = &fv; p++; if (*p++==0 && *p++==0 && *p++==0) { tree = getblk(sizeof(*fp)); tree->op = SFCON; tree->type = DOUBLE; techo == compiling C compiler echo = command cc -o cc -s -n cc.c echo = preprocessor cc -o cpp -s -n cpp.c -lS echo = pass 0 cc -o c0 -s -n c0?.c echo = code tables cc -o cvopt cvopt.c cvopt tables c1x.s as -u -o c1x.o c1x.s echo = pass 1 cc -o c1 -s -n c1?.c c1x.o r1->op==FSEL) return(lvfield(tree)); if ((dope&COMMUTE)!=0) { d1 = tree->type; tree = acommute(tree); if (tree->op == op) tree->type = d1; /* * PDP-11 special: * replace a&b by a ANDN ~ b. * This will be undone when in * truth-value context. */ /*** if (tree->op!=AND) ***/ return(tree); /* * long & pos-int is simpler */ if (tree->type==LONG && tree->tr2->op==ITOL && (tree->tr2->tr1->op==CON && tree->tr2->tr1->value>=0 || tree->tr2->tr1->type==UNSIGN)) { ase ASDIV: case ASTIMES: case PTOI: if (tree->tr2->op==CON && tree->tr2->value==1) return(tree->tr1); case MOD: case ASMOD: /*** *** Turn divides to shifts for pointers as well as unsigned ***/ /***/ if ((tree->tr1->type==UNSIGN /***/ || (tree->tr1->type&XTYPE)==PTR /***/ || op==PTOI) /***/ && ispow2(tree)) return(pow2(tree)); case ULSH: case ASULSH: d1 =+ 2; d2 =+ 2; if (tree->type==LONG) return(hardlongs(tree)); goto constant; case LSHIFT: case RSHIFT: case integer; }; register struct ftconst *fp; if ((tree=atree)==0) return(0); again: subtre = tree->tr1 = optim(tree->tr1); switch (tree->op) { case ITOF: if (tree->tr1->type==UNSIGN) { tree->tr1 = unoptim(tnode(ITOL, LONG, tree->tr1)); tree->op = LTOF; } break; case ITOC: p = tree->tr1; /* * Sign-extend PDP-11 characters */ if (p->op==CON) { /*** p->value = p->value << 8 >> 8; ***/ return(p); } else if (p->op==NAME) { p->type = CHAR; return(p); } break; && subtre->class==REG) { subtre->type = tree->type; subtre->class = OFFS; subtre->regno = subtre->nloc; return(subtre); } p = subtre->tr1; /*** if ((subtre->op==INCAFT||subtre->op==DECBEF)&&tree->type!=LONG && p->op==NAME && p->class==REG && p->type==subtre->type) { p->type = tree->type; p->op = subtre->op==INCAFT? AUTOI: AUTOD; return(p); } ***/ if (subtre->op==PLUS && p->op==NAME && p->class==REG) { if (subtre->tr2->op==CON) { p->offset =+ subtre->tr2->value; ree->value = fv.integer; tree->fvalue = fv; return(tree); } break; ***/ } tree->degree = max(islong(tree->type), degree(subtre)); return(tree); } /* * Deal with assignments to partial-word fields. * The game is that select(x) =+ y turns into * select(x =+ select(y)) where the shifts and masks * are chosen properly. The outer select * is discarded where the value doesn't matter. * Sadly, overflow is undetected on =+ and the like. * Pure assignment is handled specially. */ lvfield(at) # /* * C compiler part 2 -- expression optimizer * */ #include "c1.h" optim(atree) struct tnode *atree; { struct { int intx[4]; }; register op, dope; register d1, d2; register struct tnode *tree; register struct tnode *t; if ((tree=atree)==0) return(0); if ((op = tree->op)==0) return(tree); if (op==NAME && tree->class==AUTO) { tree->class = OFFS; /***/ tree->regno = 14; /***/ tree->offset = tree->nloc; } dope = opdope[op]; if ((dope&LEAF) != 0) { /*** if (op==FCON && tree->fva tree->type = UNSIGN; t = tree->tr2; tree->tr2 = tree->tr2->tr1; t->tr1 = tree; tree->tr1 = tnode(LTOI, UNSIGN, tree->tr1); return(optim(t)); } tree->op = ANDN; tree->tr2 = tnode(COMPL, tree->tr2->type, tree->tr2); } again: tree->tr1 = optim(tree->tr1); tree->tr2 = optim(tree->tr2); if ((dope&RELAT) != 0) { if ((d1=degree(tree->tr1)) < (d2=degree(tree->tr2)) || d1==d2 && tree->tr1->op==NAME && tree->tr2->op!=NAME) { t = tree->tr1; tree->tr1 = tree->tr2; tree->tr2 =     "#$ case LTOI: p = tree->tr1; switch (p->op) { case NAME: /***/ p->offset =+ NCPW; p->type = tree->type; return(p); case STAR: p->type = tree->type; p->tr1->type = tree->type+PTR; p->tr1 = tnode(PLUS, tree->type, p->tr1, tconst(2)); return(optim(p)); case ITOL: return(p->tr1); case PLUS: case MINUS: case AND: case ANDN: case OR: case EXOR: p->tr2 = tnode(LTOI, tree->type, p->tr2); case NEG: case COMPL: p->tr1 = tnode(LTOI, tree->type, p->tr1); p->typ->class = OFFS; p->type = tree->type; p->regno = p->nloc; return(p); } /***/ if (subtre->tr2->op==AMPER #ifdef unix && subtre->tr2->tr1->class != OFFS #else && subtre->tr2->tr1->class == STATIC #endif ) { subtre = subtre->tr2->tr1; subtre->class =+ XOFFS-EXTERN; subtre->regno = p->nloc; subtre->type = tree->type; return(subtre); } } break; case EXCLA: if ((opdope[subtre->op]&RELAT)==0) break; tree = subtre; tree->op = notrel[tree-struct tnode *at; { register struct tnode *t, *t1; register struct fasgn *t2; t = at; switch (t->op) { case ASSIGN: t2 = getblk(sizeof(*t2)); t2->op = FSELA; t2->type = UNSIGN; t1 = t->tr1->tr2; t2->mask = ((1<tr1->value)-1)<tr2->value; t2->tr1 = t->tr1; t2->tr2 = t->tr2; t = t2; case ASANDN: case ASPLUS: case ASMINUS: case ASOR: case ASXOR: case INCBEF: case INCAFT: case DECBEF: case DECAFT: t1 = t->tr1; t1->op = FSELR; t->tr1 = t1->tr1; t1->tr1 = t->tr2; lue.intx[1]==0 && tree->fvalue.intx[2]==0 && tree->fvalue.intx[3]==0) { tree->op = SFCON; tree->value = tree->fvalue.intx[0]; } ***/ return(tree); } if ((dope&BINARY) == 0) return(unoptim(tree)); /* is known to be binary */ /***/ if (tree->type==CHAR || tree->type==SHORT) tree->type = INT; switch(op) { /* * PDP-11 special: * generate new =&~ operator out of =& * by complementing the RHS. */ /*** case ASAND: tree->op = ASANDN; tree->tr2 = tnode(COMPL, tree->tr2->type, tr t; tree->op = maprel[op-EQUAL]; } if (tree->tr1->type==CHAR && tree->tr2->op==CON && (dcalc(tree->tr1, 0) <= 12 || tree->tr1->op==STAR) && tree->tr2->value <= 127 && tree->tr2->value >= 0) tree->tr2->type = CHAR; } d1 = max(degree(tree->tr1), islong(tree->type)); d2 = max(degree(tree->tr2), 0); switch (op) { /* * In assignment to fields, treat all-zero and all-1 specially. */ case FSELA: if (tree->tr2->op==CON && tree->tr2->value==0) { tree->op = ASAND; tree->tr2->value = ASRSH: case ASLSH: if (tree->tr2->op==CON && tree->tr2->value==0) { return(tree->tr1); } /* * PDP-11 special: turn right shifts into negative * left shifts */ if (tree->type == LONG) { d1++; d2++; } /*** if (op==LSHIFT||op==ASLSH) goto constant; if (tree->tr2->op==CON && tree->tr2->value==1 && tree->tr1->type!=UNSIGN) goto constant; op =+ (LSHIFT-RSHIFT); tree->op = op; tree->tr2 = tnode(NEG, tree->type, tree->tr2); if (tree->tr1->type==UNSIGN) { if (trepe = tree->type; return(optim(p)); } break; case FSEL: tree->op = AND; tree->tr1 = tree->tr2->tr1; tree->tr2->tr1 = subtre; tree->tr2->op = RSHIFT; tree->tr1->value = (1 << tree->tr1->value) - 1; return(optim(tree)); case FSELR: tree->op = LSHIFT; tree->type = UNSIGN; tree->tr1 = tree->tr2; tree->tr1->op = AND; tree->tr2 = tree->tr2->tr2; tree->tr1->tr2 = subtre; tree->tr1->tr1->value = (1 << tree->tr1->tr1->value) -1; return(optim(tree)); case AMPER: if (subtre->o>op-EQUAL]; break; case NEG: case COMPL: if (tree->type==CHAR) tree->type = INT; if (tree->op == subtre->op) return(subtre->tr1); if (subtre->op==ITOL) { subtre->op = tree->op; subtre->type = subtre->tr1->type; tree->op = ITOL; tree->type = LONG; goto again; } if (tree->op!=NEG) break; /* * Interdata FP negation */ if (subtre->op==SFCON) { /***/ subtre->value =^ (1<<31); /***/ subtre->fvalue.intx[0] =^ (1<<31); return(subtre); } if (subtre->op==FCO t->tr2 = t1; t1 = t1->tr2; t1 = tnode(COMMA, INT, tconst(t1->tr1->value), tconst(t1->tr2->value)); return(optim(tnode(FSELT, UNSIGN, t, t1))); } error("Unimplemented field operator"); return(t); } struct acl { /***/ char nextl; /***/ char nextn; /***/ struct tnode *nlist[10]; /***/ struct tnode *llist[11]; /*** *** The above arrays were changed from length [20] and [21] *** because of stack-overflow problems in 7/32 UNIX. The larger values *** should be restored if & when dynamic stack growth is implemented. *** Bounds checks in insert() will need to be changed too. ***/ }; acommute(atree) { struct acl acl; register struct tnode *t1, **t2, *tree; register struct tnode *t; register i, d, op, flt, d1; acl.nextl = 0; acl.nextn = 0; tree = atree; op = tree->op; flt = isfloat(tree); insert(op, tree, &acl); acl.nextl--; t2 = &acl.llist[acl.nextl]; if (!flt) { /* put constants together */ for (i=acl.nextl;i>0&&t2[0]->op==CON&&t2[-1]->op==CON;i--) { acl.nextl--; t2--; ispow2(tree)) tree->degree = max(degree(tree->tr1), islong(tree->type)); return(tree); } distrib(list) struct acl *list; { /* * Find a list member of the form c1c2*x such * that c1c2 divides no other such constant, is divided by * at least one other (say in the form c1*y), and which has * fewest divisors. Reduce this pair to c1*(y+c2*x) * and iterate until no reductions occur. */ register struct tnode **p1, **p2; register struct tnode *t; register ndmaj, ndmin; struct tnode **dividend, **divireturn; case AND: *vp =& v; return; case OR: *vp =| v; return; case EXOR: *vp =^ v; return; case DIVIDE: case MOD: if (v==0) error("Divide check"); else if (op==DIVIDE) *vp =/ v; else *vp =% v; return; case RSHIFT: *vp =>> v; return; case LSHIFT: *vp =<< v; return; case ANDN: *vp =& ~ v; return; } error("C error: const"); } insert(op, atree, alist) struct acl *alist; { register d; register struct acl *list; register struct tnode *tree; regse =+ size) >= coremax) { if (sbrk(1024) == -1) { error("Out of space-- c1"); exit(1); } coremax =+ 1024; } return(p); } islong(t) { if (t==LONG) return(2); return(1); } isconstant(at) struct tnode *at; { register struct tnode *t; t = at; if (t->op==CON || t->op==SFCON) return(t); if (t->op==ITOL && t->tr1->op==CON) return(t->tr1); return(0); } hardlongs(at) struct tnode *at; { register struct tnode *t; t = at; switch(t->op) { case TIMES: case DIVIDE: case MOD: t->op/* * Fortran Command */ char usage[] "Usage: fort [-c] [-l] [-S] [-o output] file [...]\n"; int lflag; /* make listing */ int cflag; /* compile & assemble only */ int vflag; /* debug */ int sflag; /* compile only */ int nerror; /* no. of errors encountered */ char *clist[64]; /* source filenames */ int nclist; char *llist[64]; /* arguments for ld */ int nllist; char *args[64]; /* argument list for exec */ char *ofname; /* output file name */ char sbuf[512]; /* string area for making negs[j++] = "-lf"; args[j++] = 0; call("/bin/ld", args); if (nclist == 1) unlink(setsuf(clist[0], 'o')); exit(nerror); } /* * Check whether suffix of filename is ".for" or ".f" */ isfor(name) char *name; { register char *p; if ((p = suffix(name)) == 0 ) return(0); if (*p == 'f') if (p[1] == '\0' || p[1] == 'o' && p[2] == 'r' && p[3] == '\0') return(1); return(0); } /* * Return a pointer to the suffix part of a filename */ suffix(name) char *name; { register char *p, *s; register c; const(op, &t2[0]->value, t2[1]->value); } } if (op==PLUS || op==OR) { /* toss out "+0" */ if (acl.nextl>0 && (t1 = isconstant(*t2)) && t1->value==0) { acl.nextl--; t2--; } if (acl.nextl <= 0) return(*t2); /* subsume constant in "&x+c" */ /***/ if (op==PLUS && t2[0]->op==CON && t2[-1]->op==AMPER #ifndef unix && t2[-1]->tr1->class != EXTERN #endif ) { t2--; t2[0]->tr1->offset =+ t2[1]->value; acl.nextl--; } } else if (op==TIMES || op==AND) { t1 = acl.llist[sor; struct tnode **maxnod, **mindiv; loop: maxnod = &list->llist[list->nextl]; ndmaj = 1000; dividend = 0; for (p1 = list->llist; p1 <= maxnod; p1++) { if ((*p1)->op!=TIMES || (*p1)->tr2->op!=CON) continue; ndmin = 0; for (p2 = list->llist; p2 <= maxnod; p2++) { if (p1==p2 || (*p2)->op!=TIMES || (*p2)->tr2->op!=CON) continue; if ((*p1)->tr2->value == (*p2)->tr2->value) { (*p2)->tr2 = (*p1)->tr1; (*p2)->op = PLUS; (*p1)->tr1 = (*p2); *p1 = optim(*p1); squash(ister d1, i; register struct tnode *t; tree = atree; list = alist; /***/ while (tree->op == op) { /***/ ins: /***/ if (list->nextn >= 10) /***/ error("Too many terms"); /***/ list->nlist[list->nextn++] = tree; /***/ insert(op, tree->tr1, list); /***/ tree = tree->tr2; } tree = optim(tree); if (tree->op == op) goto ins; if (!isfloat(tree)) { /* c1*(x+c2) -> c1*x+c1*c2 */ if ((tree->op==TIMES||tree->op==LSHIFT) && tree->tr2->op==CON && tree->tr2->value>0 && tree->tr1->op==PLUS && t =+ LTIMES-TIMES; break; case ASTIMES: case ASDIV: case ASMOD: t->op =+ LASTIMES-ASTIMES; t->tr1 = tnode(AMPER, LONG+PTR, t->tr1); break; default: return(t); } return(optim(t)); } w names */ char *str sbuf; main(argc, argv) char **argv; { register i, j, f; register char *p; if (--argc <= 0) { printf(usage); exit(1); } while (argc--) { if (*(p = *++argv) == '-') switch(*++p) { case 'c': cflag = 1; break; case 'v': vflag = 1; break; case 'S': sflag = 1; cflag = 1; break; case 'o': ofname = *++argv; if (--argc <= 0 || ofname[0] == '-') { printf(usage); exit(1); } break; case 'l': if (p[1] == '\0 s = 0; for (p = name; c = *p; p++) if (c == '/') s = 0; else if (c == '.') s = p+1; return(s); } /* * Make a new filename from with suffix */ setsuf(name, suf) char *name; { register char *p, *q; q = name; for (p = str; *p = *q++; p++) ; if ((q = suffix(str)) == 0) { q = p; *q++ = '.'; } *q++ = suf; *q++ = '\0'; p = str; str = q; return(p); } /* * Fork and execute a command with arguments in args[] */ call(command) char *command; { int status; register i; acl.nextl]; if (t1->op==CON) { if (t1->value==0) return(t1); if (op==TIMES && t1->value==1 && acl.nextl>0) if (--acl.nextl <= 0) return(acl.llist[0]); } } if (op==PLUS && !flt) distrib(&acl); tree = *(t2 = &acl.llist[0]); d = max(degree(tree), islong(tree->type)); if (op==TIMES && !flt) /***/ d =+ 2; for (i=0; itr2 = t = *++t2; d1 = degree(t); /* * PDP-11 strangeness: * rt. op of ^ must be in a register. */ /*** if p2, maxnod); list->nextl--; goto loop; } if (((*p2)->tr2->value % (*p1)->tr2->value) == 0) goto contmaj; if (((*p1)->tr2->value % (*p2)->tr2->value) == 0) { ndmin++; mindiv = p2; } } if (ndmin > 0 && ndmin < ndmaj) { ndmaj = ndmin; dividend = p1; divisor = mindiv; } contmaj:; } if (dividend==0) return; t = list->nlist[--list->nextn]; p1 = dividend; p2 = divisor; t->op = PLUS; t->type = (*p1)->type; t->tr1 = (*p1); t->tr2 = (*p2)->tr1; (*p1)->tr2ree->tr1->tr2->op==CON) { d = tree->tr2->value; if (tree->op==TIMES) tree->tr2->value =* tree->tr1->tr2->value; else tree->tr2->value = tree->tr1->tr2->value << d; tree->tr1->tr2->value = d; tree->tr1->op = tree->op; tree->op = PLUS; if (op==PLUS) goto ins; } } d = degree(tree); for (i=0; inextl; i++) { if ((d1=degree(list->llist[i]))llist[i]; list->llist[i] = tree; tree = t; d = d1; } } /***/ if (list->nextl >= 11) /***/ error("echo installing C compiler cp cc /bin/cc cpall cpp c0 c1 /lib rm cc cpp c0 c1 rm *.o c1x.s ') { lflag = 1; break; } default: llist[nllist++] = p-1; } else { if (isfor(p)) { clist[nclist++] = p; llist[nllist++] = setsuf(p, 'o'); } else llist[nllist++] = p; } } nice(10); p = str; for (i=0; i 1) printf("%s:\n", clist[i]); /* compile */ args[0] = "fortv"; args[1] = clist[i]; args[2] = setsuf(clist[i], 's'); j = 3; if (lflag) args[j++] = "l"; args[j] = 0; if (call("/usr/bin/fortv", ar if (vflag) { for (i=0; args[i]; i++) printf("%s ", args[i]); putchar('\n'); } if (fork() == 0) { execv(command, args); printf("Can't exec %s\n", command); exit(1); } wait(&status); if (i = (status&0377)) { if (i != 2) printf("Fatal error in %s\n", command); } else i = status>>8; if (i) nerror++; return(i); } (op==EXOR && dcalc(t, 0)<=12) { t1->tr2 = t = optim(tnode(LOAD, t->type, t)); d1 = t->degree; } ***/ t1->degree = d = d==d1? d+islong(t1->type): max(d, d1); t1->tr1 = tree; tree = t1; if (tree->type==LONG) { if (tree->op==TIMES) tree = hardlongs(tree); else if (tree->op==PLUS && (t = isconstant(tree->tr1)) && t->value < 0) { tree->op = MINUS; t->value = - t->value; t = tree->tr1; tree->tr1 = tree->tr2; tree->tr2 = t; } } } if (tree->op==TIMES &&->value =/ (*p2)->tr2->value; (*p2)->tr1 = t; t = optim(*p2); if (p1 < p2) { *p1 = t; squash(p2, maxnod); } else { *p2 = t; squash(p1, maxnod); } list->nextl--; goto loop; } squash(p, maxp) struct tnode **p, **maxp; { register struct tnode **np; for (np = p; np < maxp; np++) *np = *(np+1); } const(op, vp, av) int *vp; { register int v; struct { unsigned u;}; v = av; switch (op) { case PTOI: (*vp).u =/ v; return; case PLUS: *vp =+ v; return; case TIMES: *vp =* v; Too many terms"); list->llist[list->nextl++] = tree; } tnode(op, type, tr1, tr2) struct tnode *tr1, *tr2; { register struct tnode *p; p = getblk(sizeof(*p)); p->op = op; p->type = type; p->degree = 0; p->tr1 = tr1; if (opdope[op]&BINARY) p->tr2 = tr2; else p->tr2 = NULL; return(p); } tconst(val) { register struct tconst *p; p = getblk(sizeof(*p)); p->op = CON; p->type = INT; p->value = val; return(p); } getblk(size) { register *p; if (size&01) abort(); p = curbase; if ((curbaThis directory contains all source for the standard distribution version of Wollongong Interdata UNIX, Level 6. Each subdirectory contains two shell command files: make - recompile the source in this directory install - install the compiled programs in their correct places and clean up Source for the UNIX kernel itself is found in /usr/sys/. gs)) { cflag = 1; continue; } if (sflag) continue; /* assemble */ args[0] = "as"; args[1] = "-u"; args[4] = args[2]; args[2] = "-o"; args[3] = setsuf(clist[i], 'o'); args[5] = 0; if (call("/bin/as", args)) { cflag++; continue; } unlink(args[4]); } /* load */ if (cflag) exit(nerror); args[0] = "ld"; args[1] = "-x"; args[2] = "/lib/frt0.o"; j = 3; if (ofname) { args[j++] = "-o"; args[j++] = ofname; } for (i=0; i 2) { ctl(argv[2]); argc--; argv++; } } ctl(job) char job[]; { /* * Do the control functions. */ int fd; int found; /* look for the currently active job */ if ((fd = open(jobf, 0)) < 0) { /* no active job */ active[0] = '\0'; if (job[0] == '*' || flag != 'a') {; case 18: return("DLOG: Argument < 0"); case 19: return("DLOG: Argument = 0"); case 20: return("EXP: Overflow"); case 21: return("EXP: Underflow"); case 22: return("DEXP: Overflow"); case 23: return("DEXP: Underflow"); case 24: return("@A: Overflow"); case 25: return("@A: Underflow"); case 26: return("@S: Overflow"); case 27: return("@S: Underflow"); case 28: return("@M: Overflow"); case 29: return("@M: Underflow"); case 30: return("@D: Overflow"); case 31: return("@D: Underflow"); case 32: return("@D: Div of arithmetic operands."); case 62: return("Illegal assign variable."); case 63: return("Illegal assignment (mode incompatibility)."); case 64: return("Illegal arithmetic or logical expression."); case 65: return("Missing right parenthesis."); case 66: return("Illegal function reference.\n\ Unbalanced parentheses.\n\ Illegal array element reference."); case 67: return("Internally defined variable name used as a function or array \n\ element name."); case 68: return("Mode incompatibility in exponentiation ole statement."); case 82: return("Illegal syntax in an I/O list.\n\ Illegal implied DO\n\ Unbalanced parentheses."); case 83: return("IF contains a DO statement or another IF."); case 84: return("Multiply defined statement label."); case 85: return("A label reference contains more than five characters or\n\ contains non-numeric characters."); case 86: return("An identifier contains more than six characters."); case 87: return("An array may not have more than three dimensions."); case 88: return("A variable termination previously defined."); case 102: return("Illegal syntax in IMPLICIT statement."); case 103: return("Illegal type declaration."); case 104: return("Statement label used as a DO termination not found."); case 105: return("Number of subscripts and dimensions does not agree."); case 106: return("Syntax error in character constant."); case 107: return("Syntax error in address constant."); case 108: return("Address constant or variable used in real, double precision,\n\ complex or logical expression.cpall fort ferr /usr/bin rm fort ferr /* tough luck! */ printf("No active spool job\n"); exit(1); } } else { /* extract the job number of the active job */ read (fd, active, 5); close(fd); active[5] = '\0'; } if (job[0] == '*' || atoi(job) == atoi(active)) { /* our lad is the active spool job */ if (open(kill, 0) > -1) { /* "kill" already exists - cannot continue */ printf("Previous control function pending\n"); return; } else { /* "kill" not there - all's well */ if ((fd = creat(kill, 0ide fault"); case 33: return(".P,.M: Number of arguments do not match"); case 34: return("Illegal format syntax."); case 35: return("FORMAT: Format parentheses nested too deep.\n\ $TEST: Illegal array index or illegal DO parameter."); case 36: return("No format specification for remaining data."); case 37: return("Superfluous number in format ignored."); case 38: return("Zero or negative count in format."); case 39: return("Missing or negative d-field in format. Zero assumed."); case 40: return("Illegal chperands."); case 69: return("Illegal operand following a **."); case 70: return("Illegal operand following a +, -, *, or /."); case 71: return("Constant subscript too large."); case 72: return("Illegal unit specification.\n\ Unbalanced parentheses.\n\ Illegal format specification\n\ Illegal I/O list\n\ Illegal or non-existant Logical Unit number."); case 73: return("Illegal or non-existant Logical Unit number."); case 74: return("Mode of identifier and mode of data item do not match."); case 75: return("Numin the DO-list is not an integer.\n\ Missing equal sign\n\ Illegal delimiter."); case 89: return("Unrecognizable statement.\n\ Illegal statement in a DO-loop\n\ Specification statement occurs after the first executable statement\n\ Return statement used in the main program."); case 90: return("Illegal identifier or delimiter.\n\ An identifier may not be declared as an array because it has\n\ previously been used as a variable."); case 91: return("Illegal identifier or delimiter.\n\ An entry has been previou"); case 109: return("Address constant or variable appears in exponentiation."); case 110: return("Syntax error in hexadecimal constant."); case 111: return("Function variable not used as an assign variable within FUNCTION."); case 112: return("Trace option specified in BLOCK DATA subprogram."); case 113: return("Illegal OPTION statement."); case 114: return("Assign variable is not ADDRESS or INTEGER*4 type."); case 115: return("Address variable appears in a DATA statement."); case 116: return("Item in blan/* * opctl -- asynchronous control of the line printer daemon * and the spooled output queue. * * Written by Kenj McDonell, 20 April 1978. * */ char kill[] "/u/usr/lpd/kill"; /* used for cammands to the daemon */ char jobf[] "/u/usr/lpd/job"; /* the current spool job number */ char lpd[] "/u/usr/lpd"; /* spool directory */ char dbuf[17]; /* directory buffer */ char job[6]; /* job number of spool job to control */ char active[6]; /* active spool job number */ int jobn; 666)) == -1) { /* woops */ printf("Cannot open %s\n", kill); exit(1); } /* send the command to the daemon */ write(fd, active, 5); write(fd, &flag, 1); write (fd, "\n", 1); close(fd); return; } } /* it is not the active job */ if (flag != 'a') { /* can only abort queued jobs */ printf("Job no. %s not active\n", job); return; } /* delete all the files */ jobn = atoi(job); itoa(jobn, active); found = 0; /* scan all spool directory entries */ aracter in numeric input."); case 41: return("I/O list item in wrong mode. Value used anyway."); case 42: return("Input value underflow. Zero used."); case 43: return("Input value overflow. Maximum used."); case 44: return("Output exponent too large. Treated modulo 1000."); case 50: return("Symbol table overflow."); case 51: return("Overflow."); case 52: return("Underflow."); case 53: return("Integer constant is too large."); case 54: return("Illegal character constant."); case 55: return("Statement contain'(.4:)/5*06<+17=sly defined."); case 92: return("Unbalanced parentheses.\n\ Illegal identifier\n\ Less than two members in an equivalence list\n\ Two members of different common blocks are equivalent."); case 93: return("Illegal number of slashes.\n\ Illegal member\n\ Member is adjustably dimensioned."); case 94: return("No identifier.\n\ No array declarator\n\ Illegal identifier or delimiter\n\ An identifier may not be declared as an array because it has\n\ been used as a variable."); case 95: return("Unbalanced parenthesk COMMON used in DATA statement."); case 117: return("Mixed or invalid modes in argument list."); default: return("Unknown error number."); } } /* integer equivalent of "job" */ char flag; /* control action flag */ main(argc, argv) int argc; char *argv[]; { if (argc < 2 || *argv[1] != '-') { /* woops, syntax incorrect */ printf ("Usage: opctl [-arpc] [job no.]\n"); exit(1); } flag = *(argv[1]+1); switch (flag) { /* default => error */ default: printf("Bad option: %s\n", argv[1]); exit(1); /* all the spool job control functions */ case 'a': case 'r': case 'p': case 'c': break; /* kick the daemon */ case if ((fd = open(lpd, 0)) == -1) exit(1); if (chdir(lpd) == -1) exit(1); while (read(fd, dbuf, 16) == 16) if (dbuf[0] | dbuf[1] != 0 && dbuf[5] == active[0] && dbuf[6] == active[1] && dbuf[7] == active[2] && dbuf[8] == active[3] && dbuf[9] == active[4]) { unlink(&dbuf[2]); found = 1; } if (found == 0) printf("Cannot find spool job no. %s\n", job); return; } itoa(ival, pbuf) int ival; char *pbuf; { /* convert an integer (ival) to a 6 character, null-terminated string (pbuf) */ char *p; int j, temp; temp = ival; p = pbuf+5; *p-- = '\0'; for (j=1; j<6; j++) { *p-- = (temp%10) + '0'; temp =/ 10; } return; } while (argc > 1 && (arg = argv[1])[0] == '-') { for (i = 1; arg[i] != '\0'; i++) switch (arg[i]) { /* long format */ case 'l': lflag = 1; break; /* list all jobs */ case 'a': aflag = 1; break; /* list spool file names */ case 's': sflag = 1; break; /* bad option */ default: printf("Bad option: %s\n", argv[1]); exit(1); } argc--; argv++; } /* examine each entry in turn, looking for spool command files */ while (read(fd, dbuf, 16) =); printf(" %2d", copies); } if (sflag) printf(" (%s)", &lbuf[11]); if (lflag) printf(" %s", realfname); printf("\n"); if (lflag || sflag) continue; close(cmdbuf[0]); return; /* login person id */ case 'L': getline(person); continue; /* number of copies */ case 'N': getline(lbuf); copies = atoi(lbuf); continue; /* real file name */ case 'R': getline(realfname); continue; /* time submitted */ case 'S': getline(submitted); cothe daemon * "XXXXX" is the process id for the current * invocation of opr * "?" is 'a' for the first file argument, 'b' for the * second, 'c' for the third, etc. */ int nact; /* number of files spooled for output */ int tff; /* file descriptor for "tfaXXXXX" */ char person[20]; /* login user name */ int pid; /* process id */ int inchar; /* index to the character '?' in the file name strings */ int maxrec 1000; /* limit on the number of blocks to be copied across */ int debug; / (arg[1]) { case 'b': /* user defined banner */ q = banner; end = q+9; while ((q < end) && (*q++ = *p++)); banner[9] = '\0'; break; case 'c': /* copy file, rather than linking to it */ copyflg = 1; break; case 'd': /* set debug flag */ debug = 1; break; case 'm': /* write message after spooling */ q = mesg; end = q+30; while ((q < end) && (*q++ = *p++)); mesg[30] = '\0'; break; case 'n': /* produce more than one copy */ tty no. "n" * Fxxxx print file "xxxx" * Uxxxx unlink file "xxxx" * * output the global commands (D, L, T, N, B, X, M, T) */ if (debug) card('D',""); card('L', person); daytime[0] = ttyn(0); daytime[1] = '\0'; card('T', daytime); if (copies > 1) { itoa(copies, daytime); card ('N', daytime); } if (bcopies != 1) { itoa(bcopies, daytime); card ('X', daytime); } if (banner[0] != '\0') card('B', banner); if (mesg[0] != '\0') card('M', mesg); time(now); p = daytime; arg = ctime(n/* * opq -- interrogation of the spool queue * * Written by Kenj McDonell, April 17 1978. * */ char lpd[] "/u/usr/lpd"; /* spool directory */ char jobf[] "/u/usr/lpd/job"; /* active job number file */ char dbuf[16]; /* directory buffer */ int cmdbuf[131]; /* spool command buffer */ char lbuf[64]; /* for spool command lines */ char person[20]; /* login id of spool job submitter */ char submitted[30]; /* date/time spool job submitted */ char realfname[64]; /* real spool jo= 16) if (dbuf[0] | dbuf[1] != 0 && dbuf[2] == 'd' && dbuf[3] == 'f') { /* found a command file */ found++; job = atoi(&dbuf[5]); if (argc == 1) { /* no job numbers specified */ report(); continue; } for (i = 1; i < argc; i++) { /* test each argument for equality */ if (job == atoi(argv[i])) { report(); continue; } } } /* check for line printer not all there ... */ if (active == 0 && found > 0) printf("Line printer off-line?\n"); } report() { iFLRAGMSBN* debug flag */ int now[2]; /* the time the spool job is submitted */ int copies; /* number of copies */ int bcopies; /* number of banner pages per copy */ int copyflg; /* copy file into spool directory flag */ int remflg; /* remove file after spooling flag */ char banner[10]; /* banner heading */ char mesg[31]; /* all done message */ char daytime[30]; /* date and time string */ struct ibuf { int idev; int inum; int iflags; char inl; char iuid; char igid; char isize0; int isizif ((copies = atoi(p)) < 1) { printf ("Copies must be > 0\n"); out(); } break; case 'r': /* remove the file (if possible) after spooling */ remflg = 1; break; case 'x': /* define number of banner pages per copy */ bcopies = atoi(p); break; default: /* invalid flag */ printf ("Bad option: %s\n",arg); out(); } argc--; argv++; } /* debug */ if (debug) { printf ("pid: %l\nperson: %s\nbanner: %s\n", pid, person, banner); printf ("mesg: %s\ncopiow); while ((*p++ = *arg++) != '\n'); *--p = '\0'; card ('S', daytime); if(argc == 1) /* no input files specified as arguments .. use standard input */ copy(0); /* pick up file names and process them one at a time */ while(--argc) { arg = *++argv; /* skip empty files */ stat(arg, &fstatb); if (fstatb.isize == 0) goto df; /* output real file name */ card('R', arg); if (copyflg) /* user requested copy */ goto cf; if(link(arg, lfname) < 0) /* could not link tb file name */ struct ibuf { int idev; int inum; int iflags; char inl; char iuid; char igid; char isize0; int isize; int iaddr[8]; char *iatime[2]; char *imtime[2]; int filler; /***/ }; int active; /* active job number */ int job; /* report job number */ int copies; /* number of copies per spool file */ int lflag; /* long report format */ int sflag; /* spool file names */ int aflag; /* all jobs */ main(argc, argv) int argc; char *argv[]; { char *arg; int f; /* file nt fd; char c; int flag; struct ibuf statb; if (fopen(&dbuf[2], cmdbuf) < 0) { /* woops .. cannot access spool commands file */ printf("Cannot open %s\n", &dbuf[2]); return; } /* check owner of commands file */ if (!aflag) { stat(&dbuf[2], &statb); if (statb.iuid != getuid()) return; } flag = 1; copies = 1; submitted[0] = '\0'; realfname[0] = '\0'; person[0] = '\0'; /* loop round here extracting commands */ for (;;) { switch (c = getc(cmdbuf)) { /* print a fntinue; /* end of command file */ case -1: close(cmdbuf[0]); return; /* ignore all other commands */ default: getline(lbuf); continue; } } } /* * Read rest of line from command file */ getline(buf) char buf[]; { register char *p; register c; for (p = buf; (*p = c = getc(cmdbuf)) != '\n' && c > 0; p++) ; *p = '\0'; } e; int iaddr[8]; char *iatime[2]; char *imtime[2]; int filler; /***/ }; main(argc, argv) int argc; char *argv[]; { register char *arg; register char *p; /* pointer to string following argument flag */ register char *q; /* pointer for string copies */ register char *end; /* end of string pointer for copies */ int out(); int f; /* temporary file descriptor */ struct ibuf fstatb; /* buffer for "stat" call */ /* build file names, with process id appended */ pidfn(); /* hangup,es: %l\nremflg: %l\n", mesg, copies, remflg); printf ("copyflg: %l\n", copyflg); printf("bcopies: %l\nttyno: %c\n", bcopies, ttyn(0)); } /* * commands to the daemon * * D set debug flag * Lxxxx login id = "xxxx" * Nnn "nn" copies of each file * Bxxxx banner heading = "xxxx" * Xxxxx "xxxx" banner pages per copy * Mxxxx send message "xxxx" when job done * Rxxxx spooled file's real name is "xxxx" * Sxxxx "xxxx" is the time/date the job was submitted * Tn job submitted from o file, so must copy it */ goto cf; /* print via link, then unlink */ card('F', lfname); card('U', lfname); /* ensure next link has a unique name */ lfname[inchar]++; nact++; goto df; /* copy the file */ cf: f = open(arg, 0); if(f < 0) { printf("Cannot open %s\n", arg); continue; } copy(f); close(f); /* if "-r" specified, remove the original file */ df: if (remflg) { f = unlink(arg); if(f < 0) printf("Cannot remove %s\n", arg); } } if(nadescriptor */ int found; /* no. jobs located */ int i; int fd; /* spool directory file descriptor */ int format; /* report format flag */ /* open the directory */ if ((fd = open(lpd, 0)) == -1) { /* woops */ printf ("Cannot open %s\n", lpd); exit(1); } /* move to the spool directory */ if (chdir(lpd) < 0) exit(1); /* locate the active job, if any */ if ((f = open(jobf, 0)) != -1) { read(f, dbuf, 6); close(f); active = atoi(dbuf); } /* set up report flags */ ile */ case 'F': getline(lbuf); if (flag) { flag = 0; printf("%6d", job); if (job == active) printf("*"); else printf(" "); if (lflag) { printf(" %s", person); submitted[16] = '\0'; printf("\t%s", &submitted[4]); } } else if (lflag || sflag) { printf(" "); /* job number */ if (lflag) printf(" \t "); /* user and date/time */ } if (lflag) { if (stat(lbuf, &statb) < 0) statb.isize = 0; printf(" %9d", statb.isize/* * opr -- off line print via daemon * * modified by Kenj McDonell at University of Melbourne * April 13, 1978. */ char tfname[] "/u/usr/lpd/tfaXXXXX"; char cfname[] "/u/usr/lpd/cfaXXXXX"; char lfname[] "/u/usr/lpd/lfaXXXXX"; char dfname[] "/u/usr/lpd/dfaXXXXX"; /* * files used by the spooling subsystem * * tfaXXXXX temporary file of commands to the spooling daemon * cf?XXXXX a copy of a file to be spooled * lf?XXXXX a link to a file to be spooled * dfaXXXXX the actual commands file passed to interrupt and quit signals are trapped by "out" */ if((signal(1, 1) & 01) == 0) signal(1, out); if((signal(2, 1) & 01) == 0) signal(2, out); if((signal(3, 1) & 01) == 0) signal(3, out); /* create "tfaXXXXX" */ tff = nfile(tfname); /* initialize control variables and flags */ copies = 1; bcopies = 1; loginid(); q = banner; p = person; while (*q++ = *p++); mesg[0] = '\0'; /* scan arguments looking for flags */ while (argc>1 && (arg = argv[1])[0]=='-') { p = arg+2; switchTCIOUDJPEKQWX^djY_ct) { /* * some files have been queued .... * rename tfaXXXXX to dfaXXXXX * then "fire up" the daemon */ tfname[inchar]--; f = link(tfname, dfname); if(f < 0) { printf("Cannot rename %s\n", dfname); tfname[inchar]++; out(); } /* inform user of spool job number */ printf ("Spool job no. %l\n", pid); /* remove temporary daemon commands file */ unlink(tfname); /* fire up the daemon */ execl("/etc/lpd", "lpd", 0); /* woops */ printf("Cannot execute /etc/lpd\n"); exit(1); } /* exit here if no files were successfully queued */ out(); } copy(f) int f; { /* copy a file */ int ff, i, nr, nc; static char buf[512]; card('F', cfname); card('U', cfname); ff = nfile(cfname); nc = 0; nr = 0; while((i = read(f, buf, 512)) > 0) { write(ff, buf, i); nc =+ i; if(nc >= 512) { /* another block */ nc =- 512; nr++; if(nr > maxrec) { /* too many blocks in the copy file */ printf("Copy file is too large .. truncated after %l nal. * * remove all the files */ register i; signal(1, 1); signal(2, 1); signal(3, 1); i = inchar; while(tfname[i] != 'a') { tfname[i]--; unlink(tfname); } while(cfname[i] != 'a') { cfname[i]--; unlink(cfname); } while(lfname[i] != 'a') { lfname[i]--; unlink(lfname); } while(dfname[i] != 'a') { dfname[i]--; unlink(dfname); } exit(); } itoa(ival, pbuf) int ival; char *pbuf; { /* convert an integer (ival) to a 7 character, null-terminated string (pbuf) */ char *p; ing string */ char mesg[31]; /* end of job message to user */ char submitted[30]; /* date and time submitted */ char realfname[64]; /* real spooled file name */ char ttyno; /* tty no. spool job submitted from */ int debug; /* debug flag */ main() { register flag; extern int fout; int fd; /* Ignore quit, interrupt, hangup */ signal(1, 1); signal(2, 1); signal(3, 1); /* Use lock to prevent multiple active daemons */ if (creat(lock, 0) < 0) exit(0); /* Fork and exit, thus spre */ if (fopen(dfname, cmdbuf) < 0) return; /* * Now the command file has been successfully opened, * initialize all relvant strings and flags, then * process the commands serially. */ job = atoi(&dbuf[5]); copies = 1; bcopies = 1; banner[0] = '\0'; mesg[0] = '\0'; person[0] = '\0'; submitted[0] = '\0'; realfname[0] = '\0'; ttyno = '\0'; debug = 0; /* fetch and process commands */ for(;;) { switch (c = getc(cmdbuf)) { /* banner */ case 'B': getline(banner); ; if ((n = check(job)) != 0) { /* opctl has given us the word */ if (n == 1) goto restart; goto killed; } } /* flush the buffer before copying */ flush(); /* the output is done here */ seek (in, 0, 0); while ((len = read(in, prbuf, 512)) > 0 && write(1, prbuf, len) == len) if ((n = check(job)) != 0) { /* opctl has decreed that we restart or abort */ if (n == 1) goto restart; /* woops .. abandon the current outpuchar *p, *q; /* * Output the banner page headings. */ putchar('\014'); p = realfname; q = realfname; while (c = *q++) if (c == '/') p = q; /* 'p' points past the last '/' */ q = q-1; /* 'q' points at the end of the string */ if (q > p+9) { /* truncate from right */ q = p+9; *q = '\0'; } else if (q < p+9) { /* extend to the left */ p = q-9; if (p < realfname) p = realfname; } q = banner; if (*p != '\0') bprint(p); else if (*q != '0') bprint(q); else printf (".\n\bytes\n", nr*512+nc); break; } } } close(ff); nact++; } card(c, s) int c; char s[]; { char *p1, *p2; static char buf[512]; int col; p1 = buf; p2 = s; col = 0; *p1++ = c; while((c = *p2++) != '\0') { *p1++ = c; col++; } *p1++ = '\n'; write(tff, buf, col+2); } loginid() { /* extract the user's login id, and return it via 'person' */ register char *bp, *pp; static char buf[50]; bp = buf; if(getpw((getuid() & 0377), bp)) { bp = "who?:"; } pp = person; while((*pp++ = *int j, temp; temp = ival; p = pbuf+6; *p-- = '\0'; for (j=1; j<7; j++) { *p-- = (temp%10) + '0'; temp =/ 10; } return; } awning the daemon and letting opr terminate */ if (fork()) exit(0); /* Before opening the printer, make sure there's something to print */ close(0); close(1); close(2); /* * assumes following file descriptor assignments will occur OK * 0 - spool directory * 1 - printer */ if (open(lpd, 0) != 0) dexit(); flag = 0; while (read(0, dbuf, 16) == 16) if ((dbuf[0] | dbuf[1]) != 0 && dbuf[2] == 'd' && dbuf[3] == 'f') flag++; if (!flag) dexit(); /* Open the printer */ if continue; /* set debug flag */ case 'D': debug = 1; continue; /* output a file */ case 'F': getline(lbuf); if ((in = open(lbuf, 0)) < 0) continue; if (debug) { printf ("job: %l\n", job); printf ("person: %s\n", person); printf("ttyno: %c\n", ttyno); printf ("real file: %s\n", realfname); printf ("banner: %s\n", banner); printf ("banner copies: %l\n", bcopies); printf ("submitted: %s\n", submitted); printf ("released: %s\n", daytime); printt file */ killed: p = &dbuf[5]; q = &amesg[14]; while (*q++ = *p++); *--q = ' '; sendmesg(person, ttyno, amesg); printf("\n\n* * * Spool Job Aborted * * *\n"); copyno = copies; break; } /* eject the last page */ putchar('\014'); } close(in); continue; /* login user id */ case 'L': getline(person); continue; /* end of job message */ case 'M': getline(mesg); continue; /* number of copies */ case 'N'n\n\n\n\n\n\n\n\n\n\n\n"); chars(' '); chars('!'); chars('"'); printf ("\n\n"); printf ("Computer Science Department, Melbourne University\n\n"); printf ("\t\tSpool Job Number: %l\n", job); printf ("\t\tSubmitted: %s\n\t\tReleased: %s\n", submitted, daytime); printf ("\t\tCopy %l of %l\n\n\n", copyno, copies); chars('#'); chars('$'); chars('%'); printf("\n\n"); /* print the banner if it did not appear at the top of the page */ if (*p != '\0' && *q != '\0') bprint(q); putchar('\014');bp++) != ':'); *--pp = '\0'; } pidfn() { /* build file names, with process id appended */ register i, j, c; int p; /* get process id */ pid = getpid(); p = pid; i = 0; while(tfname[i] != 'X') i++; i =+ 4; /* insert process id as last 5 characters of the file names */ for(j=0; j<5; j++) { c = (p%10) + '0'; p =/ 10; tfname[i] = c; cfname[i] = c; lfname[i] = c; dfname[i] = c; i--; } inchar = i; } nfile(name) char *name; { register f; /* create a new file */ f = crea/* * Line printer daemon * * Modified by Kenj McDonell, 14 April 1978 * */ /* File names */ char lpd[] "/u/usr/lpd"; /* spooler directory */ char lock[] "/u/usr/lpd/lock"; /* existence of this file prevents multiple, concurrent daemons */ char printer[] "/dev/pr"; char kill[] "/u/usr/lpd/kill"; /* kill/restart/pause/continue current job flag */ char jobf[] "/u/usr/lpd/job"; /* current spool job no. written here */ char tty[] "/dev/tty?"; /* spool job owner's terminal */ char amesg[] "Spoo (open(printer, 1) != 1) dexit(); dup(1); fout = dup(1); /* Search lpd directory for work to do */ if (chdir(lpd) < 0) dexit(); seek(0, 0, 0); while (read(0, dbuf, 16) == 16) { if ((dbuf[0] | dbuf[1]) == 0 || dbuf[2] != 'd' || dbuf[3] != 'f') continue; /* * Process one command file. * First write the spool job number into "jobf". */ if ((fd = creat(jobf, 0666)) != -1) { write (fd, &dbuf[5], 5); write (fd, "\n", 1); } spool(&dbuf[2]); /* * All done, nowekZ`fl[am\bhn]ciopv: getline(lbuf); copies = atoi(lbuf); continue; /* real file name */ case 'R': getline(realfname); continue; /* time submitted */ case 'S': getline(submitted); continue; /* tty no. */ case 'T': getline(lbuf); ttyno = lbuf[0]; continue; /* number of banner pages per copy */ case 'X': getline(lbuf); bcopies = atoi(lbuf); continue; /* Delete file after copying */ case 'U': getline(lbuf); unlink(lbuf); continue; /* end of return; } check(job) int job; { /* * Check if opctl has sent us a message */ int fd, paused, killjob; paused = 0; again: if ((fd = open(kill, 0)) != -1) { /* "kill" file exists */ read(fd, killbuf, 6); killjob = atoi(killbuf); /* get rid of the file */ close(fd); unlink(kill); if (killjob == job) { /* this is really meant for me! */ /* the following control functions are supported :- * 'p' pause the cUrrent job * 'a' abort the current job * 'c' continue the ct(name, 0666); if(f < 0) { printf("Cannot create %s\n", name); out(); } /* * increment the 6th last character of the file name * -- this is required if multiple files are spooled in a single * execution of opr. * The resultant files names are of the form * .....aXXXXX, .....bXXXXX, .....cXXXXX, .....dXXXXX, etc */ name[inchar]++; return(f); } out() { /* * come here following :- * a) no files successfully queued * b) a fatal error * c) a hangup, interrupt, or quit sigl job no. XXXXX aborted"; char rmesg[] "Spool job no. XXXXX restarted"; /* Buffers */ int cmdbuf[131]; /* for reading command file */ char prbuf[512]; /* for copying file to printer */ char lbuf[64]; /* for assembling lines from command file */ char dbuf[17]; /* for reading directory */ char killbuf[8]; /* commands from opctl */ char person[20]; /* login user name */ char now[2]; /* used to fetch current time */ char daytime[30]; /* date and time string */ char banner[10]; /* banner head remove the job no. and command files */ close (fd); unlink(jobf); unlink(&dbuf[2]); /* Reread directory in case it changed while we were spooling */ seek(0, 0, 0); } dexit(); } /* * Remove job no. and lock files, and terminate */ dexit() { unlink(jobf); unlink(lock); exit(0); } /* * Read and obey a file of spooling commands */ spool(dfname) char *dfname; { register in, len, c; int job, copies, copyno; int bcopies, j, n; char *p, *q; /* * All the work is really done in hef ("copies: %l\n", copies); } for (copyno = 1; copyno <= copies; copyno++) { goto newcopy; restart: /* current job has been restarted */ p = &dbuf[5]; q = &rmesg[14]; while (*q++ = *p++); *--q = ' '; sendmesg(person, ttyno, rmesg); printf("\n\n* * * Spool Job Restarted * * *\n"); newcopy: time(now); p = daytime; q = ctime(now); while ((*p++ = *q++) != '\n'); *--p = '\0'; for (j = 0; j < bcopies; j++) { bannerpage(job, copyno, copies) command file */ case -1: close(cmdbuf[0]); flush(); sendmesg(person, ttyno, mesg); return; /* unidentified command */ default: getline(lbuf); /* just ignore it */ continue; } } close(cmdbuf[0]); } /* * Read rest of line from command file */ getline(buf) char buf[]; { register char *p; register c; for (p = buf; (*p = c = getc(cmdbuf)) != '\n' && c > 0; p++) ; *p = '\0'; } bannerpage(job, copyno, copies) int job, copyno, copies; { int j; char c; register urrent job * 'r' restart the current job */ switch (killbuf[5]) { /* pause */ case 'p': paused = 1; break; /* abort */ case 'a': /* abort this print file */ return(-1); /* continue */ case 'c': return(0); /* restart */ case 'r': return(1); } } /* note: if "kill" does not refer to the current spool job, ignore it */ } /* is paused, wait for 5 seconds and try again, else return */ if (paused) { sleep(5); paused++; if (paused < 24) goto again; /* waited too long ... abort him */ return(-1); } return(0); } chars(c) char c; { /* * Print a line of 128 characters, starting with 'c' */ int j; char ch; ch = c; for (j = 0; j < 128; j++) { putchar(ch++); if (ch > '~') ch = ' '; } putchar('\n'); } sendmesg(loginid, ttyno, message) char loginid[]; char ttyno; char message[]; { /* * Send a message to a user */ int fd, len; register char *p, *q; if (ttyno == 'x') return; if (message[0] !/* * Banner character set, 12x16 (Danny Companez, Robert Elz, * Melbourne University) */ # define CHEIGHT 16 # define CWIDTH 12 # define CDEPTH 6 # define CSPACE 2 # define LWIDTH 132 # define FILL '*' # define SPACE ' ' short chset[96][16] = { 0x0, /* ' ' */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x060, /* ! */ 0x060, 0x060, 0x0f0, 0x0f0, 0x0f0, 0x0f0, 0x0f0, 0x060, 0x060, 0x060, 0x060, 0x000, 0x060, 0x0f0, 0x060, 0x198, /* " */ 0x198, 0x198, 0x 0x0e0, 0x1f0, 0x1f0, 0x0e0, 0x001, /* / */ 0x003, 0x003, 0x007, 0x00e, 0x01c, 0x038, 0x070, 0x0e0, 0x1c0, 0x380, 0x700, 0xe00, 0xc00, 0xc00, 0x800, 0x7fe, /* 0 */ 0xfff, 0xc03, 0xc0b, 0xc13, 0xc23, 0xc43, 0xc83, 0xd03, 0xe03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0x7fe, 0x060, /* 1 */ 0x0e0, 0x1e0, 0x160, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x3fc, 0x3fc, 0x7fe, /* 2 */ 0xfff, 0x803, 0x003, 0x003, 0x006, 0x00c, 0x038, 0x0e0, 0x1c0, 0x300, 0x600, 0xc00, 0xc00, 0xfffqw}rx~ytzu{c0e, 0xc07, 0xc00, /* L */ 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xfff, 0xfff, 0xc03, /* M */ 0xe07, 0xf0f, 0xf0f, 0xf9f, 0xd9b, 0xdfb, 0xcf3, 0xc63, 0xc63, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, /* N */ 0xc03, 0xe03, 0xf03, 0xf83, 0xdc3, 0xce3, 0xc73, 0xc3b, 0xc1f, 0xc0f, 0xc07, 0xc03, 0xc03, 0xc03, 0xc03, 0x7fe, /* O */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0x7fe, 0xffe, x070, 0x038, 0x01c, 0x00e, 0x007, 0x003, 0x000, 0x000, 0x7f0, /* ] */ 0x7f0, 0x030, 0x030, 0x030, 0x030, 0x030, 0x030, 0x030, 0x030, 0x030, 0x030, 0x030, 0x030, 0x7f0, 0x7f0, 0x060, /* ^ */ 0x0f0, 0x1f8, 0x36c, 0x666, 0x462, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x000, /* _ */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0xfff, 0x0c0, /* ` */ 0x0c0, 0x060, 0x030, 0x010, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, = '\0' && (fd = open("/etc/utmp", 0)) != -1) { /* something to do */ while ((len = read(fd, lbuf, 24)) == 24) if (lbuf[0] != '\0') { p = loginid; q = lbuf; while (*p++ == *q++); if (*--p == '\0' && lbuf[8] == ttyno) { tty[8] = lbuf[8]; close(fd); if ((fd = open(tty,1)) != -1) { p = message; while (*p != '\0') write (fd, p++, 1); write (fd, "\n", 1); close(fd); } return; } } close(fd); } return; } 090, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* # */ 0x020, 0x060, 0x062, 0x7c6, 0x3e6, 0x0fe, 0x19f, 0xf98, 0x7f0, 0x67c, 0x63e, 0x460, 0x060, 0x040, 0x000, 0x090, /* $ */ 0x090, 0x7fe, 0xfff, 0xc90, 0xc90, 0xc90, 0xffe, 0x7ff, 0x093, 0x093, 0x093, 0xfff, 0x7fe, 0x090, 0x090, 0x060, /* % */ 0x096, 0x096, 0x066, 0x00c, 0x018, 0x030, 0x060, 0x060, 0x0c0, 0x180, 0x300, 0x660, 0x690, 0x690, 0x060, 0x000, /* & */ 0x060, 0x090, 0x118, 0x318, 0x310, 0, 0xfff, 0x7fe, /* 3 */ 0xfff, 0x803, 0x003, 0x003, 0x003, 0x003, 0x0fe, 0x0fe, 0x003, 0x003, 0x003, 0x003, 0x803, 0xfff, 0x7fe, 0x00c, /* 4 */ 0x01c, 0x03c, 0x06c, 0x0cc, 0x18c, 0x30c, 0x60c, 0xc0c, 0xfff, 0xfff, 0x00c, 0x00c, 0x00c, 0x00c, 0x00c, 0xfff, /* 5 */ 0xfff, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xffe, 0xfff, 0x003, 0x003, 0x003, 0x003, 0x803, 0xfff, 0x7fe, 0x07c, /* 6 */ 0x0fc, 0x180, 0x300, 0x600, 0xc00, 0xc00, 0xc00, 0xffc, 0xffe, 0xc03, 0xc03, 0xc03, 0xc03, 0x7fe, 0x3fc, 0xfff, /, 0x018, 0x030, 0x060, 0x0c0, 0x180, 0x180, 0x000, 0x180, 0x3c0, 0x180, 0x000, /* @ */ 0x3fe, 0x7ff, 0xc03, 0xcfb, 0xdfe, 0xd8c, 0xd8c, 0xd8c, 0xd8c, 0xdfe, 0xcf6, 0xc00, 0x7ff, 0x3fe, 0x000, 0x7fe, /* A */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xffe, /* B */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xffe, 0xffe, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0xffe, 0x7fe, /* C */ 0xfff, 0xc01, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc0 /* P */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0xffe, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0x7fe, /* Q */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc33, 0xc3b, 0xc1f, 0xc0e, 0xfff, 0x7fb, 0xffe, /* R */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0xffe, 0xce0, 0xc70, 0xc38, 0xc1c, 0xc0e, 0xc07, 0xc03, 0x7fe, /* S */ 0xfff, 0xc01, 0xc00, 0xc00, 0xc00, 0xc00, 0xffe, 0x7ff, 0x003, 0x003, 0x003, 0x003, 0x803, 0xfff, 0x7fe, 0xfff, /* T */ 0xfff, 0x00x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* a */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x3fe, 0x7ff, 0x803, 0x003, 0x3ff, 0x7ff, 0xc03, 0xc03, 0x7ff, 0x3fd, 0x000, /* b */ 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xdfc, 0xffe, 0xe03, 0xc03, 0xc03, 0xc03, 0xc03, 0xe03, 0xbfe, 0x9fc, 0x000, /* c */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x3fc, 0x7fe, 0xc01, 0xc00, 0xc00, 0xc00, 0xc00, 0xc01, 0x7fe, 0x3fc, 0x000, /* d */ 0x003, 0x003, 0x003, 0x003, 0x003, 0x3fb, 0x7ff, 0xc07, 0xc03, 0xc03, 0xc03, 0xc03, 0xc07,#include "chset.h" bprint(s) char *s; { register w, line, c, realh; register char *p; register int col, h; do { for (h=0; h LWIDTH) break; if (c < ' ') c = ' '; realh = h; switch (c) { case 'g': case 'j': case 'p': case 'q': case 'y': case ',': case ';': realh = h - CDEPTH; } if (realh<0 || realh >= CHEIGHT) x320, 0x140, 0x080, 0x140, 0x320, 0x314, 0x108, 0x094, 0x062, 0x000, 0x030, /* ' */ 0x030, 0x060, 0x0c0, 0x080, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x004, /* ( */ 0x008, 0x010, 0x030, 0x060, 0x060, 0x0e0, 0x1c0, 0x1c0, 0x0e0, 0x060, 0x060, 0x030, 0x010, 0x008, 0x004, 0x200, /* ) */ 0x100, 0x080, 0x0c0, 0x060, 0x060, 0x070, 0x038, 0x038, 0x070, 0x060, 0x060, 0x0c0, 0x080, 0x100, 0x200, 0x000, /* * */ 0x000, 0x000, 0x606, 0x30c, 0x198, 0x0f0, 0x7fe, 0x7fe, * 7 */ 0xfff, 0x003, 0x003, 0x006, 0x00c, 0x018, 0x030, 0x060, 0x0c0, 0x180, 0x300, 0x600, 0xc00, 0xc00, 0xc00, 0x7fe, /* 8 */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0x7fe, 0x7fe, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0x7fe, 0x7fe, /* 9 */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0x7fe, 0x006, 0x00c, 0x018, 0x030, 0x060, 0x0c0, 0x380, 0x300, 0x000, /* : */ 0x000, 0x000, 0x060, 0x0f0, 0x0f0, 0x060, 0x000, 0x000, 0x060, 0x0f0, 0x0f0, 0x060, 0x000, 0x000, 0x000, 0x000, /* ; */ 0x1c0, 0x3e0,0, 0xc00, 0xc00, 0xc00, 0xc00, 0xc01, 0xfff, 0x7fe, 0xffe, /* D */ 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0xffe, 0xfff, /* E */ 0xfff, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xff8, 0xff8, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xfff, 0xfff, 0xfff, /* F */ 0xfff, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xff8, 0xff8, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0x7fe, /* G */ 0xfff, 0xc01, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc0f, 0xc0f, 0xc60, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0xc03, /* U */ 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0x7fe, 0xc03, /* V */ 0xc03, 0xc03, 0xc03, 0xc03, 0xe07, 0xe07, 0x70e, 0x70e, 0x39c, 0x39c, 0x1f8, 0x0f0, 0x0f0, 0x060, 0x060, 0xc03, /* W */ 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc63, 0xc63, 0xcf3, 0xcf3, 0xdfb, 0xd9b, 0xf9f, 0xf9f, 0xf0f, 0x606, 0xc03, /* X */ 0xc03, 0xe07, 0x70e, 0x39c, 0x 0x7fd, 0x3f9, 0x000, /* e */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x3fc, 0x7fe, 0xc03, 0xc03, 0xffe, 0xffc, 0xc00, 0xc00, 0x7fe, 0x3fc, 0x000, /* f */ 0x000, 0x3fc, 0x7fe, 0xc01, 0xc00, 0xc00, 0xc00, 0xff0, 0xff0, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0x3fc, /* g */ 0x7fe, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0x7ff, 0x3ff, 0x003, 0x803, 0x7fe, 0x3fc, 0x000, 0x000, 0x000, /* h */ 0x000, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xcfc, 0xdfe, 0xe07, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0x00 line = 0; else line = chset[c-' '][realh]; for (w = 1<<(CWIDTH-1); w; w>>=1) putchar(w&line? FILL : SPACE); for (w = 0; w < CSPACE; w++) putchar(SPACE); } putchar('\n'); } } while (*(s = p)); } 0x0f0, 0x198, 0x30c, 0x606, 0x000, 0x000, 0x000, 0x000, /* + */ 0x000, 0x000, 0x060, 0x060, 0x060, 0x060, 0x7fe, 0x7fe, 0x060, 0x060, 0x060, 0x060, 0x000, 0x000, 0x000, 0x000, /* , */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x1c0, 0x3e0, 0x3e0, 0x1e0, 0x0c0, 0x080, 0x100, 0x000, 0x000, 0x000, 0x000, /* - */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x7fe, 0x7fe, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* . */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x3e0, 0x1c0, 0x000, 0x1c0, 0x3e0, 0x3e0, 0x1e0, 0x0c0, 0x080, 0x100, 0x000, 0x000, 0x000, 0x000, /* < */ 0x00c, 0x018, 0x030, 0x060, 0x0c0, 0x180, 0x300, 0x300, 0x180, 0x0c0, 0x060, 0x030, 0x018, 0x00c, 0x000, 0x000, /* = */ 0x000, 0x000, 0x000, 0x000, 0x7fe, 0x7fe, 0x000, 0x000, 0x7fe, 0x7fe, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, /* > */ 0x300, 0x180, 0x0c0, 0x060, 0x030, 0x018, 0x00c, 0x00c, 0x018, 0x030, 0x060, 0x0c0, 0x180, 0x300, 0x000, 0x060, /* ? */ 0x0f0, 0x198, 0x198, 0x018, 0x01803, 0xc03, 0xc03, 0xfff, 0x7fe, 0xc03, /* H */ 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xfff, 0xfff, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0x1f8, /* I */ 0x1f8, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x1f8, 0x1f8, 0x003, /* J */ 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x803, 0xfff, 0x7fe, 0xc07, /* K */ 0xc0e, 0xc1c, 0xc38, 0xc70, 0xce0, 0xdc0, 0xf80, 0xf80, 0xfc0, 0xce0, 0xc70, 0xc38, 0xc1c, 0x1f8, 0x0f0, 0x060, 0x060, 0x0f0, 0x1f8, 0x39c, 0x70e, 0xe07, 0xc03, 0xc03, 0xc03, /* Y */ 0xe07, 0x70e, 0x39c, 0x1f8, 0x0f0, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0xfff, /* Z */ 0xfff, 0x003, 0x007, 0x00e, 0x01c, 0x038, 0x070, 0x0e0, 0x1c0, 0x380, 0x700, 0xe00, 0xc00, 0xfff, 0xfff, 0x0fe, /* [ */ 0x0fe, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0fe, 0x0fe, 0x000, /* \ */ 0x000, 0xc00, 0xe00, 0x700, 0x380, 0x1c0, 0x0e0, 00, /* i */ 0x000, 0x000, 0x060, 0x0f0, 0x060, 0x000, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x078, 0x030, 0x006, /* j */ 0x006, 0x006, 0x006, 0x006, 0x006, 0x006, 0x006, 0x006, 0x006, 0xc0c, 0x618, 0x3f0, 0x1e0, 0x000, 0x000, 0x000, /* k */ 0x000, 0xc00, 0xc00, 0xc00, 0xc07, 0xc0e, 0xc78, 0xff0, 0xfe0, 0xe70, 0xc38, 0xc0c, 0xc06, 0xc03, 0xc03, 0x000, /* l */ 0x000, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c4, 0x078, 0x030, 0x000, /* m */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x108, 0x39c, 0x6f6, 0xc63, 0xc63, 0xc63, 0xc03, 0xc03, 0xc03, 0xc03, 0x000, /* n */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x8f8, 0x9fc, 0xb06, 0xe03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0x000, /* o */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x060, 0x0f0, 0x39c, 0x606, 0xc03, 0xc03, 0x606, 0x39c, 0x0f0, 0x060, 0x8f0, /* p */ 0x9f8, 0xb0c, 0xe06, 0xc03, 0xc03, 0xe06, 0xf0c, 0xdf8, 0xcf0, 0xc00, 0xc00, 0xc00, 0xc00, 0x000, 0x000, 0x0f1, /* q */ 0x1f9, 0x30d, 0x607, 0xc03,20, 0x070, 0x1f8, 0x000, /* ~ */ 0x000, 0x000, 0x000, 0x000, 0x100, 0x382, 0x6e2, 0x476, 0x41c, 0x008, 0x000, 0x000, 0x000, 0x000, 0x000, 0x0, /* del */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; /* * Assembler common data * * * Copyright (C) 1978, Richard Miller */ /* * Lexical tokens - returned by token() */ #define GARBAGE 0 /* unknown character */ #define PLUS 1 /* + */ #define MINUS 2 /* - */ #define OR 3 /* ! */ #define AND 4 /* & */ #define STAR 5 /* * */ #define SLASH 6 /* / */ #define BINOP 6 /* last binary operator */ #define EOL 7 /* end of line */ #define SPACE 8 /* blanks and/or tabs */ #define COMMA 9 /* , */ #define LPAREN 10 /* ( */ #define RPAREN 11 /* ) */ #define APAR 12character */ #define errh 'H' /* halfword value too large */ #define erri 'I' /* improper nesting of IFx, COMN or STRUC */ #define errl 'L' /* missing label */ #define errm 'M' /* multiply defined symbol */ #define errn 'N' /* number syntax */ #define erro 'O' /* org to illegal address */ #define errp 'P' /* symbol value changed between passes */ #define errq 'Q' /* missing quote */ #define errr 'R' /* relocation error */ #define errs 'S' /* missing symbol */ #define erru 'U' /* undefined symbol */ #define ons of relocatable symbols are permitted */ EXTERN int lflag; /* make listing to std output */ EXTERN int opt; /* SQUEZ optimization: [arg] -1: NORX3 -s1 0: NOSQUEZ -s0 1: SQUEZ (default) -s2 */ EXTERN int bdata; /* Block Data program */ EXTERN int line; /* input line number */ EXTERN int errcnt; /* no. of errors */ EXTERN int pass; /* pass number */ EXTERN int passg; /* code-generation pass flag */ EXTERN int passl; /* listing pass flag */ EXTERN int docount; /* counter f 0xc03, 0x607, 0x30f, 0x1fb, 0x0f3, 0x003, 0x003, 0x003, 0x003, 0x000, 0x000, 0x000, /* r */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x8fc, 0x9fe, 0xb03, 0xe01, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0xc00, 0x000, /* s */ 0x000, 0x000, 0x000, 0x000, 0x000, 0x3fc, 0x7fe, 0xc03, 0xc00, 0x7fc, 0x3fe, 0x003, 0xc03, 0x7fe, 0x3fc, 0x000, /* t */ 0x000, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x3f0, 0x3f0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c0, 0x0c4, 0x078, 0x030, 0x000, /* u */ 0x000, 0x000, 0x000, 0x000, 0x000, 0xc03, 0xc03cc -o lpd lpd.c bprint.c cc -o opctl opctl.c cc -o opq opq.c cc -o opr opr.c /* A( */ #define ZPAR 13 /* Z( */ #define CON 14 /* constant - value in conbuf */ #define HCON 15 /* halfword constant - value in conbuf */ #define STRING 16 /* C'...' - string & length in strbuf & strlen */ #define SYMBOL 17 /* symbol - name in symbuf */ /* * Segment relocation bits -- used in a.out relocation sections */ #define RUNDEF (-1) /* undefined -- internal only */ #define RABS 00 /* absolute */ #define RTEXT 02 /* text = PURE */ #define RDATA 04 /* data = IMPUR */ #define RBSS 06 /* bss */ #derrv 'V' /* illegal value (e.g. register >15) */ #define errx 'X' /* syntax error */ #define errz 'Z' /* division by zero */ /* * a.out file header */ EXTERN struct { int mword; /* 'magic word' */ int tsize; /* size of text (rounded to word) */ int dsize; /* " data " */ int bsize; /* " bss " */ int ssize; /* size of symbol table */ int entrypt; /* entry point (NOT IMPLEMENTED) */ int unused; int rflag; /* relocation bits suppressed */ } hdr; /* * Parser information */ EXTERN int dcflag; /b; /* label of current line */ EXTERN struct symbol *usymtab; /* first user-defined symbol entry */ EXTERN struct symbol *symtop; /* end of allocated symbol storage */ EXTERN struct symbol *nextsym; /* next available symbol entry */ EXTERN int symseek; /* seek address for symbol table */ /* * Segment information */ #define OBSIZE 512 /* size of output buffers (must be even) */ EXTERN struct segment { int loc; /* location counter */ int maxloc; /* highest address so far */ int nchar; /* numberor DO loops */ , 0xc03, 0xc03, 0xc03, 0xc03, 0xe07, 0x70f, 0x3fd, 0x1f9, 0x000, /* v */ 0x000, 0x000, 0x000, 0x000, 0x000, 0xc03, 0xc03, 0xc03, 0xc03, 0x606, 0x606, 0x30c, 0x198, 0x0f0, 0x060, 0x000, /* w */ 0x000, 0x000, 0x000, 0x000, 0x000, 0xc03, 0xc03, 0xc03, 0xc03, 0xe07, 0x666, 0x666, 0x36c, 0x1f8, 0x090, 0x000, /* x */ 0x000, 0x000, 0x000, 0x000, 0x000, 0xc03, 0xe07, 0x30c, 0x198, 0x0f0, 0x0f0, 0x198, 0x30c, 0xe07, 0xc03, 0xc03, /* y */ 0xc03, 0xc03, 0xc03, 0xc03, 0xc03, 0x607, 0x30f, 0x1fb, 0x0f3, 0x60cp lpd /etc cp opr /bin cpall opctl opq /usr/bin rm *.o rm lpd opctl opq opr efine REXT 010 /* external reference -- bits 15-4 contain symbol number */ #define RSEG 017 /* Mask for segment */ #define RHI 01 /* high-order halfword of a relocatable word -- next halfword in relocation bits contains nonzero: fullword relocatable address zero: 3-byte relocatable address */ /* * Symbol types */ #define SUNDEF 00 /* undefined */ #define SABS 01 /* absolute */ #define STEXT 02 /* text */ #define SDATA 03 /* data */ #define SBSS 04 /* bss */ #define SCOMN 05 /* offse* DC-type instruction - a() constants legal */ EXTERN int nexttoken; /* look-ahead token */ EXTERN int conbuf; /* returned value of last constant */ EXTERN char strbuf[64]; /* returned value of last string */ EXTERN int strlen; /* returned length of last string */ EXTERN char symbuf[8]; /* returned name of last symbol */ /* * Expression evaluation */ EXTERN struct exp { int rel; /* relocatability of expression */ int val; /* value of expression */ int half; /* 16-bit flag (only used in DC) */ } of chars in buffers */ int tseek; /* seek address for text buffer */ int rseek; /* seek address for relocation bits buffer */ char tbuf[OBSIZE]; /* text buffer */ char rbuf[OBSIZE]; /* relocation bits buffer */ } pure, impure; EXTERN struct vsegment { /* virtual segment - no buffers */ int loc; /* location counter */ int maxloc; /* highest address so far */ } bss, comm; EXTERN struct segment *curseg; /* current segment */ EXTERN int currel; /* current relocatability */ EXTERN struct symbol */* * Assembler mainline * * * Copyright (C) 1978, Richard Miller */ #define EXTERN #include "as.h" char *ofname = "a.out"; /* default object filename */ char **ifiles; /* list of input filenames */ int cfile; /* index of current input filename */ int nifiles; /* number of input files */ int iopt = 1; /* default: full SQUEZ optimization */ extern int (*oproutine[])(); /* branch table to opcode routines */ char usage[] = "Usage: ras [-u] [-m] [-sN] [-o object-file] input-file [...]\n"; /* 6, 0x30c, 0x1f8, 0x0f0, 0x000, 0x000, 0x000, /* z */ 0x000, 0x000, 0x000, 0x000, 0x000, 0xfff, 0xfff, 0x003, 0x00e, 0x078, 0x1e0, 0x700, 0xc00, 0xfff, 0xfff, 0x1f8, /* { */ 0x0e0, 0x040, 0x0c0, 0x080, 0x040, 0x1c0, 0xfc0, 0xfc0, 0x1c0, 0x040, 0x080, 0x0c0, 0x040, 0x0e0, 0x1f8, 0x060, /* | */ 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x060, 0x1f8, /* } */ 0x070, 0x020, 0x030, 0x010, 0x020, 0x038, 0x03f, 0x03f, 0x038, 0x020, 0x010, 0x030, 0x0This is a new printer spooler by Ken McDonell, University of Melbourne. chset.h - BIG character set for banner page bprint.c - banner subroutine for lpd lpd.c - line printer daemon with "operator interface" opr.c - print spooler opq.c - command to look at print queue opctl.c - command to control print queue & daemon t in common block -- internal only bits 31-8 contain symbol number of block name */ #define SSEG 07 /* mask for segment */ #define SEXT 040 /* external (global) symbol */ /* * Error types */ #define erra 'A' /* previously defined absolute value required */ #define errb 'B' /* short branch out of range */ #define errc 'C' /* illegal or missing opcode */ #define errd 'D' /* illegal data in COMN, STRUC or BSS */ #define erre 'E' /* eof or END within DO, COMN, STRUC or IFx */ #define errg 'G' /* garbage exp; /* * Symbol table information */ struct symbol { /* user-defined symbol */ struct symbol *next; /* chain to next symbol with same hash code (must be first field -- see symlook()) */ char name[8]; /* left-justified, zero-padded */ int type; /* relocatability type */ int value; }; struct optab { /* opcode symbol */ struct symbol *next; char name[8]; int opval; /* value of opcode */ }; EXTERN struct symbol *cursym; /* most recently looked-up symbol */ EXTERN struct symbol *curlacurcomm; /* current COMN or STRUC name */ /* * Conditional assembly information */ EXTERN int noasm; /* assembly turned off by simple IF */ EXTERN int ifnest; /* nesting level of compoiund IF */ EXTERN int ifcount; /* no. of ENDC's required to resume assembly */ EXTERN int endswitch; /* END statement encountered */ /* * Global information & flags */ EXTERN int ofile; /* fd of object file */ EXTERN int ucase; /* translate upper-case symbols to lower-case */ EXTERN int mflag; /* multiple definiti* Main program - initialize; call assembly passes; terminate * - pass 0: build symbol table * - pass 1: 'optimize' by building a bitmap of instructions which can * be squeezed to shorter forms * - pass 2: generate a.out file * All three passes re-read and re-parse the source code. * Any assembly error prevents further passes. */ main(argc, argv) char **argv; { register c; extern fout; int symout(); /* * Get flags & files */ while (--argc > 0 && **++argv == '-') { switch (argv[0][1]) { case 'u': ucase++; break; case 'm': mflag++; break; case 'l': lflag++; break; case 'o': if (--argc == 0 || **++argv == '-') { printf("No object filename\n"); exit(1); } ofname = *argv; break; case 's': if ((c = argv[0][2]) == '0') iopt = 0; /* NOSQUEZ */ else if (c == '1') iopt = -1; /* NORX3 */ break; } } if ((nifiles = argc) < 1) { printf(usage); exit(1); } ifiles = argv; /* * Enter opcodes into symbol table */ syminit(); /* != SPACE) xerror(errx); /* * a line with nothing but white space is a comment */ if (!curlab && eol()) continue; /* * get opcode */ if (!getsym()) xerror(errc); if (symlook(0)) { /* built-in opcode */ optype = SABS; op = ((struct optab *)cursym)->opval; } else if (symlook(1)) { /* user-defined opcode */ optype = cursym->type; op = cursym->value; } else { /* undefined opcode */ optype = SUNDEF; op = 0; } /* * If conditional assembly off, ignore d abort current line */ xerror(type) { error(type); nexttoken = 0; reset(); } egister nl; register char *p; register c, ncol; scanp = p = linebuf; lstinit(); /* * If previous statement was DO, decrement the count and re-use * the same buffer */ if (docount-- > 0) return('\n'); else docount = 0; ncol = 71; for (nx = next, nl = nleft; ;) { if (--nl < 0) { while ((nl = read(0, ibuf, sizeof ibuf)-1) < 0) if (!nextfile()) return(0); nx = ibuf; } if ((*p = *nx++) == '\n') { p[1] = '\0'; next = nx; nleft = nl; line++; return('\n'); = p; return(SPACE); /* * don't scan past end of line */ case EOL: scanp = --p; return(EOL); /* * stupid special case: "//" is a legal label in a COMN statement */ case SLASH: if (*p == '/' && p == &linebuf[1]) { enter("//"); scanp = ++p; return(SYMBOL); } return(SLASH); /* * single-character tokens */ default: return(ctype); } } /* * Scan a decimal or hexadecimal number (with optional sign) * from input line */ getnum(base) register base; { register char *p;und */ getsym() { register c, ctype; register char *p, *s; p = scanp; if (!((ctype = ctab[c = *p]) & C_ALPHA)) return(0); s = symbuf; ((int *)s)[0] = ((int *)s)[1] = 0; do { if (s < &symbuf[sizeof symbuf]) { if (ucase && (ctype&C_UPPER)) c += 'a'-'A'; *s++ = c; } } while ((ctype = ctab[c = *++p])&(C_ALPHA|C_HEXDIGIT)); scanp = p; return(1); } /* * Determine whether scan pointer is at end of line */ eol() { register c; return((c = ctab[*scanp]) == EOL || c== SPACE); } /* * Symbol definition pass */ assemble(); if (errcnt) exit(errcnt); /* * Squeeze pass */ pass++; sqzalloc(); assemble(); if (errcnt) exit(errcnt); /* * Code generation pass(es) * - more than one pass may be required in pathological cases * where squeezed instructions must be unsqueezed. * Since each pass can only make instructions longer, the * process is guaranteed to terminate eventually. */ do { if ((ofile = creat(ofname, 0666)) < 0) { printf("%s: can't create\nall but conditional * assembly pseudo-ops */ if ((noasm|ifcount) && (op&0xf)!=9) continue; if (optype != SABS) xerror(errc); if ((t = token()) != SPACE && t != EOL) xerror(errx); /* * call opcode routine to parse the operands */ (*oproutine[op&0xf])(op>>4); if ((t = token()) != SPACE && t != EOL) xerror(errx); } /* * End of pass - check for missing ENDC or ENDS */ if (ifnest || curcomm) error(erri); return(errcnt); } /* * Open first input file */ firstfile()/* * Assembler input & lexical scan routines * * * Copyright (C) 1978, Richard Miller */ #define EXTERN extern #include "as.h" /* * Character types */ #define C_ALPHA 0x80 /* Alphabetic (i.e. legal within symbol) */ #define C_UPPER 0x40 /* Upper-case alpha */ #define C_HEXDIGIT 0x20 /* Hexadecimal digit [0-9 a-f A-F] */ #define C_SPECIAL 0x00 /* Other special characters */ #define C_VALUE 0x0f /* C_HEXDIGIT - numerical value of digit C_SPECIAL - lexical token for character */ /* * Char } if (--ncol > 0) p++; } } /* * Return next lexical token from input line * - if constant, value is in conbuf * - if symbol, symbol pointer is in cursym */ token() { register ret, c; register ctype; register char *p; if (ret = nexttoken) { nexttoken = 0; return(ret); } /* * first character "alphabetic" */ p = scanp; if ((ctype = ctab[c = *p])&C_ALPHA) { /* * quoted numerical constants */ if (p[1] == '\'') { scanp = (p += 2); ret = CON; switch (c) { case '* Save / restore scan pointer (for backtracking) */ static char *scansave; sscan() { scansave = scanp; } rscan() { scanp = scansave; } ", ofname); exit(1); } pass++; passg = 1; outhdr(); assemble(); } while (!passg); oflush(&impure); oflush(&pure); /* * listing pass */ if (lflag) { passg = 0; passl = 1; fout = dup(1); if ((signal(2, 1) & 01) == 0) signal(2, &symout); assemble(); flush(); } /* * append symbol table to object file */ symout(); exit(errcnt); } /* * Assembler pass * - skip comments & null lines * - parse label & opcode * - call opcode routine to parse operands and generate coacter type table */ char ctab[128] { 0, 0, 0, 0, 0, 0, 0, 0, 0, SPACE, EOL, 0, EOL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SPACE, OR, 0, 0, 0x80, 0, AND, 0, LPAREN, RPAREN, STAR, PLUS, COMMA, MINUS, 0x80, SLASH, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0, 0, 0, 0, 0, 0, 0x80, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0, 0, 0, 0, 0x80, 0, 0xaa, 0x': case 'X': ret = HCON; case 'y': case 'Y': conbuf = getnum(16); break; case 'h': case 'H': ret = HCON; case 'f': case 'F': conbuf = getnum(10); break; case 'c': case 'C': ret = STRING; conbuf = getstr(); break; default: xerror(errx); } if (*scanp++ != '\'') xerror(errq); return(ret); } /* * address constants */ if (dcflag && p[1] == '(') { scanp = (p += 2); switch (c) { case 'a': case 'A': r register c, n, sign; p = scanp; sign = 1; if ((c = *p) == '-') { sign = -1; c = *++p; } else if (c == '+') c = *++p; if (((c = ctab[c])&C_HEXDIGIT) == 0 || (n = c&C_VALUE) >= base) xerror(errn); while ((c = ctab[*++p])&C_HEXDIGIT && (c &= C_VALUE) < base) { n *= base; n += c; } scanp = p; return(n*sign); } /* * Scan a character string from input line until ending quote * - translate pairs of quotes to single quote * - pad string with extra blank * - leave string in strbuf, and /* * Assembler symbol table management * * * Copyright (C) 1978, Richard Miller */ #define EXTERN extern #include "as.h" #define NSYM 100 /* initial no. of symbols */ #define SYMINC 100 /* increment for symtab expansion */ #define HASHSIZE 199 /* size of hashed index to symtab should be prime for best distribution */ /* * Hashing function for symbol table index: * defined as a macro for speed */ #define hash(name) ((((unsigned *)name)[0]+((unsigned *)name)[1])%HASHSIZE) struct symbol de */ assemble() { register t, op; register optype; /* * Initialize for assembly pass */ firstfile(); sqzinit(); seginit(); noasm = endswitch = 0; opt = iopt; setexit(); for (; getline(); putline()) { if (endswitch) { error(erre); break; } curlab = dcflag = 0; /* * comment */ if ((t = token()) == STAR || t == EOL) continue; /* * save statement label symbol to be defined by opcode routine */ if (t == SYMBOL) { curlab = cursym; t = token(); } if (t { line = 0; if (pass == 0 || nifiles > 1) { cfile = -1; nextfile(); } else cfile = 0; seek(0, 0, 0); } /* * Open next input file */ nextfile() { if (++cfile >= nifiles) return(0); close(0); if (open(ifiles[cfile], 0) != 0) { printf("%s: can't open\n", ifiles[cfile]); exit(1); } line = 0; return(1); } /* * Print error message and continue */ error(type) { if (nifiles > 1) printf("%s: ", ifiles[cfile]); printf("%d: %c\n", line, type); errcnt++; } /* * Print error message anxab, 0xac, 0xad, 0xae, 0xaf, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0, 0, 0, 0, 0 }; /* * Read next input line, truncating to 71 chars * - resets scan pointer to start of line * - initializes listing buffer * - returns 0 at end-of-file, '\n' otherwise */ char linebuf[74]; /* input line buffer */ char *scanp; /* input scan cursor */ getline() { static char ibuf[512], *next; static int nleft; register char *nx; return(APAR); case 'z': case 'Z': return(ZPAR); default: scanp -= 2; } } /* * symbol */ getsym(); symlook(2); return(SYMBOL); } /* * first character numeric -- decimal constant */ if (ctype&C_HEXDIGIT) { conbuf = getnum(10); return(CON); } /* * special characters */ scanp = ++p; switch (ctype &= C_VALUE) { /* * garbage character */ case 0: xerror(errg); /* * white space */ case SPACE: while ((c = *p) == ' ' || c == '\t') p++; scanplength in strlen */ getstr() { register char *s, *p; register c; s = strbuf; for (p = scanp; ; p++) { if ((c = *p) == '\'') { if (p[1] == '\'') p++; else break; } else if (c == '\n') xerror(errq); *s++ = c; } *s = ' '; strlen = s - strbuf; scanp = p; return(strbuf); } /* * Scan a symbol from the input line into symbuf * if -u mode, translate to lowercase * truncate long symbols to 8 characters (without warning) * * returns 0: no legal symbol found * 1: symbol fo*hashtab[HASHSIZE]; /* index to symbol table */ extern struct optab opcodes[]; /* built-in opcodes */ extern struct symbol predefs[]; /* pre-defined symbols */ /* * Initialize symbol table: * - enter opcodes into hashed index * - allocate initial space for user-defined symbols * - initialize predefined symbols */ syminit() { register struct symbol *sp, **hp; register struct optab *op; for (op = opcodes; op->name[0]; op++) { hp = &hashtab[hash(op->name)]; op->next = *hp; *hp = op; } nextsym = usymtab = sbrk(0); brk(symtop = nextsym + NSYM); for (sp = predefs; sp->name[0]; sp++) { enter(sp->name); cursym->type = sp->type; cursym->value = sp->value; } } /* * Append symbol table to object file */ symout() { register struct symbol *sp; register char c, *p; seek(ofile, symseek, 0); for (sp = usymtab; sp < nextsym; sp++) { /* * relocate */ switch (sp->type&SSEG) { case SCOMN: /* change common block members to absolute */ sp->type = SABS; break; case SB/* * Assembler expression evaluation * * * Copyright (C) 1978, Richard Miller */ #define EXTERN extern #include "as.h" struct exp trm; /* accumulator for expression terms */ /* * Evaluate an expression from the input line, leaving its value in exp * - checks for undefined symbols * - returns the relocatability of the expression */ expr() { register op, val, rel, half; /* * first term */ term(); rel = trm.rel; val = trm.val; half = trm.half; /* * check for further binary operatorss */ case SYMBOL: { register type, symno; val = cursym->value; switch (type = (cursym->type&SSEG)) { case SUNDEF: trm.rel = cursym->type&SEXT ? /* external reference */ REXT | ((cursym-usymtab)<<4) : /* undefined symbol */ RUNDEF; val = 0; break; case SCOMN: symno = cursym->type>>8; if ((type=usymtab[symno].type&SSEG)==SUNDEF) /* offset in common block */ trm.rel = REXT | (symno<<4); else { /* offset from local symbol */ trm.rel = (type-1)<value += hdr.dsize; case SDATA: sp->value += hdr.tsize; } write(ofile, sp->name, 16); } } /* * Look up symbol name in symbuf in hash-indexed symbol table * flag = 0: opcode expected * 1: user symbol expected * 2: user symbol expected; enter into index if not found * * returns 0: symbol was not previously defined * 1: symbol was previously defined * cursym: points to symbol table entry */ symlook(flag) { register struct symbol *sym, *sp, *lp, **hp; lp = hp = &hashtab[ha */ while ((op = token()) <= BINOP) { term(); /* * find relocatability of result */ rel = combine(rel, trm.rel, op); half &= trm.half; /* * compute fullword value of result */ switch (op) { case PLUS: val += trm.val; break; case MINUS: val -= trm.val; break; case STAR: val *= trm.val; break; case SLASH: if (trm.val) val /= trm.val; else error(errz); break; case AND: val &= trm.val; break; case OR: val |= trm.val; } } nex1; val += usymtab[symno].value; } break; default: /* translate symbol type to relocation bits */ trm.rel = ((type&SSEG)-1)<<1; } } break; /* * location counter */ case STAR: val = curseg->loc; trm.rel = currel; break; default: xerror(errx); } if (sign < 0) { if (trm.rel != RABS && trm.rel != RUNDEF) error(errr); val = -val; } trm.val = val; trm.half = half; return; } } /* * Determine relocatability of result of operation op performed on * operandine[])() { &donull, /* unused opcode - ignore */ &dori2, /* RI2 */ &dorx, /* RX1, RX2, RX3 */ &dobrx, /* RX-type branch */ &dori1, /* RI1 */ &dodata, /* PSEUDO: data definition */ &doloc, /* PSEUDO: location counter */ &dopseud, /* PSEUDO: other */ &dorr, /* RR */ &docond, /* PSEUDO: conditional assembly */ &dobad, /* - */ &dobad, /* - */ &dobrr, /* RR-type branch */ &dobsf, /* SF-type branch */ &dobad, /* - */ &donop /* STUPID: zero-or-one-operand (=NOP,NOPR) */00 | SF, 0, "bxh", 0xc000 | RX, 0, "bxle", 0xc100 | RX, 0, "c", 0x5900 | RX, 0, "cbt", 0x7700 | RX, 0, "ce", 0x6900 | RX, 0, "cer", 0x2900 | RR, 0, "ch", 0x4900 | RX, 0, "chi", 0xc900 | RI1, 0, "chvr", 0x1200 | RR, 0, "ci", 0xf900 | RI2, 0, "cl", 0x5500 | RX, 0, "clb", 0xd400 | RX, 0, "clh", 0x4500 | RX, 0, "clhi", 0xc500 | RI1, 0, "cli", 0xf500 | RI2, 0, "clr", 0x0500 | RR, 0, "cr", 0x0900 | RR, 0, "crc12", 0x5e00 | RX, 0, "crc16", 0x5f00 | RX, 0, "d", 0x5d00 | RX, 0, "de", 0x6d00 | RX, , 0xf600 | RI2, 0, "or", 0x0600 | RR, 0, "rb", 0xd700 | RX, 0, "rbl", 0x6700 | RX, 0, "rbr", 0x9700 | RR, 0, "rbt", 0x7600 | RX, 0, "rd", 0xdb00 | RX, 0, "rdr", 0x9b00 | RR, 0, "rh", 0xd900 | RX, 0, "rhr", 0x9900 | RR, 0, "rll", 0xeb00 | RI1, 0, "rrl", 0xea00 | RI1, 0, "rtl", 0x6600 | RX, 0, "s", 0x5b00 | RX, 0, "sbt", 0x7500 | RX, 0, "scp", 0xe300 | RX, 0, "se", 0x6b00 | RX, 0, "ser", 0x2b00 | RR, 0, "sh", 0x4b00 | RX, 0, "shi", 0xcb00 | RI1, 0, "si", 0xfb00 | RI2, 0, "sint", 0xe200 |sh(&symbuf)]; for (sp = *hp; sp; lp = sp, sp = sp->next) { if (((int *)sp->name)[0] == ((int *)&symbuf)[0] && ((int *)sp->name)[1] == ((int *)&symbuf)[1]) { if (flag) { if (sp < usymtab) continue; } else if (sp >= usymtab) continue; /* * Move symbol to the front of the chain so it will * be found sooner next time. */ if (lp != hp) { lp->next = sp->next; sp->next = *hp; *hp = sp; } cursym = sp; return(1); } } /* * Enter new symbottoken = op; exp.val = val; exp.half = half; if (rel == RUNDEF && pass > 0) error(erru); return(exp.rel = rel); } /* * Evaluate a single expression term from the input line, leaving its * value in trm */ term() { register val, sign, half; half = 0; sign = 1; for (;;) { /* loop through leading + or - signs */ switch (token()) { /* * leading sign(s) */ case MINUS: sign = -sign; case PLUS: continue; /* * address constant */ case ZPAR: half = 1; case APAR: expr(); ts with relocatability rel1 and rel2 * * Permitted combinations are: * undefined with anything -> undefined * absolute with absolute -> absolute * relocatable + absolute -> relocatable * relocatable - absolute -> relocatable * absolute + relocatable -> relocatable * relocatable - relocatable -> absolute (provided both are in * same segment or in same common block) * * Note that external references are permitted to take part in expressions */ combine(rel1, rel2, op) register rel1, rel2; { }; /* * Opcodes and pseudo-ops */ struct optab opcodes[] { /* data-definition pseudo-ops */ 0, "db", 0x05, 0, "dc", 0x15, 0, "dac", 0x25, 0, "dcf", 0x35, 0, "dcx", 0x45, 0, "dcy", 0x55, 0, "dcz", 0x65, /* location counter pseudo-ops */ 0, "impur", 0x06, 0, "pure", 0x16, 0, "align", 0x26, 0, "ds", 0x36, 0, "das", 0x46, 0, "dsf", 0x46, 0, "dsh", 0xc6, 0, "org", 0x56, 0, "comn", 0x66, 0, "struc", 0x76, 0, "ends", 0x86, 0, "bss", 0x96, 0, "bdata", 0xa6, 0, "borg", 0xb6, 0, "dlist", 0xd6, 0, "der", 0x2d00 | RR, 0, "dh", 0x4d00 | RX, 0, "dhr", 0x0d00 | RR, 0, "dr", 0x1d00 | RR, 0, "epsr", 0x9500 | RR, 0, "exbr", 0x9400 | RR, 0, "exhr", 0x3400 | RR, 0, "flr", 0x2f00 | RR, 0, "fxr", 0x2e00 | RR, 0, "l", 0x5800 | RX, 0, "la", 0xe600 | RX, 0, "lb", 0xd300 | RX, 0, "lbr", 0x9300 | RR, 0, "lcs", 0x2500 | SF, 0, "le", 0x6800 | RX, 0, "ler", 0x2800 | RR, 0, "lh", 0x4800 | RX, 0, "lhi", 0xc800 | RI1, 0, "lhl", 0x7300 | RX, 0, "li", 0xf800 | RI2, 0, "lis", 0x2400 | SF, 0, "lm", 0x RI1, 0, "sis", 0x2700 | SF, 0, "sla", 0xef00 | RI1, 0, "slha", 0xcf00 | RI1, 0, "slhl", 0xcd00 | RI1, 0, "sll", 0xed00 | RI1, 0, "slhls", 0x9100 | SF, 0, "slls", 0x1100 | SF, 0, "sr", 0x0b00 | RR, 0, "sra", 0xee00 | RI1, 0, "srha", 0xce00 | RI1, 0, "srhl", 0xcc00 | RI1, 0, "srl", 0xec00 | RI1, 0, "srhls", 0x9000 | SF, 0, "srls", 0x1000 | SF, 0, "ss", 0xdd00 | RX, 0, "ssr", 0x9d00 | RR, 0, "st", 0x5000 | RX, 0, "stb", 0xd200 | RX, 0, "stbr", 0x9200 | RR, 0, "ste", 0x6000 | RX, 0, "sth", 0l into symbol table and index */ if (flag > 1) { sym = nextsym; if (++nextsym > symtop) brk(symtop += SYMINC); ((int *)sym->name)[0] = ((int *)&symbuf)[0]; ((int *)sym->name)[1] = ((int *)&symbuf)[1]; sym->next = *hp; *hp = cursym = sym; } return(0); } /* * Enter a symbol name into the symbol table */ enter(name) register char *name; { register i; for (i=0; i<8; i++) if (symbuf[i] = *name) name++; symlook(2); } rm.rel = exp.rel; val = exp.val; if (token() != RPAREN) xerror(errx); break; /* * numeric constant */ case HCON: half = 1; case CON: trm.rel = RABS; val = conbuf; break; /* * character constant -- right-justify into a word */ case STRING: { register i, n; if (strlen > 4) xerror(errq); n = 0; for (i = 0; i < strlen; i++) { n <<= 8; n |= strbuf[i]; } trm.rel = RABS; val = n; } break; /* * symbolic name -- get its value & relocation bit register ret; if (rel1 == RUNDEF || rel2 == RUNDEF) ret = RUNDEF; else if (pass == 0 && (rel1 & REXT || rel2 & REXT)) /* forward references in ENTRY statements may change types */ ret = RUNDEF; else if (rel2 == RABS) if (rel1 == RABS) ret = RABS; else if (op <= MINUS) ret = rel1; else error(errr); else if (rel1 == RABS) if (op == PLUS) ret = rel2; else error(errr); else if (rel1 == rel2 && op == MINUS) ret = RABS; else error(errr); return(ret); } 0, "cnop", 0xe6, /* Other pseudo-ops */ 0, "equ", 0x07, 0, "extrn", 0x17, 0, "entry", 0x27, 0, "do", 0x37, 0, "squez", 0x47, 0, "nosqz", 0x57, 0, "norx3", 0x67, /* Conditional assembly pseudo-ops */ 0, "ifz", 0x09, 0, "ifnz", 0x19, 0, "ifp", 0x29, 0, "ifnp", 0x39, 0, "ifm", 0x49, 0, "ifnm", 0x59, 0, "ife", 0x69, 0, "ifo", 0x79, 0, "ifu", 0x89, 0, "ifd", 0x99, 0, "else", 0xa9, 0, "endc", 0xb9, 0, "if", 0xc9, 0, "end", 0xd9, /* 7/32 Machine Instructions */ 0, "a", 0x5a00 | RX, 0, "abl", d100 | RX, 0, "lme", 0x7200 | RX, 0, "lpsw", 0xc200 | RX, 0, "lpswr", 0x1800 | RR, 0, "lra", 0x6300 | RX, 0, "lr", 0x0800 | RR, 0, "m", 0x5c00 | RX, 0, "me", 0x6c00 | RX, 0, "mer", 0x2c00 | RR, 0, "mh", 0x4c00 | RX, 0, "mhr", 0x0c00 | RR, 0, "mr", 0x1c00 | RR, 0, "n", 0x5400 | RX, 0, "nh", 0x4400 | RX, 0, "nhi", 0xc400 | RI1, 0, "ni", 0xf400 | RI2, 0, "nr", 0x0400 | RR, 0, "o", 0x5600 | RX, 0, "oc", 0xde00 | RX, 0, "ocr", 0x9e00 | RR, 0, "oh", 0x4600 | RX, 0, "ohi", 0xc600 | RI1, 0, "oi"x4000 | RX, 0, "stm", 0xd000 | RX, 0, "stme", 0x7100 | RX, 0, "svc", 0xe100 | RX, 0, "tbt", 0x7400 | RX, 0, "thi", 0xc300 | RI1, 0, "ti", 0xf300 | RI2, 0, "tlate", 0xe700 | RX, 0, "ts", 0xe000 | RX, 0, "wb", 0xd600 | RX, 0, "wbr", 0x9600 | RR, 0, "wd", 0xda00 | RX, 0, "wdr", 0x9a00 | RR, 0, "wh", 0xd800 | RX, 0, "whr", 0x9800 | RR, 0, "x", 0x5700 | RX, 0, "xh", 0x4700 | RX, 0, "xhi", 0xc700 | RI1, 0, "xi", 0xf700 | RI2, 0, "xr", 0x0700 | RR, /* Extended Branch Mnemonics */ 0, "bc", 0x4280 | BRX, 0, "bcr", 0x0280 | BRR, 0, "bcs", 0x2080 | BSF, 0, "bnc", 0x4380 | BRX, 0, "bncr", 0x0380 | BRR, 0, "bncs", 0x2280 | BSF, 0, "be", 0x4330 | BRX, 0, "ber", 0x0330 | BRR, 0, "bes", 0x2230 | BSF, 0, "bne", 0x4230 | BRX, 0, "bner", 0x0230 | BRR, 0, "bnes", 0x2030 | BSF, 0, "bl", 0x4280 | BRX, 0, "blr", 0x0280 | BRR, 0, "bls", 0x2080 | BSF, 0, "bnl", 0x4380 | BRX, 0, "bnlr", 0x0380 | BRR, 0, "bnls", 0x2280 | BSF, 0, "bm", 0x4210 | BRX, 0, "bmr", 0x0210 | BRR, 0, "bms", 0x2010 | BSF, | RR, /* Double-precision floating point instructions */ #ifdef OPDBL 0, "ad", 0x7a00 | RX, 0, "adr", 0x3a00 | RR, 0, "cd", 0x7900 | RX, 0, "cdr", 0x3900 | RR, 0, "dd", 0x7d00 | RX, 0, "ddr", 0x3d00 | RR, 0, "fldr", 0x3f00 | RR, 0, "fxdr", 0x3e00 | RR, 0, "ld", 0x7800 | RX, 0, "ldr", 0x3800 | RR, 0, "lmd", 0x7f00 | RX, 0, "md", 0x7c00 | RX, 0, "mdr", 0x3c00 | RR, 0, "sd", 0x7b00 | RX, 0, "sdr", 0x3b00 | RR, 0, "std", 0x7000 | RX, 0, "stmd", 0x7e00 | RX, #endif /* 8/32 Machine Instructionexp.rel) { case RBSS: exp.val += hdr.dsize; case RDATA: exp.val += hdr.tsize; } if (exp.half || op == DCZ) { if (passg && (exp.val < 0xffff8000 || exp.val > 0xffff)) error(errh); puth(exp.val, exp.rel); } else putw(exp.val, exp.rel); } continue; /* * Hex constant */ case DCX: t = getnum(16); if (t < 0xffff8000 || t > 0xffff) error(errh); puth(t, RABS); continue; case DCY: t = getnum(16); putw(t, RABS); DS: label(); if (expr() != RABS) xerror(erra); if ((t = exp.val) < 0) { t = 0; error(errv); } if (op == DSF) t *= 4; else if (op == DSH) t *= 2; org(curseg->loc + t); break; case DLIST: if (expr() != RABS) error(erra); if ((t = exp.val) < 0) { t = 0; error(errv); } align(4); label(); puth(t, RABS); puth(0, RABS); putw(0, RABS); org(curseg->loc + t*4); break; case ORG: label(); switch (t = expr()) { case RTEXT: curseg = &pure; br * Block Data program: change common to data */ if (bdata && currel != RABS) { curseg = &impure; currel = RDATA; curcomm->type = SDATA | SEXT; curcomm->value = impure.loc; org(impure.loc + comm.maxloc); } currel = saverel; curseg = saveseg; curcomm = 0; comm.loc = comm.maxloc = 0; nexttoken = EOL; break; case BDATA: bdata++; mflag++; /* allow redefinitions in Fortran blkdata */ nexttoken = EOL; break; case BORG: if (token() != SYMBOL) xerror(errs); blk(); /* * Compound IF statements */ if (op <= IFCOND) { /* Evaluate expression -- must be previously defined */ if (op < IFU) { if (expr() == RUNDEF) error(erru); v = exp.val; } else if (!getsym()) error(errs); else v = symlook(1); /* Evaluate condition */ switch (op) { case IFU: case IFZ: cond = (v == 0); break; case IFD: case IFNZ: cond = (v != 0); break; case IFP: cond = (v > 0); break; case IFNP: cond = (v <= 0); break; case IFM: cond = (v < 0, "bnm", 0x4310 | BRX, 0, "bnmr", 0x0310 | BRR, 0, "bnms", 0x2210 | BSF, 0, "bp", 0x4220 | BRX, 0, "bpr", 0x0220 | BRR, 0, "bps", 0x2020 | BSF, 0, "bnp", 0x4320 | BRX, 0, "bnpr", 0x0320 | BRR, 0, "bnps", 0x2220 | BSF, 0, "bo", 0x4240 | BRX, 0, "bor", 0x0240 | BRR, 0, "bos", 0x2040 | BSF, 0, "bno", 0x4340 | BRX, 0, "bnor", 0x0340 | BRR, 0, "bnos", 0x2240 | BSF, 0, "bz", 0x4330 | BRX, 0, "bzr", 0x0330 | BRR, 0, "bzs", 0x2230 | BSF, 0, "bnz", 0x4230 | BRX, 0, "bnzr", 0x0230 | BRR, 0, "bnzss */ #ifdef OP832 0, "bdcs", 0xe500 | RX, 0, "ecs", 0xe900 | RI1, 0, "mpbsr", 0x3000 | RR, 0, "pb", 0x6200 | RX, 0, "pbr", 0x3200 | RR, 0, "rdcs", 0xe820 | BRR, 0, "wdcs", 0xe800 | BRR, #endif /* Ignored pseudo-ops */ 0, "title", 0, 0, "eject", 0, 0, "space", 0, 0, "nlist", 0, 0, "list", 0, 0, "lstc", 0, 0, "nlstc", 0, 0, "prog", 0, 0, "lcnt", 0, 0, "width", 0, 0, "scrat", 0, 0, "ersqz", 0, 0, 0 }; /* * Predefined symbols */ struct symbol predefs[] { 0, "adc", 1, 4, 0, "ladc", 1, 2, 0, 0 }; continue; /* * Byte constant */ case DB: if ((t = token()) == STRING && strlen > 1) { puts(strlen); continue; } nexttoken = t; t = expr(); if (passg) if (t != RABS || exp.val < -127 || exp.val > 255) error(errv); putb(exp.val); if (passl) lstb(exp.val); continue; } while ((t = token()) == COMMA); nexttoken = t; } /* * Location counter pseudo-ops */ #define IMPURE 0 #define PURE 1 #define ALIGN 2 #define DS 3 #define DSF 4 #define ORG eak; default: if (t == currel) break; error(errr); t = RDATA; case RDATA: curseg = &impure; break; } currel = t; org(exp.val); break; case COMN: if (curcomm) xerror(erri); if (!curlab) xerror(errl); curcomm = curlab; if ((t = curlab->type&SSEG) != SUNDEF && (t != SDATA || (bdata && pass == 0))) error(errm); curlab->type = SEXT | (bdata? SUNDEF : t); saverel = currel; saveseg = curseg; currel = REXT | ((curlab-usymtab)<<4); curseg = & = cursym; if (token() != LPAREN) xerror(errs); if (blk->type != (SDATA|SEXT)) xerror(errr); switch (t = expr()&RSEG) { case RABS: case REXT: t = blk->value; break; case RDATA: t = 0; break; default: xerror(errr); } if (token() != RPAREN) xerror(errx); currel = RDATA; curseg = &impure; org(t + exp.val); break; } } /* * Other pseudo-ops */ #define EQU 0 #define EXTRN 1 #define ENTRY 2 #define DO 3 #define SQUEZ 4 #define NOSQZ 5 #define NORX0); break; case IFNM: cond = (v >= 0); break; case IFE: cond = !(v & 01); break; case IFO: cond = (v & 01); break; } /* Adjust conditional assembly & nesting level */ if (!cond || ifcount) ifcount++; ifnest++; return; } /* * Other compound conditionals */ if (op != IF) nexttoken = EOL; switch (op) { case ELSE: if (!ifnest) error(erri); if (ifcount <= 1) ifcount = 1-ifcount; break; case ENDC: if (!ifnest) error(erri); if (ifcount) ifcount-", 0x2030 | BSF, 0, "b", 0x4300 | BRX, 0, "br", 0x0300 | BRR, 0, "bs", 0x2200 | BSF, 0, "nop", 0x4200 | NOP, 0, "nopr", 0x0200 | NOP, /* 32-bit Common Mode Instructions */ 0, "aa", 0x5a00 | RX, 0, "aai", 0xfa00 | RI2, 0, "aar", 0x0a00 | RR, 0, "aam", 0x5100 | RX, 0, "ca", 0x5900 | RX, 0, "cai", 0xf900 | RI2, 0, "car", 0x0900 | RR, 0, "cla", 0x5500 | RX, 0, "clai", 0xf500 | RI2, 0, "clar", 0x0900 | RR, 0, "lda", 0x5800 | RX, 0, "ldai", 0xe600 | RX, 0, "ldar", 0x0800 | RR, 0, "na", 0x5400/* * Assembler pseudo-op processing * * * Copyright (C) 1978, Richard Miller */ #define EXTERN extern #include "as.h" /* * Ignored opcode */ donull() { nexttoken = EOL; } /* * Illegal opcode */ dobad() { xerror(errc); } /* * Data definition pseudo-ops */ #define DB 0 #define DC 1 #define DAC 2 #define DCF 3 #define DCX 4 #define DCY 5 #define DCZ 6 dodata(op) { register t; dcflag = 1; /* a()-type constants are legal */ switch (op) { case DC: case DCX: case DCZ: align(2); bre5 #define COMN 6 #define STRUC 7 #define ENDS 8 #define BSS 9 #define BDATA 10 #define BORG 11 #define DSH 12 #define DLIST 13 #define CNOP 14 #define NOPR 0x0200 /* NO-OP instruction */ doloc(op) { static struct segment *saveseg; /* previous segment (while in a STRUC or COMN */ static int saverel; /* previous relocatability */ register t; register struct symbol *blk; switch (op) { case IMPURE: label(); curseg = &impure; currel = RDATA; align(2); nexttoken = EOL; break; 3 6 dopseud(op) { register t; register t1, t2; switch(op) { /* * EQUate */ case EQU: if (!curlab) { xerror(errl); } expr(); deflab(exp.rel, exp.val, mflag); if (passl) lstaddr(exp.val, exp.rel); break; case EXTRN: case ENTRY: do { if (!getsym()) xerror(errs); else if (symlook(1)) cursym->type |= SEXT; } while ((t = token()) == COMMA); nexttoken = t; break; case DO: label(); docount = 0; if (expr() != RABS) error(erra); if ((t = exp.val-; ifnest--; break; /* * Simple IF */ case IF: if (expr() == RUNDEF) error(erru); noasm = !(exp.val); break; /* * END statement - set switch for assemble() */ case END: endswitch = 1; break; } } | RX, 0, "nai", 0xf400 | RI2, 0, "nar", 0x0400 | RR, 0, "oa", 0x5600 | RX, 0, "oai", 0xf600 | RI2, 0, "oar", 0x0600 | RR, 0, "sa", 0x5b00 | RX, 0, "sai", 0xfb00 | RI2, 0, "sar", 0x0b00 | RR, 0, "slaa", 0xef00 | RI1, 0, "slal", 0xed00 | RI1, 0, "sraa", 0xee00 | RI1, 0, "sral", 0xec00 | RI1, 0, "sta", 0x5000 | RX, 0, "tai", 0xf300 | RI2, 0, "xa", 0x5700 | RX, 0, "xai", 0xf700 | RI2, 0, "xar", 0x0700 | RR, 0, "ma", 0x5c00 | RX, 0, "mar", 0x1c00 | RR, 0, "da", 0x5d00 | RX, 0, "dar", 0x1d00ak; case DAC: case DCF: case DCY: align(4); break; case DB: /* * Stupid special case: * "DB *" is equivalent to "ALIGN 2" */ if ((t = token()) == STAR && eol()) { label(); align(2); return; } nexttoken = t; } label(); do switch (op) { /* * fullword or halfword constant */ case DC: case DAC: case DCF: case DCZ: if ((t = token()) == STRING) puts((strlen+01)&~01); else { nexttoken = t; expr(); /* * relocate */ switch ( case PURE: label(); curseg = &pure; currel = RTEXT; align(2); nexttoken = EOL; break; case BSS: label(); curseg = &bss; currel = RBSS; align(2); nexttoken = EOL; break; case ALIGN: case CNOP: if (expr() != RABS) xerror(erra); if ((t = exp.val) != 2 && t != 4 && t != 8) t = 4; if (op == ALIGN) { align(t); label(); break; } align(2); label(); while (curseg->loc & (t-1)) puth(NOPR, RABS); break; case DSF: align(4); case DSH: align(2); casecomm; nexttoken = EOL; break; case STRUC: if (curcomm) error(erri); if (curlab) { curcomm = curlab; deflab(RABS, 0, 0); } else curcomm = -1; saverel = currel; saveseg = curseg; currel = RABS; curseg = &comm; nexttoken = EOL; break; case ENDS: if (!curcomm) xerror(erri); if (comm.loc > comm.maxloc) comm.maxloc = comm.loc; if ((currel != RABS && curcomm->type == (SEXT|SUNDEF)) || (currel == RABS && curcomm != -1)) curcomm->value = comm.maxloc; /*) < 0) t = 0; if (!getline()) xerror(erre); docount = t; break; case SQUEZ: opt = 1; break; case NOSQZ: opt = 0; break; case NORX3: opt = -1; break; } } /* * Conditional assembly pseudo-ops */ #define IFZ 0 #define IFNZ 1 #define IFP 2 #define IFNP 3 #define IFM 4 #define IFNM 5 #define IFE 6 #define IFO 7 #define IFU 8 #define IFD 9 #define IFCOND 9 /* last compound if */ #define ELSE 10 #define ENDC 11 #define IF 12 #define END 13 docond(op) { register v, cond; label/* * Assembler output & location counter routines * * * Copyright (C) 1978, Richard Miller */ #define EXTERN extern #include "as.h" /* * Initialize segments (at the beginning of each pass) */ seginit() { impure.loc = impure.maxloc = pure.loc = pure.maxloc = bss.loc = bss.maxloc = 0; curseg = &impure; currel = RDATA; } /* * Write out the a.out header and initialize output buffers * (at the beginning of code-generation pass(es)) */ outhdr() { register n; if (pure.maxloc < pure.loc) pure.maxloc = pure.loc; if (impure.maxloc < impure.loc) impure.maxloc = impure.loc; if (bss.maxloc < bss.loc) bss.maxloc = bss.loc; hdr.mword = 0407; hdr.tsize = (pure.maxloc+03)&~03; hdr.dsize = (impure.maxloc+03)&~03; hdr.bsize = (bss.maxloc+03)&~03; hdr.ssize = 16*(nextsym - usymtab); write(ofile, &hdr, sizeof hdr); pure.tseek = n = sizeof hdr; impure.tseek = (n += hdr.tsize); pure.rseek = (n += hdr.dsize); impure.rseek = (n += hdr.tsize); symseek = (n += hdr.dsize); pure.nchar = impureary by padding with zeroes */ align(boundary) { register struct segment *sp; register n; n = boundary - 1; if ((sp = curseg) != &pure && sp != &impure) { sp->loc = (sp->loc + n) & ~n; return; } while (sp->loc&n) putb(0); } /* * Move the current location counter to the specified location * - done by repositioning seek pointers, not padding with zeroes, * to avoid overwriting previously generated code */ org(loc) register loc; { register struct segment *sp; register off; sp = curseg; rdata Fortran V * - redefinition of absolute symbols is always permitted */ deflab(rel, val, flag) { register type, otype; /* * convert relocation bits to symbol type */ if (rel&REXT) type = SCOMN | ((rel & ~RSEG)<<4); else type = (rel>>1)+1; /* * check for illegal redefinitions */ if (!flag) { if ((otype = curlab->type&SSEG) == SCOMN) otype = curlab->type; if (pass == 0) { if (otype!=SUNDEF && (otype!=SABS || type!=SABS)) error(errm); } else if (otype != type) err sis - ais */ 0xc8, 0x24, 0x25, /* lhi - lis - lcs */ 0xec, 0x10, 0, /* srl - srls */ 0xed, 0x11, 0, /* sll - slls */ 0xcc, 0x90, 0, /* srhl - srhls */ 0xcd, 0x91, 0, /* slhl - slhls */ 0 }; int nsquez; /* no. of bytes squeezed out in pass 1 */ /* * RR- or SF-type instruction */ dorr(op) { align(2); label(); getr1(op); reg2 = regexpr(); puth(((op|reg1)<<4) | reg2, RABS); } /* * RI1-type instruction */ dori1(op) { register nindex, sqz; sqz = (pass <= 1? 0 : getsqz()); align(2); l&& off >= -30 && off <= 30+nsquez) if (sqz <= 1 && opt > 0) { genbsf(op&0x10 ? op-0x210 : op-0x220, off); if (pass==1) { setsqz(1); nsquez += 4; } return; } puth((op<<4) | reg2, RABS); genrx(nindex, sqz); } /* * Stupid special case: NOP and NOPR instructions * address operand may be left out */ #define NOP 0x42 #define NOPR 0x02 donop(op) { align(2); label(); switch (op) { case NOPR<<4: puth((NOPR<<8) | (eol()? 0 : regexpr()), RABS); break; case NOP<<4: if (eol(ddress */ } /* * Generate destination field of RI2 instruction */ genri1(op, nindex, sqz) { register rop, pop; register struct sftab *p; /* * Shrink RI1 to SF */ if (pass && drel==RABS && nindex==0 && sqz <= 1 && opt > 0) { rop = op>>4; for (p = sftab; pop = p->op_ri1; p++) if (pop == rop) { if (dval>=0 && dval<=15) { puth((p->op_sf<<8)|(reg1<<4)|dval, RABS); if (pass == 1) { setsqz(1); nsquez += 2; } return; } if ((pop = p->op_csf) && dval<0 &&.nchar = 0; } /* * Emit a string of characters */ puts(len) register len; { register struct segment *sp; register i, n; if ((sp = curseg) != &impure && sp != &pure) xerror(errd); sp->loc += len; if (passg) { n = sp->nchar; for (i = 0; len--; i++) { if (n >= OBSIZE) { sp->nchar = n; oflush(sp); n = 0; } sp->tbuf[n] = strbuf[i]; sp->rbuf[n++] = RABS; } sp->nchar = n; } else if (passl) for (i = 0; len--; i++) lstb(strbuf[i]); } /* * Emit a word */ putw if ((off = loc-curseg->loc) == 0) return; if (loc & 0xff000000) xerror(erro); if (sp->maxloc < sp->loc) sp->maxloc = sp->loc; sp->loc = loc; if (passg && (sp == &impure || sp == &pure)) { oflush(sp); sp->tseek += off; sp->rseek += off; sp->nchar = sp->tseek & 01; /* keep proper alignment */ } } /* * Flush the output buffer for the specified segment */ oflush(sp) register struct segment *sp; { register n; register off; /* * If text in buffer begins on an odd byte boundary, adjusor(errm); else if (passg && type != SABS && curlab->value != val) error(errp); } curlab->type = (curlab->type & SEXT) | type; curlab->value = val; } abel(); getr1(op); if ((nindex = geta()) > 1) error(errx); if (passg && (dval < 0xffff8000 || dval > 0xffff)) error(errh); genri1(op, nindex, sqz); } /* * RI2-type instruction */ dori2(op) { register nindex, sqz; sqz = (pass <= 1? 0 : getsqz()); align(2); label(); getr1(op); if ((nindex = geta()) > 1) error(errx); /* * Shrink RI2 to RI1 */ if (pass && drel==RABS && dval>=0xffff8000 && dval<=0x7fff) if (sqz <= 2 && opt > 0) { genri1(op - 0x300, nindex, sqz); if (pass == 1) )) putw(NOP<<24, RABS); else { register sqz, nindex; sqz = (pass <= 1? 0 : getsqz()); nindex = geta(); puth((NOP<<8) | reg2, RABS); genrx(nindex, sqz); } } } /* * Generate destination field of RX instruction */ genrx(nindex, sqz) { register off; /* * Try to shrink instruction */ if (pass && nindex < 2 && sqz <= 2) { /* * Shrink RX3 to RX1 */ if (drel==RABS && dval>=0 && dval<=0x3fff && opt != 0) { puth(dval, drel); setsqz(2); if (pass == 1) nsquez += dval >= -15) { puth((pop<<8)|(reg1<<4)|(-dval), RABS); if (pass == 1) { setsqz(1); nsquez += 2; } return; } break; } } /* * Use full RI1 format */ if (pass) setsqz(2); puth(((op|reg1)<<4) | reg2, RABS); puth(dval, drel); } /* * Generate a short branch instruction */ genbsf(op, off) { if (off < 0) off = -off; else op += 0x10; puth((op<<4) | (off>>1), RABS); if (passl) lstaddr(dval, drel); } /* * Get first operand from instruction */ getr(val, rel) struct { short halfw[2]; } val; { puth(val.halfw[0], rel==RABS? rel : rel|RHI); puth(val.halfw[1], rel); } /* * Emit a halfword * - current location counter must be even */ puth(val, rel) short val; { register struct segment *sp; register n; if ((sp = curseg) != &pure && sp != &impure) xerror(errd); sp->loc += 2; if (passg) { if ((n = sp->nchar) >= OBSIZE) { oflush(sp); n = 0; } sp->nchar = n+2; n >>= 1; ((short *)sp->tbuf)[n] = val; ((short *)sp->rbuf)[n] = rel; t offset * and length for writes */ off = sp->tseek & 01; if ((n = sp->nchar-off) == 0) return; seek(ofile, sp->tseek, 0); write(ofile, sp->tbuf+off, n); seek(ofile, sp->rseek, 0); write(ofile, sp->rbuf+off, n); sp->tseek += n; sp->rseek += n; } /* * Define the symbol in curlab to have the given relocatability and value * - converts relocation bits to symbol type * - checks for illegal redefinitions * - if flag==1, redefinition is permitted (used mainly to compensate * for bug in InteUNIX Interdata assembler - for details see AS(I) Jobjar: - make 16-bit version - make portable OS/MT version - finish implementing listings The copyright notice is meant to be taken seriously. nsquez += 2; return; } /* * Use full RI2 form */ if (pass) setsqz(3); puth(((op|reg1)<<4) | reg2, RABS); putw(dval, drel); } /* * RX-type instruction */ dorx(op) { register nindex, sqz; sqz = (pass <= 1? 0 : getsqz()); align(2); label(); getr1(op); nindex = geta(); puth(((op|reg1)<<4) | reg2, RABS); genrx(nindex, sqz); } /* * RR-type branch */ dobrr(op) { align(2); label(); reg2 = regexpr(); puth((op<<4) | reg2, RABS); } /* * SF-type branch */ dobsf(op) { register of 2; return; } /* * Shrink RX3 to RX2 */ off = dval - (curseg->loc+2); if (currel == RDATA) off -= hdr.tsize; if (drel == currel && opt != 0 && off>=0xffffc000 && off<=0x3fff) { puth((off&0x7fff)|0x8000, RABS); if (passl) lstaddr(dval, drel); setsqz(2); if (pass == 1) nsquez += 2; return; } } /* * Use full RX3 format */ if (pass) setsqz(3); puth(((0x40|reg3)<<8) | ((dval>>16)&0xff), drel|RHI); puth(dval&0xffff, 0); /* second reloc=0 means 24-bit a1(op) { reg1 = 0; sscan(); /* save scan pointer for backtracking */ expr(); if (token() != COMMA) { /* * Stupid special case instructions * reg1 operand is optional */ switch (op) { case 0xd50: /* al */ case 0xc20: /* lpsw */ case 0x180: /* lpswr*/ case 0xe20: /* sint */ case 0xe00: /* ts */ /* * Reset scan pointer to parse expression again * as second operand, and use default reg 0 */ rscan(); return; default: xerror(errx); } } if (pas } if (passl) lsth(val); } /* * Emit a byte */ putb(val) { register struct segment *sp; register n; if ((sp = curseg) != &impure && sp != &pure) xerror(errd); sp->loc++; if (passg) { if ((n = sp->nchar) >= OBSIZE) { oflush(sp); n = 0; } sp->tbuf[n] = val; sp->rbuf[n] = RABS; sp->nchar = ++n; } } /* * Define a label at the current location */ label() { if (passl) lstloc(); if (curlab) deflab(currel, curseg->loc, 0); } /* * Align generated code to the specified bound/* * Assembler Machine Instruction Processing * * * Copyright (C) 1978, Richard Miller */ #define EXTERN extern #include "as.h" /* * disassembled instruction parts */ int reg1; int reg2; int reg3; int dval; int drel; /* * Table of immediate instructions optimizable to SF format */ struct sftab { char op_ri1; /* RI1-format opcode */ char op_sf; /* SF-format opcode */ char op_csf; /* complement SF-format opcode */ } sftab[] { 0xca, 0x26, 0x27, /* ahi - ais - sis */ 0xcb, 0x27, 0x26, /* shi -f; align(2); label(); if (geta() != 0) error(errx); off = dval - curseg->loc; if (currel == RDATA) off -= hdr.tsize; if (passg) if (drel != currel || off < -30 || off > 30) error(errb); genbsf(op, off); } /* * RX-type branch */ dobrx(op) { register nindex, off, sqz; sqz = (pass <= 1? 0 : getsqz()); align(2); label(); nindex = geta(); /* * Shrink BRX to BSF */ off = dval - curseg->loc; if (currel == RDATA) off -= hdr.tsize; if (pass && nindex == 0 && drel == currel    s && (exp.rel != RABS || (reg1 = exp.val) & ~0xf)) error(errv); } /* * Get second operand from instruction * - returns number of index registers */ geta() { register t, nreg; reg2 = reg3 = 0; drel = expr(); dval = exp.val; /* * relocate */ switch (drel & RSEG) { case RBSS: dval += hdr.dsize; case RDATA: dval += hdr.tsize; } if ((t = token()) != LPAREN) { nexttoken = t; return(0); } reg2 = regexpr(); if ((t = token()) != COMMA) nreg = 1; else { reg3 = regexpr(); nreg = 2; t = token(); } if (t != RPAREN) xerror(errx); return(nreg); } /* * Evaluate an expression which is expected to return * a 4-bit absolute value */ regexpr() { register ret; register r; ret = 0; r = expr(); if (pass && (r != RABS || (ret = exp.val) & ~0xf)) error(errv); return(ret); } /* * SQUEZ 'optimization' routines * * During pass 1, while final values of labels are being calculated, an * attempt is made to shrink instructions to shorter equivalent forms: * RI2 -> RI1 -> SF = 6; } return(lastsq = b); } /* * Save the next sequential pair of squeeze bits */ setsqz(b) { register p; if (pass > 1) { if (b == lastsq) return; /* * instruction length has changed - need another pass 2 */ passg = 0; if ((sbits += 2) > 6) { pbits--; sbits = 0; } } p = *pbits & ~(03<= squeztop && brk(squeztop += SQSIZE) < 0) { printf(nocore); exit(1); } } } /* * List location counter value */ lstloc() { lstx(curseg->loc, 5, lstbuf.l_loc); lstbuf.l_locr = lstreloc(currel); } /* * List the operand address */ lstaddr(val, rel) { lstx(val, 8, lstbuf.l_add); lstbuf.l_addr = lstreloc(rel); } /* * List a halfword of code/data */ lsth(val) { if (listp < &lstbuf.l_data[19]) lstx(val, 4, listp); listp += 5; } /* * List a byte of data */ lstb(val) { register n; if (listp < &lstbuf.l_data[19]) { for (n = listp-lstbuf.l_data; (n -= 5) > 0; ) ; chdir src ar ru /lib/libS.a rm *.o rm *.c ar() getc(stdin) #define putc(x,p) (--(p)->_cnt>=0? (*(p)->_ptr++=(x)):_flsbuf((x),p)) #define putchar(x) putc(x,stdout) #define feof(p) (((p)->_flag&_IOEOF)!=0) #define ferror(p) (((p)->_flag&_IOERR)!=0) #define fileno(p) p->_file FILE *fopen(); FILE *freopen(); #define _U 01 #define _L 02 #define _A 03 #define _N 04 #define _S 010 extern char _ctype[]; #define isalpha(c) (_ctype[c]&_A) #define isupper(c) (_ctype[c]&_U) #define islower(c) (_ctype[c]&_L) #define isdigit(c) (_ctype[c]&_N) #define isspac_L, _L, _L, _L, _L, 0, 0, 0, 0, 0 }; data.c#include "stdio.h" char _sibuf[BUFSIZ]; char _sobuf[BUFSIZ]; struct _iobuf _iob[_NFILE] { { _sibuf, 0, _sibuf, _IOREAD, 0}, { NULL, 0, NULL, _IOWRT, 1}, {NULL, 0, NULL, _IOWRT+_IONBF, 2}, }; /* * Ptr to end of buffers */ struct _iobuf *_lastbuf { &_iob[_NFILE] }; doprnt.cH /*** *** Quick-and-dirty modification of printf to make a _doprnt *** for the standard i/o library ***/ /* * Printf: * Print formatted data t * RX branch -> SF branch * RX3 -> RX2 or RX1 * Since labels must not move during the code generation pass, the lengths * of all squeezable instructions are recorded in a bitmap (or, more precisely, * a two-bit map: each pair of bits gives the length in halfwords of the * corresponding instruction). In pass 2, instructions are squeezed only if * the bitmap shows that they were squeezed during pass 1. * In pathological cases, the operand of a squeezable instruction may * move out of range during scc -n -s -o as as?.c if (n == -1) listp++; lstx(val, 2, listp); } listp += 2; } /* * Print out listing line */ putline() { extern char linebuf[]; if (passl) printf("%.33s %5d %s", &lstbuf, line, linebuf); } /* * List number in hex with leading zeroes */ lstx(value, nibbles, buf) char *buf; register value; { register char *p; for (p = buf+nibbles; --p >= buf; ) { *p = "0123456789ABCDEF"[value&0xf]; value >>= 4; } } /* * Convert relocation type to readable value */ lstreloc(rel) { switch (rel&RSEGStandard I/O Library src - source for all standard io library routines pdp11 - contains original pdp11 assembly versions of some routines - malloc.c is original malloc(), which has been replaced (temporarily?) with a copy of alloc() from liba e(c) (_ctype[c]&_S) #define toupper(c) ((c)-'a'+'A') #define tolower(c) ((c)-'A'+'a') o standard output file. * For external description, see man(iii). * */ #include "stdio.h" int _prfwidth, _prfprec; /* Width & precision */ _doprnt(afmt, aargs, file) char *afmt; int *aargs; FILE *file; { register char *fmt, *p; register int *argp, left, c, n; static char buff[128]; /* * argp is used to step along list of arguments, since * the number of args is not known in advance. */ argp = aargs; p = buff; for (fmt = afmt; c = *fmt; fmt++) { /* * Copy format string to outputubsequent squeezing. If pass 2 finds that an * instruction has grown longer, the 'passg' flag is reset, causing assemble() * to repeat the code generation pass. * */ #define SQSIZE 512 /* allocation increment for bitmap */ char *squezmap; /* bitmap of squeezable instructions */ char *squeztop; /* end of bitmap */ char *pbits; /* current byte position in bitmap */ int sbits; /* current bit position in *pbits */ int lastsq; /* last squeeze bits returned */ char *nocore = "Out of squeeze space\cp as /bin rm as as?.o ) { case RABS: return('a'); case RTEXT: return('t'); case RDATA: return('d'); case RBSS: return('b'); case REXT: return('U'); default: return('?'); } } #define _U 01 #define _L 02 #define _A 03 #define _N 04 #define _S 010 extern char _ctype[]; #define isalpha(c) (_ctype[c]&_A) #define isupper(c) (_ctype[c]&_U) #define islower(c) (_ctype[c]&_L) #define isdigit(c) (_ctype[c]&_N) #define isspace(c) (_ctype[c]&_S) #define toupper(c) ((c)-'a'+'A') #define tolower(c) ((c)-'A'+'a') ecalloc.cp#include "stdio.h" /* calloc - allocate and clear memory block */ #define BYTESPERWD (sizeof(int)/sizeof(char)) int *malloc(); int *calloc(num, size) unsigned num; { register *p, *q; register m; num =* size; if((p=malloc(num)) != NULL) { q = p; m = (num+BYTESPERWD-1)/BYTESPERWD; while(--m>=0) *q++ = 0; } return(p); } cfree(p) int *p; { free(p); } clrerr.cd#include "stdio.h" clearerr(iop) register struct _iobuf *iop; { iop->_flag =& ~(_I string until * escape character is encountered. */ if (c != '%') { *p++ = c; continue; } if (p > buff) _strout(buff, p-buff, 0, file); /* '-' means left-justification of field. */ left = 0; if ((c = *++fmt) == '-') { left++; fmt++; } /* Convert width field if present. */ n = 0; while ((c = *fmt) <= '9' && c >= '0') { n =* 10; n =+ c - '0'; fmt++; } _prfwidth = n; /* Convert precision field if present. */ n = 0; if (c == '.') while ((c = *++fmt)n"; /* * Allocate squeeze bitmap at end of symbol table * - called at the beginning of pass 1 */ sqzalloc() { squezmap = (char *)nextsym; squeztop = (char *)symtop; if (squeztop <= squezmap && brk(squeztop += SQSIZE) < 0) { printf(nocore); exit(1); } } /* * Initialize for squeeze pass */ sqzinit() { pbits = squezmap; sbits = 6; nsquez = 0; } /* * Return next sequential pair of squeeze bits */ getsqz() { register b; b = (*pbits>>sbits)&03; if ((sbits -= 2) < 0) { pbits++; sbits /* * Assembler listing routines * * * Copyright (C) 1978, Richard Miller */ #define EXTERN extern #include "as.h" /* * Buffer for listing */ struct { char l_loc[5]; char l_locr; char l_fill1[1]; char l_data[16]; char l_add[8]; char l_addr; char l_fill3[1]; } lstbuf; char *listp; /* current output position in l_data */ /* * Initialize listing buffer */ lstinit() { register char *p; register n; p = &lstbuf; for (n = sizeof(lstbuf); n--; p++) *p = ' '; listp = &lstbuf.l_data[0]; }chdir src ar x src.a cc -c *.c stripsym *.o #define BUFSIZ 512 #define _NFILE 20 # ifndef FILE extern struct _iobuf { char *_ptr; int _cnt; char *_base; char _flag; char _file; } _iob[_NFILE]; # endif #define _IOREAD 01 #define _IOWRT 02 #define _IONBF 04 #define _IOMYBUF 010 #define _IOEOF 020 #define _IOERR 040 #define _IOSTRG 0100 #define NULL 0 #define FILE struct _iobuf #define EOF (-1) #define stdin (&_iob[0]) #define stdout (&_iob[1]) #define stderr (&_iob[2]) #define getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p)) #define getchOERR|_IOEOF); } ctype.c#include "ctype.h" char _ctype[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, _S, _S, _S, _S, _S, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _S, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _N, _N, _N, _N, _N, _N, _N, _N, _N, _N, 0, 0, 0, 0, 0, 0, 0, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, 0, 0, 0, 0, 0, 0, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, <= '9' && c >= '0') { n =* 10; n =+ c - '0'; } _prfprec = n; /* * Print the argument in the requested format. * If _prf1() returns <0, an unknown character followed * the '%', so the argument was not used. Otherwise, * step to the next argument. */ if (_prf1(c, *argp, left, buff, file) >= 0) argp++; p = buff; } if (p > buff) _strout(buff, p-buff, 0, file); } /* * Print a single argument according to the given format character. * Left-justify if left == 1. */ char prfhex[] { "0123456789ABCDEF" }; /* Hexadecimal digits */ _prf1(fmt, arg, left, buff, file) char *buff; FILE *file; { register int x, len, c; register char *p, *lastc; /* Initialize pointers to first & last+1 char in buffer. */ x = arg; lastc = p = &buff[32]; switch (fmt) { /* Unknown character: just print the format char. */ default: *--p = fmt; fmt = -1; break; /* Single character */ case 'c': case 'C': if (x) *--p = x; break; /* String: set pointers to first & last+1 cha} doscan.c##include "stdio.h" #define SPC 01 #define STP 02 char *_getccl(); char _sctab[128] { 0,0,0,0,0,0,0,0, 0,SPC,SPC,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, SPC,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, }; _doscan(iop, fmt, argp) register char *fmt; register int *argp; { register int ch; int nmatch, len, ch1; int *ptr, fileended; nmatch = 0; fileended = 0; for (;;) switch (ch = *fmt++) { case '\0': return (nmatch); case '%': ifc<='9' || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) { ndigit++; if (base==8) lcval =<<3; else if (base==10) lcval = ((lcval<<2) + lcval)<<1; else lcval =<< 4; c1 = c; if ('0'<=c && c<='9') c =- '0'; else if ('a'<=c && c<='f') c =- 'a'-10; else c =- 'A'-10; lcval =+ c; c = c1; continue; } else if (c=='.') { if (base!=10 || scale==0) break; ndigit++; continue; } else if ((c=='e'||c=='E') && expseen==0) { if (base!=10 || stdio.h" _error(s) register char *s; { static reentered; if (reentered) _exit(0177); write(2, s, strlen(s)); exit(0176); } exit.c'{/*** *** Special version of exit() to flush all output buffers ***/ exit(code) int code; { _cleanup(); _exit(code); } )fftoa.c/* * Fake version of ftoa for programs with no floating pt */ ftoa(x, str, prec, format) float x; char *str; { str[0] = '?'; str[1] = '\0'; } fgetc.c'?#include "stdio.h" fgetc( } iop->_base = _sobuf; iop->_ptr = _sobuf; goto tryagain; } if ((iop->_base=base=malloc(BUFSIZ)) == NULL) { iop->_flag =| _IONBF; goto tryagain; } iop->_flag =| _IOMYBUF; n = 1; } else if ((n = iop->_ptr - base) > 0) n = write(fileno(iop), base, n); iop->_cnt = BUFSIZ-1; *base++ = c; iop->_ptr = base; } if (n < 0) { iop->_flag =| _IOERR; return(-1); } return(c); } fflush(iop) register struct _iobuf *iop; { register char *base; register n; if ((istdio.h" fputs(s, iop) register char *s; register FILE *iop; { register c; while (c = *s++) putc(c, iop); } freopen.ci#include "stdio.h" struct _iobuf *freopen(file, mode, iop) char *file; register char *mode; register struct _iobuf *iop; { register f; fclose(iop); if (*mode=='w') f = creat(file, 0666); else if (*mode=='a') { if ((f = open(file, 1)) < 0) f = creat(file, 0666); seek(f, 0, 2); } else f = open(file, 0); if (f < 0) return(NULL); iop->_file = f; if r. */ case 's': case 'S': p = lastc = x; while (*lastc) lastc++; break; /* Octal */ case 'o': case 'O': do *--p = (x & 07) + '0'; while (x =>> 3); break; /* Hexadecimal */ case 'x': case 'X': do *--p = prfhex[x & 017]; while (x =>> 4); break; /* Signed decimal */ case 'd': case 'D': if (x < 0) x = -arg; /* Unsigned decimal */ case 'l': case 'L': do *--p = (x % 10) + '0'; while (x =/ 10); if (arg < 0 && (fmt == 'd' || fmt == 'D')) *--p = '-'; break; ((ch = *fmt++) == '%') goto def; ptr = 0; if (ch != '*') ptr = *argp++; else ch = *fmt++; len = 0; while (ch>='0' && ch <='9') { len = len*10 + ch - '0'; ch = *fmt++; } if (len == 0) len = 30000; if (ch=='l') { ch = *fmt++; if (ch>='a' && ch<='z') ch =+ 'A'-'a'; } else if (ch=='[') fmt = _getccl(fmt); if (ch == '\0') _error("scanf\n"); if (_innum(ptr, ch, len, iop, &fileended) && ptr) nmatch++; if (fileended) return(nmatch? nmatch: -1); breascale==0 || ndigit==0) break; expseen++; *np++ = c; c = getc(iop); if (c!='+'&&c!='-'&&('0'>c||c>'9')) break; } else break; } if (negflg) lcval = -lcval; if (c != EOF) { ungetc(c, iop); *eofptr = 0; } else *eofptr = 1; if (ptr==NULL || np==numbuf) return(0); *np++ = 0; if (scale==0) if (size) *ptr.longptr = lcval; else *ptr = lcval; else if (size) *ptr.dblptr = atof(numbuf); else *ptr.fltptr = atof(numbuf); return(1); } _instr(ptr, type, len, fp) FILE *fp; { return(getc(fp)); } fgets.c(#include "stdio.h" fgets(s, n, iop) char *s; register FILE *iop; { register c; register char *cs; cs = s; while (--n>0 && (c = getc(iop))>=0) { *cs++ = c; if (c=='\n') break; } if (c<0 && cs==s) return(NULL); *cs++ = '\0'; return(s); } tfilbuf.c)#include "stdio.h" _filbuf(iop) register struct _iobuf *iop; { static char smallbuf[_NFILE]; if ((iop->_flag&_IOREAD) == 0) _error("Reading bad file\n"); ifop->_flag&(_IONBF|_IOWRT))==_IOWRT && (base=iop->_base)!=NULL && (n=iop->_ptr-base)>0) { iop->_ptr = base; iop->_cnt = BUFSIZ; if (write(fileno(iop), base, n)!=n) iop->_flag =| _IOERR; } } /* * Flush buffers on exit */ _cleanup() { register struct _iobuf *iop; extern struct _iobuf *_lastbuf; for (iop = _iob; iop < _lastbuf; iop++) fclose(iop); } fclose(iop) register struct _iobuf *iop; { if (iop->_flag&(_IOREAD|_IOWRT)) { fflush(iop); close(fileno(iop)); if (iop->_flag&_IOMYBUF(*mode != 'r') iop->_flag =| _IOWRT; else iop->_flag =| _IOREAD; return(iop); } fseek.c-%#include "stdio.h" /* * Seek for standard library. Coordinates with buffering. */ fseek(iop, offset, ptrname) FILE *iop; long offset; { register n, resync; if (iop->_flag&_IOREAD) { resync = 0; if (ptrname==1) { /* relative */ n = iop->_cnt; if (n<0) n = 0; } else { n = offset&01; resync = n; } n = lseek(fileno(iop), offset - n, ptrname); iop->_cnt = 0; if (        *   % +  & ,  ! ' -  " ( .  # ) / 0 6 < B 1 7 = C 2 8 > D 3 9 ? E 4 : @k; case ' ': case '\n': case '\t': break; default: def: if (ch != (ch1 = getc(iop))) return(ch1==EOF? -1: nmatch); } } _innum(ptr, type, len, iop, eofptr) int *ptr, *eofptr; struct _iobuf *iop; { extern double atof(); struct { double *dblptr;}; struct { long *longptr;}; struct { float *fltptr;}; register char *np; char numbuf[64]; register c, base; int expseen, scale, size, negflg, c1, ndigit; long lcval; if (type=='c' || type=='s' || type=='[') return(_instr(ptr, type, len, iiop, eofptr) register char *ptr; register struct _iobuf *iop; int *eofptr; { register ch; register char *optr; int ignstp; *eofptr = 0; optr = ptr; if (type=='c' && len==30000) len = 1; ignstp = 0; if (type=='s') ignstp = SPC; while (_sctab[ch = getc(iop)] & ignstp) if (ch==EOF) break; ignstp = SPC; if (type=='c') ignstp = 0; else if (type=='[') ignstp = STP; while (--len>=0 && ch>=0 && (_sctab[ch]&ignstp)==0) { if (ptr) *ptr++ = ch; ch = getc(iop); } if (ch != EOF) { u (iop->_flag&_IOSTRG) return(-1); tryagain: if (iop->_base==NULL) { if (iop->_flag&_IONBF) { iop->_base = &smallbuf[fileno(iop)]; goto tryagain; } if ((iop->_base = malloc(BUFSIZ)) == NULL) { iop->_flag =| _IONBF; goto tryagain; } iop->_flag =| _IOMYBUF; } iop->_ptr = iop->_base; iop->_cnt = read(fileno(iop), iop->_ptr, iop->_flag&_IONBF?1:BUFSIZ); if (--iop->_cnt < 0) { if (iop->_cnt == -1) iop->_flag =| _IOEOF; else iop->_flag =| _IOERR; iop->_cnt = 0; return(-1)) free(iop->_base); } iop->_base = NULL; iop->_flag =& ~(_IOREAD|_IOWRT|_IONBF|_IOMYBUF|_IOERR|_IOEOF); iop->_cnt = 0; return(0); } fopen.c,I#include "stdio.h" struct _iobuf *fopen(file, mode) register char *mode; { register f; register struct _iobuf *iop; extern struct _iobuf *_lastbuf; for (iop = _iob; iop->_flag&(_IOREAD|_IOWRT); iop++) if (iop >= _lastbuf) return(NULL); if (*mode=='w') f = creat(file, 0666); else if (*mode=='a') { if ((f = open(file, 1)) < 0) resync) getc(iop); return(n); } if (iop->_flag&_IOWRT) { fflush(iop); return(lseek(fileno(iop), offset, ptrname)); } _error("fseek\n"); } nftell.c.#include "stdio.h" /* * Return file offset. * Coordinates with buffering. */ long tell(); long ftell(iop) FILE *iop; { long tres; register adjust; if (iop->_cnt < 0) iop->_cnt = 0; if (iop->_flag&_IOREAD) adjust = - iop->_cnt; else if (iop->_flag&_IOWRT) { adjust = 0; if (iop->_base && (iop->_flag&_IONBF)==0) /* Floating point */ case 'f': case 'F': case 'e': case 'E': p = lastc = buff; ftoa(x, p, _prfprec, fmt); while (*lastc) lastc++; _prfprec = 0; break; } /* Compute len = -(no. of pad chars needed to fill width) */ len = lastc - p; if (_prfprec && len > _prfprec) { len = _prfprec; lastc = p + len; } if ((len =- _prfwidth) > 0) len = 0; if (left) len = -len; _strout(p, lastc-p, len, file, ' '); /* Returned value >=0 asks printf to step to next argument. */ return(fmt); op, eofptr)); lcval = 0; ndigit = 0; size = 0; if (type>='A' && type <='Z') { size++; type =+ 'a'-'A'; } scale = 0; if (type=='e'||type=='f') scale++; base = 10; if (type=='o') base = 8; else if (type=='x') base = 16; np = numbuf; expseen = 0; negflg = 0; while ((c = getc(iop))==' ' || c=='\t' || c=='\n'); if (c=='-') { negflg++; *np++ = c; c = getc(iop); len--; } else if (c=='+') { len--; c = getc(iop); } for ( ; --len>=0; *np++ = c, c = getc(iop)) { if ('0'<=c && ngetc(ch, iop); *eofptr = 0; } else *eofptr = 1; if (ptr && ptr!=optr) { if (type!='c') *ptr++ = '\0'; return(1); } return(0); } char * _getccl(s) register char *s; { register c, t; t = 0; if (*s == '^') { t++; s++; } for (c = 0; c < 128; c++) if (t) _sctab[c] =& ~STP; else _sctab[c] =| STP; while (((c = *s++)&0177) != ']') { if (t) _sctab[c++] =| STP; else _sctab[c++] =& ~STP; if (c==0) return(--s); } return(s); } herror.c%#include "; } return(*iop->_ptr++&0377); } flsbuf.c+L#include "stdio.h" _flsbuf(c, iop) register struct _iobuf *iop; { register n; register char *base; char c1; static gttybuf[4]; extern char _sobuf[]; if ((iop->_flag&_IOWRT)==0) _error("writing\n"); tryagain: if (iop->_flag&_IONBF) { c1 = c; n = write(fileno(iop), &c1, 1); iop->_cnt = 0; } else { if ((base=iop->_base)==NULL) { if (iop==stdout) { if (gtty(1, gttybuf)>=0) { iop->_flag =| _IONBF; goto tryagain; f = creat(file, 0666); seek(f, 0, 2); } else f = open(file, 0); if (f < 0) return(NULL); iop->_flag =& ~(_IOREAD|_IOWRT); iop->_file = f; if (*mode != 'r') iop->_flag =| _IOWRT; else iop->_flag =| _IOREAD; return(iop); } fprintf.cej#include "stdio.h" fprintf(iop, fmt, args) struct _iobuf *iop; char *fmt; { _doprnt(fmt, &args, iop); } fputc.c,E#include "stdio.h" fputc(c, fp) FILE *fp; { return(putc(c, fp)); } *fputs.c,|#include " adjust = iop->_ptr - iop->_base; } else _error("ftell\n"); tres = tell(fileno(iop)); if (tres<0) return(tres); tres =+ adjust; return(tres); } ftoa.c?/* * Floating-point to ASCII conversion */ int fltused 0; /* forces loading if floating pt used in C program */ ftoa (x, str, prec, format) float x; char *str; { /* converts a floating point number to an ascii string */ /* x is stored into str, which should be at least 30 chars long */ int ie, i, k, ndig, fstyle; double y; ndig= ( prec<=0) ? 7 : (prec > 22 ? 23 : prec+1); if (format == 'f' || format == 'F') fstyle = 1; else fstyle = 0; /* print in eformat unless last arg is 'f' */ ie = 0; /* if x negative, write minus and reverse */ if ( x < 0) { *str++ = '-'; x = -x; } /* put x in range 1 <= x < 10 */ if (x > 0.0) while (x < 1.0) { x =* 10.0; ie--; } while (x >= 10.0) { x = x/10.0; ie++; } /* in f format, number of digits is related to size */ if (fstyle) ndig =+ ie; /* roun *p2++ = 'e'; if (decpt<0) { decpt = -decpt; *p2++ = '-'; } else *p2++ = '+'; *p2++ = decpt/10 + '0'; *p2++ = decpt%10 + '0'; } else { if (decpt<=0) { *p2++ = '.'; while (decpt<0) { decpt++; *p2++ = '0'; } } for (i=1; i<=ndigit; i++) { *p2++ = *p1++; if (i==decpt) *p2++ = '.'; } if (ndigitword&BUSY)==0) { /* combine adjancent free blocks */ while(((q = *p)->word&BUSY)==0) *p = *q; /* q -> end of current free block */ if(q >= &p[nwords]) goto found; } q = p; p = p->word & ~BUSY; } while(q>=allocp || p=0) putc(*string++, file); while (adjust) { putc(fillch, file); adjust--; } } stuff.c<7int yyportlib 1; wdleng() { return(8*sizeof(int)); } ,system.c<G#define INTR 2 #define QUIT 3 system(s) char *s; { int status; register int *istat, *qstat; if (fork() == 0) { execl("/bin/sh", "sh", "-c", s, 0); _eit mov $' ,zfill cmpb *formp,$'- bne 2f inc formp inc rjust 2: cmpb *formp,$'0 bne 2f mov $'0,zfill 2: jsr r3,gnum mov r1,width clr ndfnd cmp r0,$'. bne 1f jsr r3,gnum mov r1,ndigit 1: mov $swtab,r1 1: mov (r1)+,r2 bne 2f movb r0,(r3)+ jmp prbuf 2: cmp r0,(r1)+ bne 1b jmp (r2) .data swtab: decimal; 'd octal; 'o hex; 'x float; 'f scien; 'e general; 'g charac; 'c string; 's longorunsg; 'l longorunsg; 'L unsigned; 'u remote; 'r long; 'D loct; 'O lhex; 'X lunsigd. x is between 1 and 10 and ndig will be printed to right of decimal point so rounding is ... */ for (y = i = 1; i < ndig; i++) y = y/10.; x =+ y/2.; if (x >= 10.0) {x = 1.0; ie++;} /* repair rounding disasters */ /* now loop. put out a digit (obtain by multiplying by 10, truncating, subtracting) until enough digits out */ /* if fstyle, and leading zeros, they go out special */ if (fstyle && ie<0) { *str++ = '0'; *str++ = '.'; if (ndig < 0) ie = ie-ndig; /* limit zeros if underflow */ uf) int uid; char buf[]; { static FILE *pwf; register n, c; register char *bp; if(pwf == 0) pwf = fopen("/etc/passwd", "r"); if(pwf == NULL) return(1); rewind(pwf); uid =& 0377; for (;;) { bp = buf; while((c=getc(pwf)) != '\n') { if(c <= 0) return(1); *bp++ = c; } *bp++ = '\0'; bp = buf; n = 3; while(--n) while((c = *bp++) != ':') if(c == '\n') return(1); while((c = *bp++) != ':') { if(c<'0' || c>'9') continue; n = n*10+c-'0'; } if(n == uid) only on 1st storage request */ alloct->word =| BUSY; alloct = (*t = &t[BLOK]-1); *alloct = allocs; alloct->word =| BUSY; } found: allocp = &p[nwords]; if(q>allocp) *allocp = *p; /*ie if only part of a free block reqd*/ *p = allocp.word|BUSY; return(p+1); } free(p) char **p; { allocp = p-1; allocp->word =& ~BUSY; /* set pointer not busy */ } printf.c2H#include "stdio.h" printf(fmt, args) { _doprnt(fmt, &args, stdout); } puts.c3p#include "stdio.h" #include "stdio.h" setbuf(iop, buf) register struct _iobuf *iop; { if (iop->_base != NULL && iop->_flag&_IOMYBUF) free(iop->_base); iop->_flag =& ~(_IOMYBUF|_IONBF); if ((iop->_base = buf) == NULL) iop->_flag =| _IONBF; else iop->_ptr = iop->_base; iop->_cnt = 0; } sprintf.co#include "stdio.h" char *sprintf(str, fmt, args) char *str, *fmt; { struct _iobuf _strbuf; _strbuf._flag = _IOWRT+_IOSTRG; _strbuf._ptr = str; _strbuf._cnt = 32767; _doprnt(fmt, &args, &_strbuf);xit(127); } istat = signal(INTR, 1); qstat = signal(QUIT, 1); if (wait(&status) == -1) status = -1; signal(INTR, istat); signal(QUIT, qstat); return(status); } etmpnam.c<echar *tmpnam(s) char *s; { static seed; sprintf(s, "temp.%d.%d", getpid(), seed++); return(s); } fungetc.c=#include "stdio.h" ungetc(c, iop) register struct _iobuf *iop; { if ((iop->_flag&_IOREAD)==0 || iop->_ptr <= iop->_base) if (iop->_ptr == iop->_base && iop->_cnt==0) *iop->_ptr+ned; 'U 0; 0 .text general: mov ndigit,r0 mov ndfnd,r2 jsr pc,pgen jbr prbuf longorunsg: movb *formp,r0 inc formp cmp r0,$'o beq loct cmp r0,$'x beq lhex cmp r0,$'d beq long cmp r0,$'u beq lunsigned dec formp br unsigned octal: clr r0 br 1f loct: mov (r4)+,r0 1: mov $8.,r2 br 2f hex: clr r0 br 1f lhex: mov (r4)+,r0 1: mov $16.,r2 2: mov (r4)+,r1 br compute decimal: mov (r4)+,r1 sxt r0 bmi 3f br 2f unsigned: clr r0 br 1f long: mov (r4)+,r0 bge 1f mov (r4)+,r1 3: for (i = -1; i > ie; i--) *str++ = '0'; } for (i=0; i < ndig; i++) { k = x; *str++ = k + '0'; if (i == (fstyle ? ie : 0)) /* where is decimal point */ *str++ = '.'; x =- (y=k); x =* 10.0; } /* now, in estyle, put out exponent if not zero */ if (!fstyle && ie!= 0) { *str++ = 'E'; if (ie < 0) { ie = -ie; *str++ = '-'; } for (k=100; k > ie; k =/10); for (; k >0; k =/10) { *str++ = ie/k + '0'; ie = ie%k; } } *str = '\0'; return; } egcvt.creturn(0); } return(1); } gets.c/#include "stdio.h" gets(s) char *s; { register c; register char *cs; cs = s; while ((c = getchar()) != '\n' && c >= 0) *cs++ = c; if (c<0 && cs==s) return(NULL); *cs++ = '\0'; return(s); } getw.c0#include "stdio.h" getw(iop) register struct _iobuf *iop; { register i; i = getc(iop); if (iop->_flag&_IOEOF) return(-1); return(i | (getc(iop)<<8)); } intss.c0%intss() { return(ttyn(0) != 'x'); } rputs(s) register char *s; { register c; while (c = *s++) putchar(c); putchar('\n'); } putw.c4o#include "stdio.h" putw(i, iop) register i; register struct _iobuf *iop; { putc(i, iop); putc(i>>8, iop); } rdwr.c4H#include "stdio.h" fread(ptr, size, count, iop) register char *ptr; register struct _iobuf *iop; { register c; int ndone, s; ndone = 0; if (size) for (; ndone= 0) *ptr++ = c; e putc('\0', &_strbuf); return(str); } strcat.c7/* * Concatenate s2 on the end of s1. S1's space must be large enough. * Return s1. */ char * strcat(s1, s2) register char *s1, *s2; { register os1; os1 = s1; while (*s1++) ; *--s1; while (*s1++ = *s2++) ; return(os1); } )strcmp.c8/* * Compare strings: s1>s2: >0 s1==s2: 0 s1_cnt++; *--iop->_ptr = c; } neg r0 neg r1 sbc r0 movb $'-,(r3)+ br 2f lunsigned: mov (r4)+,r0 1: mov (r4)+,r1 2: mov $10.,r2 / / Algorithm courtesy Keith Davis / compute: mov r5,-(sp) mov r4,-(sp) mov r0,r4 mov r1,r5 ashc $0,r4 beq 1f tst ndigit beq 1f movb $'0,(r3)+ 1: jsr pc,1f mov (sp)+,r4 mov (sp)+,r5 br prbuf 1: clr r0 mov r4,r1 beq 2f div r2,r0 mov r0,r4 mov r1,r0 2: mov r5,r1 asl r2 div r2,r0 asr r2 asl r0 cmp r2,r1 bgt 2f sub r2,r1 inc r0 2: mov r1,-(sp) mov r0,r5 bne 2f tst r4 beq ./* * gcvt - Floating output conversion to * minimal length string */ gcvt(number, ndigit, buf) double number; char *buf; { int sign, decpt; register char *p1, *p2; register i; p1 = ecvt(number, ndigit, &decpt, &sign); p2 = buf; if (sign) *p2++ = '-'; for (i=ndigit-1; i>0 && p1[i]=='0'; i--) ndigit--; if (decpt >= 0 && decpt-ndigit > 4 || decpt < 0 && decpt < -3) { /* use E-style */ decpt--; *p2++ = *p1++; *p2++ = '.'; for (i=1; i_cnt = 0; iop->_ptr = iop->_base; iop->_f; } strcpy.c8/* * Copy string s2 to s1. s1 must be large enough. * return s1 */ char * strcpy(s1, s2) register char *s1, *s2; { register os1; os1 = s1; while (*s1++ = *s2++) ; return(os1); } strlen.c8Wstrlen(s) register char *s; { register n; n = 0; while (*s++) n++; return(n); } 1strout.c;#include "stdio.h" _strout(string, count, adjust, file, fillch) register char *string; register count; int adjust; register struct _iobuf *file; / C library -- conversions .globl __doprnt .globl pfloat .globl pscien .globl pgen .globl __strout .globl csv .globl cret __doprnt: jsr r5,csv sub $128.,sp mov 4(r5),formp / format mov 6(r5),r4 loop: mov sp,r3 mov formp,r1 2: movb (r1)+,r2 beq 2f cmp r2,$'% beq 2f movb r2,(r3)+ br 2b 2: mov r1,formp cmp r3,sp beq 2f mov sp,r0 mov 8(r5),-(sp) clr -(sp) mov r3,-(sp) sub r0,(sp) mov r0,-(sp) jsr pc,__strout add $8,sp 2: tst r2 bne 2f jmp cret 2: mov sp,r3 2: clr rjust clr ndig1f 2: jsr pc,1b 1: mov (sp)+,r0 add $'0,r0 cmp r0,$'9 ble 1f add $'a-'0-10.,r0 1: movb r0,(r3)+ rts pc charac: movb (r4)+,(r3)+ bne 1f dec r3 1: movb (r4)+,(r3)+ bne prbuf dec r3 br prbuf string: mov ndigit,r1 mov (r4),r2 mov r2,r3 bne 1f mov $nulstr,r2 mov r2,r3 mov r2,(r4) 1: tstb (r2)+ beq 1f inc r3 sob r1,1b 1: mov (r4)+,r2 br prstr float: mov ndigit,r0 mov ndfnd,r2 jsr pc,pfloat br prbuf scien: mov ndigit,r0 inc r0 tst ndfnd bne 1f mov $7,r0 1: mov pc,r2 jsr pc,pscien br prbuf remote: mov (r4)+,r4 mov (r4)+,formp jmp loop prbuf: mov sp,r2 prstr: sub r2,r3 mov width,r1 sub r3,r1 bge 1f clr r1 1: tst rjust bne 1f neg r1 1: mov zfill,-(sp) mov 8(r5),-(sp) mov r1,-(sp) mov r3,-(sp) mov r2,-(sp) jsr pc,__strout add $10.,sp jmp loop gnum: clr ndfnd clr r1 1: movb *formp,r0 inc formp sub $'0,r0 cmp r0,$'*-'0 bne 2f mov (r4)+,r0 br 3f 2: cmp r0,$9. bhi 1f 3: inc ndfnd mul $10.,r1 add r0,r1 br 1b 1: add $'0,r0 rts r3 .bss width:,(r3)+ 2: clr r0 div $10.,r0 add $'0,r0 movb r0,(r3)+ add $'0,r1 movb r1,(r3)+ rts pc s.byte[BYTESPERPTR]; /*last cell of arena*/ char *allocx; /*for benefit of realloc*/ #define block allocx /*perhaps gratuitous space saving*/ malloc(nbytes) { register nb; register char *p, *q; nb = (nbytes+BYTESPERPTR+BYTESPERPTR-1)&~(BYTESPERPTR-1); ASSERT(allocp>(&allocs.byte[0])&&allocp<=alloct); for(p=allocp; ; ) { for(allocx=0; ; ) { if(!(p->ptr&BUSY)) { while(!((q=p->ptr)->ptr&BUSY)) { ASSERT(q>p); ASSERT(qptr = q->ptr; } if(q>=p+nb && p+nb>p) line = 0; else line = chset[c-' '][realh]; for (w = 1<<(CWIDTH-1); w; w>>=1) putchar(w&line? FILL : SPACE); for (w = 0; w < CSPACE; w++) putchar(SPACE); } putchar('\n'); } } while (*(s = p)); } 011, 036, 037, 020, 020, 034, 020, 020, 037, 037, 020, 020, 034, 020, 020, 020, 017, 020, 020, 023, 021, 021, 017, 021, 021, 021, 037, 021, 021, 021, 016, 004, 004, 004, 004, 004, 016, 001, 001, 001, 001, 001, 021, 016, 021, 022, 024, 020, 024, 022, 021, 020, 020, 020, 020, 020, 020, 037, 021, 033, 025, 025, 021, 021, 021, 021, 031, 025, 023, 021, 021, 021, 037, 021, 021, 021, 021, 021, 037, 036, 021, 021, 036, 020, 020, 020, 016, 021, 021, 021, 025, 022, 015, 036, 021, 021, 036, 024, 022, 02104, 004, 010, 000, 000, 001, 016, 020, 000, 000, 012, 025, 012, 025, 012, 025, 012 }; .=.+2 formp: .=.+2 rjust: .=.+2 ndfnd: .=.+2 ndigit: .=.+2 zfill: .=.+2 .data nulstr: <(null)\0> / C library-- fake floating output .globl pfloat .globl pscien .globl pgen pfloat: pscien: pgen: add $8,r4 movb $'?,(r3)+ rts pc goto found; } q = p; p = p->ptr & ~BUSY; if(p>q) { ASSERT(p<=alloct); } else if(q!=alloct||p!=&allocs.byte[0]) { write(2,"corrupt arena\n",14); exit(0175); } else if(++allocx>1) break; } block = (nb+BYTESPERPTR+BLOCK-1)&~(BLOCK-1); if((q = sbrk(block)) == -1) return(NULL); ASSERT(q>alloct); alloct->ptr = q; if(q != alloct+BYTESPERPTR) alloct->ptr =| BUSY; alloct = (q->ptr = q+block-BYTESPERPTR); alloct->ptr = allocs.byte+BUSY; } found: allocp = p+nb/* * Banner character set -- 5x7 (copy of DataMedia set) */ # define CHEIGHT 7 # define CWIDTH 5 # define CDEPTH 2 # define CSPACE 1 # define LWIDTH 132 # define FILL '*' # define SPACE ' ' char chset[96][7] = { 000, 000, 000, 000, 000, 000, 000, 004, 004, 004, 004, 004, 000, 004, 012, 012, 012, 000, 000, 000, 000, 012, 012, 033, 000, 033, 012, 012, 004, 017, 024, 016, 005, 036, 004, 031, 031, 002, 004, 010, 023, 023, 010, 024, 024, 010, 025, 022, 015, 014, 014, 014, 000, 000, 000, 000, 002, 004,, 016, 021, 020, 016, 001, 021, 016, 037, 004, 004, 004, 004, 004, 004, 021, 021, 021, 021, 021, 021, 016, 021, 021, 021, 012, 012, 004, 004, 021, 021, 021, 021, 025, 033, 021, 021, 021, 012, 004, 012, 021, 021, 021, 021, 012, 004, 004, 004, 004, 037, 001, 002, 004, 010, 020, 037, 016, 010, 010, 010, 010, 010, 016, 020, 020, 010, 004, 002, 001, 001, 016, 002, 002, 002, 002, 002, 016, 004, 012, 021, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 037, 020, 010, 004, 000, 000, 000, 000, 000, /* * banner [arg ...] * * If no arguments, reads standard input and prints it in block chars * If arguments present, prints arguments in block chars (1 per line) */ main(argc, argv) register int argc; register char **argv; { static char buf[128]; if (argc == 1) { while (gets(buf)) bprint(buf); } else while (--argc) bprint(*++argv); } gets(s) register char *s; { register char *p, c; for (p = s; (c = getchar()) && c != '\n'; p++) *p = c; *p = '\0'; return (c); } / C library-- floating output .globl pfloat .globl pscien .globl pgen .globl fltused .globl _ndigit .globl ecvt .globl fcvt .globl _gcvt fltused: / force loading pgen: mov r3,-(sp) mov r0,-(sp) tst r2 bne 1f mov $6,(sp) 1: movf (r4)+,fr0 movf fr0,-(sp) jsr pc,_gcvt add $8+2+2,sp 1: tstb (r3)+ bne 1b dec r3 rts pc pfloat: mov r0,_ndigit tst r2 bne 1f mov $6,_ndigit 1: movf (r4)+,fr0 jsr pc,fcvt tst r1 beq 1f movb $'-,(r3)+ 1: tst r2 bgt 1f movb $'0,(r3)+ 1: mov r2,r1 ble 1f 2# #define ASSERT(p) #ifdef debug #define ASSERT(p) if(!(p)){botch("p");} botch(s) char *s; { printf("assertion botched: %s\n",s); abort(); } #endif /* C storage allocator * circular first-fit strategy * works with noncontiguous, but monotonically linked, arena * each block is preceded by a ptr to the (pointer of) * the next following block * blocks are even number of words long; low * bit in ptr is 1 for busy, 0 for idle * gaps in arena are merely noted as busy blocks * last block of arena (point; ASSERT(allocp<=alloct); if(q>allocp) { allocx = allocp->ptr; allocp->ptr = p->ptr; } p->ptr = allocp|BUSY; return(p+BYTESPERPTR); } /* freeing strategy tuned for LIFO allocation */ free(p) char *p; { ASSERT((p-BYTESPERPTR)->ptr & BUSY); (allocp = p-BYTESPERPTR)->ptr =& ~BUSY; ASSERT(allocp->ptr>=allocs.ptrs[1]&&allocp->ptrptr > allocp); } 010, 010, 010, 004, 002, 010, 004, 002, 002, 002, 004, 010, 004, 025, 016, 037, 016, 025, 004, 000, 004, 004, 037, 004, 004, 000, 000, 000, 000, 014, 014, 004, 010, 000, 000, 000, 037, 000, 000, 000, 000, 000, 000, 000, 000, 014, 014, 001, 001, 002, 004, 010, 020, 020, 014, 022, 022, 022, 022, 022, 014, 004, 014, 004, 004, 004, 004, 016, 016, 021, 001, 016, 020, 020, 037, 016, 021, 001, 006, 001, 021, 016, 002, 006, 012, 022, 037, 002, 002, 037, 020, 036, 001, 001, 021, 016, 006, 010, 020, 03000, 014, 022, 022, 022, 017, 020, 020, 026, 031, 021, 021, 036, 000, 000, 017, 020, 020, 020, 017, 001, 001, 015, 023, 021, 021, 017, 000, 000, 016, 021, 036, 020, 017, 006, 011, 010, 034, 010, 010, 010, 015, 023, 021, 021, 017, 001, 016, 020, 020, 026, 031, 021, 021, 021, 010, 000, 010, 010, 010, 012, 004, 002, 000, 002, 002, 002, 022, 014, 020, 020, 021, 022, 024, 032, 021, 010, 004, 004, 004, 004, 004, 002, 000, 000, 032, 025, 025, 021, 021, 000, 000, 026, 031, 021, 021, 021, 000, 000, 016# /* * Line printer daemon */ /* File names */ char lpd[] "/usr/lpd"; char lock[] "/usr/lpd/lock"; char printer[] "/dev/pr"; /* * control sequence to set unix default tabs on hydra */ char stabs[] { "\033G008016024032040048056064072080088096104112120128\n" }; /* Buffers */ int cmdbuf[131]; /* for reading command file */ char prbuf[512]; /* for copying file to printer */ char lbuf[64]; /* for assembling lines from command file */ char dbuf[17]; /* for reading directory */ /* Tty modes for printer : movb (r0)+,(r3)+ sob r1,2b 1: mov _ndigit,r1 beq 1f movb $'.,(r3)+ 1: neg r2 ble 1f 2: dec r1 blt 1f movb $'0,(r3)+ sob r2,2b 1: tst r1 ble 2f 1: movb (r0)+,(r3)+ sob r1,1b 2: rts pc pscien: mov r0,_ndigit tst r2 bne 1f mov $6,_ndigit 1: movf (r4)+,fr0 jsr pc,ecvt tst r1 beq 1f movb $'-,(r3)+ 1: movb (r0)+,(r3)+ movb $'.,(r3)+ mov _ndigit,r1 dec r1 ble 1f 2: movb (r0)+,(r3)+ sob r1,2b 1: movb $'e,(r3)+ dec r2 mov r2,r1 bge 1f movb $'-,(r3)+ neg r1 br 2f 1: movb $'+ed to by alloct) is empty and * has a pointer to first * idle blocks are coalesced during space search */ /* all these defines must be powers of 2 */ #define BLOCK 1024 #define BYTESPERPTR 2 #define BUSY 01 #define NULL 0 char *sbrk(); struct { char *ptr; }; struct { char byte[2*BYTESPERPTR]; }; struct { char *ptrs[2]; } allocs /* initial arena */ { &allocs.byte[1*BYTESPERPTR]+BUSY, &allocs.byte[0*BYTESPERPTR]+BUSY }; char *allocp &allocs.byte[BYTESPERPTR]; /*current search ptr*/ char *alloct &alloc#include "chset.h" bprint(s) char *s; { register w, line, c, realh; register char *p; register int col, h; do { for (h=0; h LWIDTH) break; if (c < ' ') c = ' '; realh = h; switch (c) { case 'g': case 'j': case 'p': case 'q': case 'y': case ',': case ';': realh = h - CDEPTH; } if (realh<0 || realh >= CHEIGHT) 6, 021, 021, 016, 037, 001, 002, 004, 010, 020, 020, 016, 021, 021, 016, 021, 021, 016, 016, 021, 021, 017, 001, 002, 014, 000, 014, 014, 000, 000, 014, 014, 014, 014, 000, 014, 014, 004, 010, 001, 002, 004, 010, 004, 002, 001, 000, 000, 037, 000, 037, 000, 000, 020, 010, 004, 002, 004, 010, 020, 014, 022, 002, 004, 004, 000, 004, 016, 021, 001, 015, 025, 025, 016, 004, 012, 021, 021, 037, 021, 021, 036, 011, 011, 016, 011, 011, 036, 016, 021, 020, 020, 020, 021, 016, 036, 011, 011, 011, 011, , 021, 021, 021, 016, 026, 031, 021, 021, 036, 020, 020, 016, 021, 021, 023, 015, 001, 001, 000, 000, 026, 031, 020, 020, 020, 000, 000, 017, 020, 016, 001, 036, 010, 036, 010, 010, 010, 011, 006, 000, 000, 021, 021, 021, 023, 015, 000, 000, 021, 021, 012, 012, 004, 000, 000, 021, 021, 025, 025, 012, 000, 000, 021, 012, 004, 012, 021, 021, 021, 021, 023, 015, 001, 016, 000, 000, 037, 002, 004, 010, 037, 002, 004, 004, 010, 004, 004, 002, 004, 004, 004, 000, 004, 004, 004, 010, 004, 004, 002, 0*/ int ttymode[3] { (11<<8) | 11, /* 2400 baud */ 0, 020 /* CRMOD */ }; main() { register flag; /* Ignore quit, interrupt, hangup */ signal(1, 1); signal(2, 1); signal(3, 1); /* Use lock to prevent multiple active daemons */ if (creat(lock, 0) < 0) exit(0); /* Fork and exit, thus spawning the daemon */ if (fork()) exit(0); /* Before opening the printer, make sure there's something to print */ close(0); close(1); close(2); if (open(lpd, 0) != 0) dexit(); flag = 0; while (read(0, dbuf, 16) == 16) if ((dbuf[0] | dbuf[1]) != 0 && dbuf[2] == 'd' && dbuf[3] == 'f') flag++; if (!flag) dexit(); /* Open the printer, and set proper tty modes */ if (open(printer, 1) != 1) dexit(); stty(1, ttymode); /* set hydra tabs */ write(1, stabs, sizeof stabs); /*** hydra ***/ /* Search lpd directory for work to do */ if (chdir(lpd) < 0) dexit(); seek(0, 0, 0); while (read(0, dbuf, 16) == 16) { if ((dbuf[0] | dbuf[1]) == 0 || dbuf[2] != 'd' || dbuf[3] != 'f') omputing Science Laboratory ==========\n\n\n"; char hd1[] = "\n\n\n=============================================== "; char hd2[] = " ===============================================\n\014"; header() { int tbuf[2]; time(tbuf); write(1, hd0, sizeof hd0); bprint(lbuf); write(1, hd1, sizeof hd1); write(1, ctime(tbuf), 24); write(1, hd2, sizeof hd2); } ; exit(1); } out(); } copy(f) int f; { int ff, i, nr, nc; static int buf[256]; card('F', cfname); card('U', cfname); ff = nfile(cfname); nc = 0; nr = 0; while((i = read(f, buf, 512)) > 0) { write(ff, buf, i); nc =+ i; if(nc >= 512) { nc =- 512; nr++; if(nr > maxrec) { printf("Copy file is too large\n"); break; } } } close(ff); nact++; } card(c, s) int c; char s[]; { char *p1, *p2; static char buf[512]; int col; p1 = buf; p2 = s; col = 0; *p1++ = c; whilSpooling Routines banner - print message in large letters bprint - subroutine to generate banner characters chset.h - definitions of banner character set (for bprint.c) lpd - 'line-printer' (Hydra) daemon opr - print spooler end address wh selch,bufe+2 wdr disc,cylsect cyl no. to disc wdr cntrl,cylsect sector no. to controller oc cntrl,c.read start controller oc selch,s.read start selch wselch ssr selch,work wait for selch busy==0 bc wselch oc selch,s.stop stop selch b bootaddr branch to loaded bootstrap * c.read db x'01' read s.stop db x'48' stop + extended address read s.read db x'30' read + go align adc bufs dc bootaddr bufe dc bootaddr+511 end har,ind(count) clear indirect blocks & filename sis count,4 bnm zeroout * lhi char,PROMPT ask user for filename bal ret1,putc lis count,0 nxtchr1 bal ret,getc read a character from console bz lookup returns 0 at end of line chi char,PAUSE flag to pause after loading? bne nopause no - continue li work,WAITPSW set wait bit st work,ps.start in start psw b nxtchr1 nopause equ * stb char,names(count) set in filename ais count,1 b nxtchr1 note no test for overflow * lookup equ * lis inode,1 recontinue; /* Process one command file */ spool(&dbuf[2]); unlink(&dbuf[2]); /* Reread directory in case it changed while we were spooling */ seek(0, 0, 0); } /* Feed paper partly out of printer */ write(1, "\033H44\n", 5); dexit(); } /* * Remove lock and terminate */ dexit() { unlink(lock); exit(0); } /* * Read and obey a file of spooling commands */ spool(dfname) char *dfname; { register in, len, c; if (fopen(dfname, cmdbuf) < 0) return; for(;;) { switch (c = getc(cmdbuf)/* * opr -- off line print via daemon */ char tfname[] "/usr/lpd/tfaXXXXX"; char cfname[] "/usr/lpd/cfaXXXXX"; char lfname[] "/usr/lpd/lfaXXXXX"; char dfname[] "/usr/lpd/dfaXXXXX"; int nact; int tff; int mailflg; char person[10]; int inchar; int maxrec 1000; main(argc, argv) int argc; char *argv[]; { register char *arg; int c, f, flag; int out(); pidfn(); if((signal(1, 1) & 01) == 0) signal(1, out); if((signal(2, 1) & 01) == 0) signal(2, out); if((signal(3, 1) & 01) == 0) signal(3, out); e((c = *p2++) != '\0') { *p1++ = c; col++; } *p1++ = '\n'; write(tff, buf, col+2); } ident() { int c, n; register char *b1p, *pp, *b2p; static char b1[100], b2[100]; b1p = b1; if(getpw(getuid()&0377, b1p)) { /*** b1p = "pdp::::m0000,m000:"; ***/ b1p = "***:::::"; } n = 0; b2p = b2; while(*b2p++ = "$ ident "[n++]); b2p--; n = 5; while(--n) while(*b1p++ != ':'); while((*b2p++ = *b1p++) != ':'); b2p[-1] = ','; b1p = b1; pp = person; while((c = *b1p++) != ':') { *b2p++ = c; *pp+cc -c bprint.c cc -o banner banner.c bprint.o cc -o lpd lpd.c bprint.o cc -o opr opr.c * * Unix bootstrap loader * * N.B. Must be assembled with SQUEZ to make it relocatable * bootaddr equ y'20000' must be >top of loaded program * i.addr equ x'78' 10 console input address i.cmd2 equ x'79' a3 console init cmd d.addr equ x'7a' c7 disc address * x'7b' unused c.addr equ x'7c' b6 disc controller s.addr equ x'7d' f0 selch address os.ext equ x'7e' 0000 OS file extension (for LSU) or console def'n * LARGE equ 19 large file bit in inode flags MAGIC equ x'107' a.out magic number EOL equ x'0d' carriagad inode for root directory bal ret,iget nxtdblk bal ret1,rblk read directory block bz start start over if end of directory la count,buf cmpnext lis offset,12 lh inode,0(count) directory entry used? bz nextent no - look at next nxtchr2 lh char,2(offset,count) compare names clh char,names(offset) bne nextent not equal - look at next entry sis offset,2 bnm nxtchr2 b gotinod right name - go read it in nextent ahi count,16 next directory entry la work,buf+512 cr count,work bl cmpnext b nxtdblk) { /* EOF or unknown command */ default: close(cmdbuf[0]); return; /* Unsupported commands */ case 'S': case 'M': getline(lbuf); continue; /* header page */ case 'L': lbuf[0] = lbuf[1] = ' '; getline(&lbuf[2]); header(); continue; /* Copy file in binary ('F' means prepend a form feed */ case 'F': case 'B': getline(lbuf); if ((in = open(lbuf, 0)) < 0) continue; while ((len = read(in, prbuf, 512)) > 0 && write(1, prbuf, len) == len) ; flag = 0; tff = nfile(tfname); while (argc>1 && (arg = argv[1])[0]=='-') { switch (arg[1]) { case 'c': flag = '+'; break; case 'r': flag = '-'; break; case 'm': mailflg = 1; break; } argc--; argv++; } ident(); if(argc == 1) copy(0); while(--argc) { arg = *++argv; if(flag == '+') goto cf; if(*arg == '/' && flag != '-') { card('F', arg); nact++; continue; } if(link(arg, lfname) < 0) goto cf; card('F', lfname); card('U', lfname); lfnam+ = c; } *b2p++ = 0; *pp++ = 0; /*** card('L', b2); ***/ card('L', person); if (mailflg) card('M', person); } pidfn() { register i, j, c; int p; p = getpid(); i = 0; while(tfname[i] != 'X') i++; i =+ 4; for(j=0; j<5; j++) { c = (p%10) + '0'; p =/ 10; tfname[i] = c; cfname[i] = c; lfname[i] = c; dfname[i] = c; i--; } inchar = i; } nfile(name) char *name; { register f; f = creat(name, 0666); if(f < 0) { printf("Cannot create %s\n", name); out(); } name[inchar]++; cp banner /usr/bin/banner cp opr /bin/opr cp lpd /etc/lpd rm banner opr lpd *.o e return PROMPT equ c'?' PAUSE equ c'-' flag to go into wait state after loading WAITPSW equ x'8000' wait-state psw * ret equ 15 ret1 equ 14 work equ 13 offset equ 12 count equ 11 bno equ 10 inode equ 09 char equ 08 cyl equ 07 sector equ 06 dev equ 05 disc equ 04 cntrl equ 03 selch equ 02 core equ 01 * low equ * loaded into low core by LSU org low+x'60' b start(0,0) org low+x'80' * start equ * li 1,bootaddr relocation address lis 2,0 start at low core rloop lm 8,0(2) move 8 words stm 8,0(1,2) ah * gotinod equ * bal ret,iget read inode for file lis core,0 nxtsblk st core,bufs read block into core ai core,511 st core,bufe bal ret1,rblk bz reloc ais core,1 b nxtsblk * reloc equ * l char,x'0' check first word clhi char,MAGIC a.out file? bne finish no - done lis count,0 yes - relocate to get rid of header mvsys l char,32(count) st char,0(count) ais count,4 cr count,core bl mvsys finish equ * lm 14,lowsave restore lowcore data stm 14,i.addr lpsw ps.start go to start address in loaded if (c == 'F') write(1, "\014", 1); close(in); continue; /* Delete file after copying */ case 'U': getline(lbuf); unlink(lbuf); continue; } } close(cmdbuf[0]); } /* * Read rest of line from command file */ getline(bufp) char *bufp; { register char *p; register c; for (p = bufp; (*p = c = getc(cmdbuf)) != '\n' && c > 0; p++) ; *p = '\0'; } /* * Print header page */ char hd0[] = "========== University of Wollongong ========================\ ==================== Ce[inchar]++; nact++; goto df; cf: f = open(arg, 0); if(f < 0) { printf("Cannot open %s\n", arg); continue; } copy(f); close(f); df: if(flag == '-') { f = unlink(arg); if(f < 0) printf("Cannot remove %s\n", arg); } } if(nact) { tfname[inchar]--; f = link(tfname, dfname); if(f < 0) { printf("Cannot rename %s\n", dfname); tfname[inchar]++; out(); } unlink(tfname); execl("/etc/lpd", "lpd", 0); dfname[inchar]++; printf("Cannot execute /etc/lpd\n")return(f); } out() { register i; signal(1, 1); signal(2, 1); signal(3, 1); i = inchar; while(tfname[i] != 'a') { tfname[i]--; unlink(tfname); } while(cfname[i] != 'a') { cfname[i]--; unlink(cfname); } while(lfname[i] != 'a') { lfname[i]--; unlink(lfname); } while(dfname[i] != 'a') { dfname[i]--; unlink(dfname); } exit(); } * * Bootstrap program to read block 0 from disc * bootaddr equ y'20000' core address for bootstrap * squez selch equ 1 cntrl equ 2 disc equ 3 cylsect equ 4 work equ 5 s.addr equ x'7d' selch address c.addr equ x'7c' controller address d.addr equ x'7a' disc address * start equ * lb selch,s.addr set device addresses lb cntrl,c.addr ... from low core locations lb disc,d.addr lis cylsect,0 cyl 0, sector 0 oc selch,s.stop stop selch wd selch,bufs+1 core start address wh selch,bufs+2 wd selch,bufe+1 core i 2,8*adc increment core address cli 2,high all moved? bl rloop no - continue b go-low(1) execute relocated code * go equ * lh work,os.ext OS file extension 0? bz lsu yes - assume loaded by LSU sth work,i.addr no - OS extension is really console def lsu equ * lm 14,i.addr save lowcore data stm 14,lowsave lb selch,s.addr lb cntrl,c.addr lb disc,d.addr la work,buf set up disc read buffer addresses st work,bufs ahi work,511 st work,bufe lis char,0 lhi count,names-ind+12 zeroout st c file * * Read inode and indirect blocks * iget equ * ahi inode,15 find block containing inode lr sector,inode srls sector,3 (inode+15)/8 bal ret1,rblka read block ni inode,7 find offset of inode in block slls inode,6 (inode+15) mod 8 stm 6,regsave save work regs lm 6,buf(inode) copy inode info from buffer stm 6,inod (up to addr[7]) lm 6,regsave restore work regs * la bno,addr small file: block addresses in addr li work,LARGE test for large file tbt work,inod bzr ret la core,ind large file - read indirect blocks nxtind bal ret1,rblk bz finind li count,508 move indirect block mvind l char,buf(count) st char,0(core,count) sis count,4 bnm mvind ahi core,512 b nxtind finind la bno,ind large file: block addresses in ind br ret * * Console read and write routines * getc equ * lb dev,i.addr console input address oc dev,i.cmd2 initialize oc dev,t.read start terminal read getwait ssr dev,work wait for busy == 0 bc getwait rdr dev,char read char from terminal buffer nhi char,x'7f' clearl cylinder address to disc oc disc,d.seek start seek wcntrl2 ssr cntrl,work sense controller status bfc c.idle,wcntrl2 wait for idle == 1 wdisc2 ssr disc,work sense disc status btc d.nrsrw,wdisc2 wait for no arm motion btc d.err,* oc selch,s.stop stop selch wd selch,bufs+1 start address to selch wh selch,bufs+2 wd selch,bufe+1 end address to selch wh selch,bufe+2 whr disc,cyl cylinder to disc (again) wdr cntrl,sector sector to controller oc cntrl,c.read start controller reading oc selch,s.read LOCATIONS * DEVICE X'78' X'7A' X'7C' * * MAG TAPE& DDA1 0000 0000 * CASSETTE * * * DISC YYZZ DDTT CCSS * * * WHERE: DD= THE DEVICE WITH THE MAGNETIC MEDIA * CC= THE CONTROLLER ADDRESS IF DD IS A DISC * TT= DISC TYPE INDICATOR * OO=2.5 MB DISC * 01=10 MB DISC * * SS= THE DISC SELCH ADDRESS * YY= THE DEVICE ADDRESS OF THE DISC BOOT * 19 SLHL R5,8 LB R6,PDB+20 OAR R5,R6 R5=THE STARTING ADDRESS LH R6,PDB+22 R6= THE CLHI RD,23 END OF TRACK? BNES CONT1 LHI RD,X'1F' SET HEAD1 SECTOR 0 CONT1 AIS RD,1 BUMP TO NEXT SECTOR BAL RE,READ1 GO READ THE LOADER * *CALCULATE CHKSUM * LDAR R7,R5 XAR RA,RA ZERO THE CHKSUM ACCUMULATOR CKLP LB RB,0(R7) SET UP THE CONTROLLER ST R5,SELCHAD START ADDRESS *** WD R1,SELCHAD+1 SET UP THE SELCH *** WH R1,SELCHAD+2 *** ST R6,SELCHAD END ADDRESS *** WD R1,SELCHAD+1 SET UP THE SELCH *** WH R1,SELCHAD+2 *** * WHR R1,R5 SET UP THE SELCH *** * int bmap; /* beginning sector of bit map */ } vol; int baddr 9600; /* block address on dev for boot program */ char buff[512]; extern errno; main(argc, argv) char **argv; { register dev, file, nblocks, len; register char *p; if (--argc && *(p = *++argv) == '-') { if ((baddr = atoi(++p)) <= 0) error("Illegal block number"); argc--; argv++; } if (argc < 2) error("Usage: mkboot [ - baddr ] file dev"); if ((file = open(*argv, 0)) < 0) error("Can't open %s", *argv); if ((dev = open(*++ j p v e k q w x y  start selch reading wselch2 ssr selch,work sense selch status btc s.busy,wselch2 wait for busy == 0 oc selch,s.stop stop selch wcntrl3 ssr cntrl,work check controller status bfc c.idle,wcntrl3 wait for idle == 0 btc c.err,* br ret1 (cond code must be nonzero) * s.busy equ 8 selector channel busy c.idle equ 2 disc controller idle c.err equ 5 disc controller error d.nrsrw equ 8 disc not-ready-to-seek-read-or-write d.err equ 7 disc error * align 8 ps.start dc 0,y'60' psw to start loaded program f24 dc LOADING DEVICE. * ZZ= THE READ COMMAND FOR THE BOOT LOAD DEVICE * * 99= READER PUNCH * 94= TTY * * * * low equ * dc y'8000',disbt start psw org low+x'60' 'OS' entry point lpsw low halt at entry org low+x'100' DISBT EQU * LB R1,X'7D' GET SELCH ADDRESS LIS R4,8 LOAD THE SELCH STOP COMMAND OCR R1,R4 STOP THE SELCH LB R2,X'7A' GET XAR RA,RB AIS R7,1 CLAR R7,R6 BLS CKLP BES CKLP LB R7,PDB+24 GET THE CHKSUM BYTE CLAR R7,RA BER R5 CHKSUM OK PASS CONTROL TO THE PROGRAM * LHI R1,X'EE00' LIS RA,1 DISPLAY LHI RB,X'40' OCR RA,RB THE CHKSUM WHR RA,R1 XAR RE,RE ERROR CODE WHR RA,RE LHI RB,X WHR R1,R6 SET UP THE SELCH *** OCR R3,RB START THE CONTROLLER OCR R1,RA START THE SELCH SSR R1,R0 WAIT FOR SELCH BTBS 8,1 NOT BUSY OCR R1,R4 STOP THE SELCH SSR R3,R0 WAIT FOR CONTROLLER BFBS 2,1 IDLE BR RE * FRSRWN EQU * SSR R3,R0 WAIT FOR CONTROLLER Bargv, 2)) < 0) error("Can't write on %s", *argv); /* * Make sure we aren't overwriting file system */ seek(dev, 1, 3); if (read(dev, buff, 512) != 512) error("Superblock read error"); if (baddr < buff[0].s_fsize) error("Are you trying to clobber the file system??"); /* * Skip a.out header */ seek(file, 32, 0); seek(dev, baddr, 3); /* * Copy file & count blocks copied */ nblocks = 0; while ((len = read(file, buff, 512)) > 0) { if (write(dev, buff, len) != len) error("Write parity bit clhi char,c'A' check for alpha bl notran clhi char,c'Z' bp notran ohi char,x'20' alpha - translate to lowercase notran bal ret1,putc echo character back clhi char,EOL end of line? bner ret no - return (cond. code nonzero) lr ret1,ret lis char,x'0a' echo extra linefeed * putc equ * lb dev,i.addr console output address ais dev,1 oc dev,t.write start terminal writing wdr dev,char write the character putwait ssr dev,work wait for busy == 0 bc putwait br ret1 * * Read a disc block * rh'24' sectors per track d.seek db x'c2' disarm+seek c.read db x'01' read s.stop db x'48' stop + extended address read s.read db x'70' extended address read + read + go t.write db x'a3' t.read db x'a1' align adc high equ * highest location for relocate * bufs equ * bufe equ bufs+4 lowsave equ bufe+4 regsave equ 8+lowsave buf equ 10*adc+regsave inod equ buf+512 mode equ inod addr equ 3*adc+inod ind equ 11*adc+inod names equ 8*512+ind end THE DEVICE ADDRESS LB R3,X'7C' GET THE CONTROLLER ADDRESS LHI R8,X'C1' LOAD THE RESTORE COMMAND OCR R2,R8 RESTORE THE FILE BAL RF,FRSRWN WAIT FOR COMPLETE LIS R7,0 SET THE CYLINDER ADDRESS LIS RD,0 SET THE SECTOR OR HEAD NUMBER AIS R8,1 MAKE THE RESTORE COMMAND A SEEK COMMAND BAL RE,READ READ THE DIRECTORY * '80' OCR RA,RB HERE B HERE * * READ LA R5,PDB SET UP THE SELCH *** LA R6,PDB+30 ADDRESSES *** READ1 WHR R2,R7 SET UP THE FILE OCR R2,R8 SEEK BAL RF,FRSRWN LIS RB,1 LOAD THE DISC READ COMMAND LHI RA,X'30' LOAD THE SELCH READ COMMAND WHR R2,R7 SET UP THE FILE WDR R3,RD FBS 2,1 IDLE SSR R2,R0 WAIT FOR FILE BTBS 15,1 STATUS = 0 BR RF * ALIGN 4 SELCHAD DC A(*-*) FOR SELCH ADDRESS *** PDB DS 32 DISBTE EQU * * END DISBT error %d", errno); nblocks++; } if (len < 0) error("Read error %d", errno); /* * Set up a pseudo OS/MT volume descriptor for the LSU */ vol.osaddr = baddr*2; vol.ossize = nblocks*2; seek(dev, 0, 0); if (write(dev, &vol, sizeof vol) != sizeof vol) error("Volume label write error %d\n", errno); } error(s, x) { printf(s, x); putchar('\n'); exit(1); } blk equ * l sector,0(bno) next block number bzr ret1 ais bno,4 rblka equ * dh sector,f24 get cylinder address slls sector,1 get sector address clhi sector,24 correct head? bl wselch1 yes - start read ais sector,8 else set head 0 wselch1 ssr selch,work wait for selch busy == 0 btc s.busy,wselch1 wcntrl1 ssr cntrl,work check controller status bfc c.idle,wcntrl1 wait for idle == 1 btc c.err,* wdisc1 ssr disc,work check disc status btc d.nrsrw,wdisc1 wait for no arm motion btc d.err,* whr disc,cy NORX3 TITLE REGISTER DEFINITIONS R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 RA EQU 10 RB EQU 11 RC EQU 12 RD EQU 13 RE EQU 14 RF EQU 15 TITLE MULTI MEDIA DIAGNOSTIC COMMON DISC BOOT LOADER * * * * BEFORE THIS BOOT LOADER IS EXECUTED THE DEVICE DEFINITION * TABLE MUST BE SET UP AS FOLLOWS. * * LIS R5,8 SET POINTER * * LH RE,X'7E' GET THE LOADER INDICATOR * BZS LD16 16 BIT BRANCH AIS R5,8 32 BIT-BUMP POINTER LD16 LH R7,PDB+4(R5) LOAD THE CYLINDER NUMBER LB R9,PDB+7(R5) GET THE HEAD NUMBER SLHL R9,5 LB RD,PDB+6(R5) GET THE SECTOR NUMBER OAR RD,R9 BAL RE,READ READ THE PROGRAM DEFINITION BLOCK * LB R5,PDB+ z { | # /* * mkboot [-addr] file dev * * Copy as a bootstrappable program onto device at * block address (default 9600). * Set up sector 0 of the device to look like an OS/MT volume * descriptor for the LSU. * */ #include "/usr/sys/filsys.h" struct { /* pseudo OS/MT volume descriptor */ char volname[4]; /* name of volume */ int atrb; /* attributes? */ int dirp; /* beginning sector of directory */ int osaddr; /* address of OS image # 0 */ int ossize; /* size of OS image */ * * Unix bootstrap loader -- 40-megabyte disc * * N.B. Must be assembled with SQUEZ to make it relocatable * bootaddr equ y'20000' must be >top of loaded program * i.addr equ x'78' 10 console input address i.cmd2 equ x'79' a3 console init cmd d.addr equ x'7a' c7 disc address * x'7b' unused c.addr equ x'7c' b6 disc controller s.addr equ x'7d' f0 selch address os.ext equ x'7e' 0000 OS file extension (for LSU) or console def'n * LARGE equ 19 large file bit in inode flags MAGIC equ x'107' a.out magic number EOL equ x'0d' carriage return PROMPT equ c'?' PAUSE equ c'-' flag to go into wait state after loading WAITPSW equ x'8000' wait-state psw * ret equ 15 ret1 equ 14 work equ 13 offset equ 12 count equ 11 bno equ 10 inode equ 09 char equ 08 cyl equ 07 head equ 06 dev equ 05 disc equ 04 cntrl equ 03 selch equ 02 core equ 01 * low equ * loaded into low core by LSU org low+x'60' b start(0,0) org low+x'80' * start equ * li 1,bootaddr relocation address lis 2,0 start at low core rloop lm 8,0(2) move 8 wordscmpnext b nxtdblk * gotinod equ * bal ret,iget read inode for file lis core,0 nxtsblk st core,bufs read block into core ai core,511 st core,bufe bal ret1,rblk bz reloc ais core,1 b nxtsblk * reloc equ * l char,x'0' check first word clhi char,MAGIC a.out file? bne finish no - done lis count,0 yes - relocate to get rid of header mvsys l char,32(count) st char,0(count) ais count,4 cr count,core bl mvsys finish equ * lm 14,lowsave restore lowcore data stm 14,i.addr lpsw ps.start go to start,x'7f' clear parity bit clhi char,c'A' check for alpha bl notran clhi char,c'Z' bp notran ohi char,x'20' alpha - translate to lowercase notran bal ret1,putc echo character back clhi char,EOL end of line? bner ret no - return (cond. code nonzero) lr ret1,ret lis char,x'0a' echo extra linefeed * putc equ * lb dev,i.addr console output address ais dev,1 oc dev,t.write start terminal writing wdr dev,char write the character putwait ssr dev,work wait for busy == 0 bc putwait br ret1 * * Read a di'20' d.setcyl db x'10' d.rstatn db x'08' d.rsthd db x'04' sector db 0 align adc high equ * highest location for relocate * bufs equ * bufe equ bufs+4 lowsave equ bufe+4 regsave equ 8+lowsave buf equ 10*adc+regsave inod equ buf+512 mode equ inod addr equ 3*adc+inod ind equ 11*adc+inod names equ 8*512+ind end * * Unix bootstrap loader * - load from 'tp' tape * * N.B. Must be assembled with SQUEZ to make it relocatable * * Format of 'tp' block tapea equ 44 size1 equ 38 dirsiz equ 64 MDIR equ 62 bootaddr equ y'20000' must be >top of loaded program * t.addr equ x'78' 85 tape address i.addr equ x'7e' 10 console input address i.cmd2 equ x'7f' a3 console init cmd * MAGIC equ x'107' a.out magic number EOL equ x'0d' carriage return PROMPT equ c'?' PAUSE equ c'-' flag to go into wait state after loading WAITPSW equ x'ilename? bne find.2 no - next char lhl count,tapea(dir) file address exbr count,count pdp11 swapped bytes pos cr bno,count right block? be pos.1 yes - got it bal ret1,skip skip forward block b pos pos.1 equ * lhl count,size1(dir) size of file exbr count,count pdp11 swapped bytes lis core,0 start reading into low core load bal ret1,rtape read next block shi count,512 decrement size bp load more - read next block reloc equ * l char,x'0' check first word clhi char,MAGIC a.out file? bne stm 8,0(1,2) ahi 2,8*adc increment core address cli 2,high all moved? bl rloop no - continue b go-low(1) execute relocated code * go equ * lh work,os.ext OS file extension 0? bz lsu yes - assume loaded by LSU sth work,i.addr no - OS extension is really console def lsu equ * lm 14,i.addr save lowcore data stm 14,lowsave lb selch,s.addr lb cntrl,c.addr lb disc,d.addr la work,buf set up disc read buffer addresses st work,bufs ahi work,511 st work,bufe lis char,0 lhi count,names-i address in loaded file * * Read inode and indirect blocks * iget equ * ahi inode,15 find block containing inode lr cyl,inode srls cyl,3 (inode+15)/8 bal ret1,rblka read block ni inode,7 find offset of inode in block slls inode,6 (inode+15) mod 8 stm 6,regsave save work regs lm 6,buf(inode) copy inode info from buffer stm 6,inod (up to addr[7]) lm 6,regsave restore work regs * la bno,addr small file: block addresses in addr li work,LARGE test for large file tbt work,inod bzr ret la core,insc block * rblk equ * l cyl,0(bno) next block number bzr ret1 ais bno,4 rblka equ * xar head,head slls cyl,1 sector on disc d head,f20 divide by sectors per track stb head,sector rem is sectorin track xar head,head quotient is track on disc d head,f20 divide by tracks per disc bal 0,cidle * whr disc,cyl oc disc,d.setcyl bal 0,cidle oc disc,d.rstatn bal 0,cidle oc disc,d.rsthd bal 0,cidle whr disc,head oc disc,d.sethd bal 0,cidle oc disc,d.seek * bal 0,cidle wdisc equ * ssr disc,work Bootstrap programs boot0 - standalone program to read block 0 from 10MB disc mdl - Interdata multimedia diagnostics loader mkboot - copies bootstrap program (e.g. uboot) to a disc and fakes an OS/MT volume descriptor so it can be loaded by the LSU uboot-40 - uboot for 40MB disc uboot - bootstrap program to load UNIX image from UNIX filesystem tpboot - bootstrap program to load UNIX image from 'tp' tape 8000' wait-state psw * ret equ 15 ret1 equ 14 work equ 13 tape equ 12 count equ 11 bno equ 10 dir equ 09 char equ 08 dev equ 05 core equ 01 * low equ * org low+x'60' b start(0,0) org low+x'80' * start equ * li 1,bootaddr relocation address lis 2,0 start at low core rloop lm 8,0(2) move 8 words stm 8,0(1,2) ahi 2,8*adc increment core address cli 2,high all moved? bl rloop no - continue b go-low(1) execute relocated code * go equ * lm 14,t.addr save lowcore data stm 14,lowsave lb tapefinish no - done lis count,0 yes - relocate to get rid of header mvsys l char,32(count) st char,0(count) ais count,4 cr count,core bl mvsys finish equ * lm 14,lowsave restore lowcore data stm 14,t.addr lh work,i.addr console addr & cmd 2 sth work,t.addr put where unix wants them lpsw ps.start go to start address in loaded file * * Console read and write routines * getc equ * lb dev,i.addr console input address oc dev,i.cmd2 initialize oc dev,i.read start terminal read getwait ssr dev,work waitnd+12 zeroout st char,ind(count) clear indirect blocks & filename sis count,4 bnm zeroout * lhi char,PROMPT ask user for filename bal ret1,putc lis count,0 nxtchr1 bal ret,getc read a character from console bz lookup returns 0 at end of line chi char,PAUSE flag to pause after loading? bne nopause no - continue li work,WAITPSW set wait bit st work,ps.start in start psw b nxtchr1 nopause equ * stb char,names(count) set in filename ais count,1 b nxtchr1 note no test for overflow * lookup equ d large file - read indirect blocks nxtind bal ret1,rblk bz finind li count,508 move indirect block mvind l char,buf(count) st char,0(core,count) sis count,4 bnm mvind ahi core,512 b nxtind finind la bno,ind large file: block addresses in ind br ret * * Console read and write routines * getc equ * lb dev,i.addr console input address oc dev,i.cmd2 initialize oc dev,t.read start terminal read getwait ssr dev,work wait for busy == 0 bc getwait rdr dev,char read char from terminal buffer nhi char btc d.nready,wdisc * oc selch,s.stop stop selch wd selch,bufs+1 start address to selch wh selch,bufs+2 wd selch,bufe+1 end address to selch wh selch,bufe+2 wd cntrl,sector sector to controller slls head,10 or cyl,head whr cntrl,cyl oc cntrl,c.read start controller reading oc selch,s.read start selch reading wselch2 ssr selch,work sense selch status btc s.busy,wselch2 wait for busy == 0 oc selch,s.stop stop selch bal 0,cidle br ret1 (cond code must be nonzero) * * wait for controller idle * cc -o mkboot -s mkboot.c as -o uboot uboot.s as -o tpboot tpboot.s as -u -o mdl mdl.s ,t.addr * restart equ * bal ret1,rewind rewind tape lhi char,PROMPT ask user for filename bal ret1,putc lis count,0 nxtchr1 bal ret,getc read a character from console bz nxtchr2 returns 0 at end of line chi char,PAUSE flag to pause after loading? bne nopause no - continue li work,WAITPSW set wait bit st work,ps.start in start psw b nxtchr1 nopause equ * stb char,names(count) store in filename ais count,1 b nxtchr1 note no test for overflow nxtchr2 lis char,0 delimit end of filename stb ch for busy == 0 bc getwait rdr dev,char read char from terminal buffer nhi char,x'7f' clear parity bit clhi char,c'A' check for alpha bl notran clhi char,c'Z' bp notran ohi char,x'20' alpha - translate to lowercase notran bal ret1,putc echo character back clhi char,EOL end of line? bner ret no - return (cond. code nonzero) lr ret1,ret lis char,x'0a' echo extra linefeed * putc equ * lb dev,i.addr console output address ais dev,1 oc dev,i.write start terminal writing wdr dev,char write the cha* lis inode,1 read inode for root directory bal ret,iget nxtdblk bal ret1,rblk read directory block bz start start over if end of directory la count,buf cmpnext lis offset,12 lh inode,0(count) directory entry used? bz nextent no - look at next nxtchr2 lh char,2(offset,count) compare names clh char,names(offset) bne nextent not equal - look at next entry sis offset,2 bnm nxtchr2 b gotinod right name - go read it in nextent ahi count,16 next directory entry la work,buf+512 cr count,work bl cidle equ * ssr cntrl,work bfc c.idle,cidle br 0 * s.busy equ 8 selector channel busy c.idle equ 2 disc controller idle c.err equ 5 disc controller error d.nready equ 8 disc not-ready-to-seek-read-or-write d.err equ 7 disc error * align 8 ps.start dc 0,y'60' psw to start loaded program f20 dc f'20' sectors per track d.seek db x'c2' disarm+seek c.read db x'01' read s.stop db x'48' stop + extended address read s.read db x'70' extended address read + read + go t.write db x'a3' t.read db x'a1' d.sethd db x: UNIX filesystem bootstrap program (10-MB disk) cp mkboot /etc rm mkboot strip uboot cp uboot /uboot rm uboot : disc version - loaded by LSU /etc/mkboot -9600 /uboot /dev/df0 : tape version - loaded by '50 sequence' dd if=/uboot of=/tuboot bs=160 skip=1 dd if=/tuboot of=/dev/rmt0 bs=1k : multimedia diagnostics loader - loaded by uboot strip mdl cp mdl /mdl rm mdl : 'tp' tape bootstrap: copied onto blk 0 of tape by 'tp' strip tpboot dd if=tpboot of=/tpboot bs=160 skip=1 rm tpboot ar,names(count) * lookup equ * bal ret1,skip skip boot block find equ * ci bno,MDIR all directory read? be restart yes - start again la core,dirbuf set to read into directory block bal ret1,rtape read next block la dir,dirbuf-dirsiz find.1 ai dir,dirsiz next dir entry la work,dirbuf+512 last entry? cr dir,work be find yes - read next dir block lis count,0 find.2 lb char,0(dir,count) next char clb char,names(count) match? bne find.1 no - next dir entry ais count,1 lr char,char end of fracter putwait ssr dev,work wait for busy == 0 bc putwait br ret1 * * Magtape I/O Routines * rewind equ * rewind tape bal ret,nmtn oc tape,t.clear clear controller oc tape,t.rew rewind lis bno,0 reset block address br ret1 skip equ * skip forward block bal ret,nmtn oc tape,t.read start reading skip.1 ssr tape,work tape status bfc T.EOM,skip.1 wait for EOM = 1 ais bno,1 increment block addr br ret1 rtape equ * read tape block into *(core) bal ret,nmtn lr ret,core save core address for r cct",1)) >0)){ [paper accounting file; create it by "date >/usr/jfo/tr.acct " or >wherever_you_want_it; read it with programs/tacct.c] ni.c:char nextf[NS] "/usr/lib/tmac.xxxxx"; [macro packages; e.g. tmac.s for -ms] ni.c:char termtab[NS] "/usr/lib/term/37"; ni.c:char suftab[] "/usr/lib/suftab"; t6.c:char fontfile[] "/usr/lib/font/XX"; In the programs directory, pti.s is a phototypesetter interpreter used to see in painfull detail what troff is telling the hardware to do: troff -t | pti is the usage. tcp neqn /usr/bin rm neqn *.[ch] , ct); ct = $1; } | pile MQ list MQ1 ={ lpile('-', $1, ct); ct = $1; } | box sub box sbox %prec SUB ={ if(dbg)printf(".\t sub box %d %d %d\n",$1,$3,$4); shift2($1, $3, $4); } | box sub box %prec SUB ={ bshiftb($1, $2, $3); } | box sup box %prec SUP ={ bshiftb($1, $2, $3); } | left eqn right ={ paren($1, $2, $3); } | pbox | box from box tbox %prec FROM ={ fromto($1,$3,$4); fromflg=0; } | box to box %prec TO ={ fromto($1, 0, $3); } | box diacrit ={ diacrit($1,$2); } | fwd box %prec UP ={ moThe grammar for neqn is in ne.g; don't change it until you're reasonably cocky. The grammars for eqn and neqn are designed to accept exactly the same language, and it is strongly recommended that you keep to this principle. Semantic actions for most kinds of things are in ne[1256].c; input processing is in ne3.c, general control in ne4.c (including the main routine), and lexical stuff in nelex.c. nelex.c includes y.tab.c (from yaccing ne.g), so if you change the grammar you have to recompile nelex.c. Make.nf .EQ x .EN .sp .EQ alpha ~ beta ~ sum ~ int ~ pi ~ partial .EN .sp .EQ x sub i .EN .sp .EQ x sub i sup k .EN .sp .EQ a over bc .EN .sp .EQ a over b+c .EN .sp .EQ x sup 2 over a sup 2 ~=~ y sup 2 over b sup 2 .EN .sp .EQ sum from i=0 to n x .EN .sp .EQ pile {a above b above c} .EN .sp .EQ left [ cpile {abcdef above b above cd} right ] .EN .sp .EQ sqrt x ~~~ sqrt {ax sup 2 + bx+c} .EN etry oc tape,t.read start reading rtape.1 ssr tape,work tape status btc T.BSY,rtape.1 wait for BSY = 0 btc T.EOM,rtape.2 EOM - end of block rdr tape,char read byte stb char,0(core) store in memory ais core,1 increment memory ptr b rtape.1 next char rtape.2 equ * end of block ais bno,1 increment block addr thi work,T.ERR error ? bzr ret1 no - return lr core,ret restore core addr bal ret,nmtn oc tape,t.bsp backspace tape sis bno,1 decrement block addr b rtape retry nmtn equ * wait k.c is a general purpose pipe interface to the TEK4014; it understands Model 37 Teletype half-line and reverse line motions (default nroff output) and also squeezes 66 lines into a 64 line baseline space. It waits for a newline from the keyboard between pages. Options are "-t" for not waiting between pages and "-pLs" for redefineing the page length to L inches if s=i or L lines if s is null. tcat.c (with tcat1.c) interprets troff output onto a TEK4014. It squeezes an 11inch page into the 4014's 10.7 inches\{# # int fromflg 0; \} %term CONTIG QTEXT SPACE THIN TAB %term MATRIX LCOL CCOL RCOL COL %term MARK LINEUP %term SUM INT PROD UNION INTER %term LPILE PILE CPILE RPILE ABOVE %term DEFINE TDEFINE NDEFINE DELIM GSIZE GFONT %right FROM TO %left OVER SQRT %right SUP SUB %right SIZE FONT ROMAN ITALIC BOLD FAT %right UP DOWN BACK FWD %left MQ MQ1 %left LEFT RIGHT %right DOT DOTDOT HAT TILDE BAR UNDER VEC DYAD %% stuff : eqn ={ putout($1); } | error ={ error(!FATAL, "syntax error in equation %d", first); } ve(0,$1,$2); } | up box %prec UP ={ move(1,$1,$2); } | back box %prec UP ={ move(2,$1,$2); } | down box %prec UP ={ move(3,$1,$2); } | matrix MQ collist MQ1 ={ matrix($1,$3); } ; fwd : FWD text ={ $$ = numb($1); } ; up : UP text ={ $$ = numb($1); } ; back : BACK text ={ $$ = numb($1); } ; down : DOWN text ={ $$ = numb($1); } ; diacrit : HAT ={ $$ = 'H'; } | VEC ={ $$ = 'V'; } | DYAD ={ $$ = 'Y'; } | BAR ={ $$ = 'B'; } | UNDER ={ $$ = 'N'; } /* under bar */ | DOT ={ $$ = 'D'; } | TILDE ={ $$ = ' a new neqn with yacc ne.g cc ne*.c -ly -lp Notice that this uses -lp, not -lS. The file test1 is a miniature test, small enough that you can understand what it does by eyeballing the output. When that works, use the file aip/browman for bigger and more serious testing. Both eqn and neqn have an undocumented option "-" which turns on a fair amount of debugging information related mainly to the heights of various objects. Regrettably, neqn is somewhat different from eqn internally, because it has not yeene.g~Q \{# # int fromflg 0; \} %term CONTIG QTEXT SPACE THIN TAB %term MATRIX LCOL CCOL RCOL COL %term MARK LINEUP %term SUM INT PROD UNION INTER %term LPILE PILE CPILE RPILE ABOVE %term DEFINE TDEFINE NDEFINE DELIM GSIZE GFONT %right FROM TO %left OVER SQRT %right SUP SUB %right SIZE FONT ROMAN ITALIC BOLD FAT %right UP DOWN BACK FWD %left MQ MQ1 %left LEFT RIGHT %right DOT DOTDOT HAT TILDE BAR UNDER VEC DYAD %% stuff : eqn ={ putout($1); } | error ={ error(!FATAL, "syntax erfor end of motion ssr tape,work tape status thi work,T.NMTN no motion? bz nmtn no - wait br ret T.ERR equ x'80' T.NMTN equ x'10' T.BSY equ x'08' T.EOM equ x'02' align 8 ps.start dc 0,y'60' psw to start loaded program i.write db x'a3' i.read db x'a1' t.clear db x'e0' t.rew db x'f8' t.read db x'e1' t.bsp db x'd1' align adc high equ * highest location for relocate * lowsave equ * dirbuf equ 8+lowsave names equ 512+dirbuf end by compression at the bottom. It also waits for a newline between pages. Typical use is troff -t files | tcat tcat options are "-t" as above "-sN" to skip the first N pages and "-pLs" to redefine the page length (if s=i inches, =c centimeters, =p points, =P picas, =null lines). Finally, the file usr-lib-tmac.s should be copied to /usr/lib/tmac.s, which makes it into the '-ms' macro package. | ={ eqnreg = 0; } ; eqn : box ={ if(dbg)printf(".\teqn: S%d\n",$1); } | eqn box ={ eqnbox($1,$2); } | eqn MARK ={ mark($1); } | MARK ={ mark(0); } | eqn LINEUP ={ lineup($1); } | LINEUP ={ lineup(0); } ; matrix : MATRIX ={ $$ = ct; } ; collist : column | collist column ; column : lcol MQ list MQ1 ={ column('L',$1,$3); } | ccol MQ list MQ1 ={ column('C',$1,$3); } | rcol MQ list MQ1 ={ column('R',$1,$3); } | col MQ list MQ1 ={ column('-',$1,$3); } ; lcol : LCOL ={ $$ = ct++; } ; ccol : CCOT'; } | DOTDOT ={ $$ = 'U'; } /* umlaut = double dot */ ; from : FROM ; to : TO ; left : LEFT text ={ $$ = $2->c1; } | LEFT MQ ={ $$ = '{'; } ; right : RIGHT text ={ $$ = $2->c1; } | RIGHT MQ1 ={ $$ = '}'; } | ={ $$ = 0; } ; list : eqn ={ lp[ct++] = $1; } | list ABOVE eqn ={ lp[ct++] = $3; } ; lpile : LPILE ={ $$=ct; } ; cpile : CPILE ={ $$=ct; } ; pile : PILE ={ $$=ct; } ; rpile : RPILE ={ $$=ct; } ; size : SIZE text ; font : ROMAN | ITALIC | BOLD | FONT text ; sub : SUB ={ shift(1t been converted to use the new standard io. ror in equation %d", first); } | ={ eqnreg = 0; } ; eqn : box ={ if(dbg)printf(".\teqn: S%d\n",$1); } | eqn box ={ eqnbox($1,$2); } | eqn MARK ={ mark($1); } | MARK ={ mark(0); } | eqn LINEUP ={ lineup($1); } | LINEUP ={ lineup(0); } ; matrix : MATRIX ={ $$ = ct; } ; collist : column | collist column ; column : lcol MQ list MQ1 ={ column('L',$1,$3); } | ccol MQ list MQ1 ={ column('C',$1,$3); } | rcol MQ list MQ1 ={ column('R',$1,$3); } | col MQ list MQ1 ={ column('-',$1,$3); } ; lcol : LSubdirectories: formatters source for nroff and troff terminals terminal driving tables for nroff fonts font width tables for troff programs useful ancillary programs tests test input for nroff and troff The run file in formatters creates nroff, troff, and the suffix table, which have to be copied to their final resting place, e.g /usr/bin for the first two, /usr/lib for the latter. The following indicates where builtin pathnames are located. n2.c: if((ptid != 1) && paper && ((i=open("/usr/jfo/tr.aar x src.a yacc ne.g cc -o neqn -n -s ne*.c -ly L ={ $$ = ct++; } ; rcol : RCOL ={ $$ = ct++; } ; col : COL ={ $$ = ct++; } ; sbox : sup box %prec SUP ={ $$ = $2; } ; tbox : to box %prec TO ={ $$ = $2; } | %prec FROM ={ $$ = 0; } ; box : box OVER box ={ boverb($1,$3); } | size box %prec SIZE ={ size($1, $2); } | font box %prec FONT ={ font($1, $2); } | FAT box ={ $$ = $2; } | SQRT box ={ sqrt($2); } | lpile MQ list MQ1 ={ lpile('L', $1, ct); ct = $1; } | cpile MQ list MQ1 ={ lpile('C', $1, ct); ct = $1; } | rpile MQ list MQ1 ={ lpile('R', $1); } ; sup : SUP ={ shift(-1); } ; pbox : MQ eqn MQ1 ={ $$ = $2; } | QTEXT ={ text('q',$1); } | CONTIG ={ text('c',$1); } | SPACE ={ text('~', $1); } | THIN ={ text('^', $1); } | TAB ={ text('\t', $1); } | SUM ={ funny('S'); } | PROD ={ funny('P'); } | INT ={ funny('I'); } | UNION ={ funny('U'); } | INTER ={ funny('A'); } /* intersection */ ; text : CONTIG | QTEXT | SPACE ={ $$ = & "\\|\\|"; } | THIN ={ $$ = & "\\|"; } ; %% In spite of what the other read_me file says, neqn does not use the portable io library. See make to recompile neqn. COL ={ $$ = ct++; } ; ccol : CCOL ={ $$ = ct++; } ; rcol : RCOL ={ $$ = ct++; } ; col : COL ={ $$ = ct++; } ; sbox : sup box %prec SUP ={ $$ = $2; } ; tbox : to box %prec TO ={ $$ = $2; } | %prec FROM ={ $$ = 0; } ; box : box OVER box ={ boverb($1,$3); } | size box %prec SIZE ={ size($1, $2); } | font box %prec FONT ={ font($1, $2); } | FAT box ={ $$ = $2; } | SQRT box ={ sqrt($2); } | lpile MQ list MQ1 ={ lpile('L', $1, ct); ct = $1; } | cpile MQ list MQ1 ={ lpile('C', $1, ct); ct = $1; } | rpile MQ list MQ1 ={ lpile('R', $1, ct); ct = $1; } | pile MQ list MQ1 ={ lpile('-', $1, ct); ct = $1; } | box sub box sbox %prec SUB ={ if(dbg)printf(".\t sub box %d %d %d\n",$1,$3,$4); shift2($1, $3, $4); } | box sub box %prec SUB ={ bshiftb($1, $2, $3); } | box sup box %prec SUP ={ bshiftb($1, $2, $3); } | left eqn right ={ paren($1, $2, $3); } | pbox | box from box tbox %prec FROM ={ fromto($1,$3,$4); fromflg=0; } | box to box %prec TO ={ fromto($1, 0, $3); } | box diacrit ={ diacrit($1,ine FATAL 1 #ifdef gcos #define fout cout #define fin cin #define close cclose #define exit cexit #define signal wdleng #define flush wdleng #define dup(n) n #define alloc(n) calloc(n, 1) #define free(p) cfree(p, 0, 0) #define open(f,m) copen(f, m==1 ? 'w' : 'r') #endif #define VERT(n) (20*n) extern int dbg; extern int ct; extern int lp[40]; extern int used[100]; /* available registers */ extern int ps; /* dflt init pt size */ extern int ft; /* dflt font */ extern int first; extern int fout, fin; extern iint lastchar; /* last character read by lex */ hne1.c~W# include "ne.h" boverb(p1, p2) int p1, p2; { int h, b, treg; treg = oalloc(); yyval = p1; h = eht[p1] + eht[p2]; b = eht[p2] - VERT(1); if(dbg)printf(".\tb:bob: S%d <- S%d over S%d; b=%d, h=%d\n", yyval, p1, p2, b, h); nrwid(p1, ps, p1); nrwid(p2, ps, p2); printf(".nr %d \\n(%d\n", treg, p1); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2); printf(".ds %d \\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d\\\n", 1; { int i, n, c; for(i=n=0; (c=p1[i++])!='\0'; ) if( c>='0' && c<='9' ) n = n*10 + c-'0'; if(dbg)printf(".\tnumb: %s %d\n", p1, n); return( n ); } font(p1, p2) { yyval = p2; } shift(p1) int p1; { yyval = p1; if(dbg)printf(".\tshift: %d;ps=%d\n", yyval, ps); } sqrt(p2) int p2; { yyval = p2; nrwid(p2, ps, p2); printf(".ds %d \\v'%du'\\e\\L'%du'\\l'\\n(%du'", p2, ebase[p2], -eht[p2], p2); printf("\\v'%du'\\h'-\\n(%du'\\*(%d\n", eht[p2]-ebase[p2], p2, p2); eht[p2] =+ VERT(1); if(dbg)prinal]-ebase[yyval]+gap, type!='R' ? 1 : 0, yyval); for( i=p1; i h2 ) /* move little sub down */ subsh = b1-b2; supsh = - VERT(se[p3]), yyval, p3, p3, yyval, p3, (h1-b1+ebase[p3])); } printf("\n"); ebase[yyval] = b + b1; if(dbg)printf(".\tfrom to: S%d <- %d f %d t %d; h=%d b=%d\n", yyval, p1, p2, p3, eht[yyval], ebase[yyval]); ofree(p1); if( p2>0 ) ofree(p2); if( p3>0 ) ofree(p3); } paren(leftc, p1, rightc) int p1, leftc, rightc; { int n, m, h1, j, b1, v; h1 = eht[p1]; b1 = ebase[p1]; yyval = p1; n = max(b1+VERT(1), h1-b1-VERT(1)) / VERT(1); if( n<2 ) n=2; m = n-2; if (leftc=='{' || rightc == '}'){ n = n%2 ? n :$2); } | fwd box %prec UP ={ move(0,$1,$2); } | up box %prec UP ={ move(1,$1,$2); } | back box %prec UP ={ move(2,$1,$2); } | down box %prec UP ={ move(3,$1,$2); } | matrix MQ collist MQ1 ={ matrix($1,$3); } ; fwd : FWD text ={ $$ = numb($1); } ; up : UP text ={ $$ = numb($1); } ; back : BACK text ={ $$ = numb($1); } ; down : DOWN text ={ $$ = numb($1); } ; diacrit : HAT ={ $$ = 'H'; } | VEC ={ $$ = 'V'; } | DYAD ={ $$ = 'Y'; } | BAR ={ $$ = 'B'; } | UNDER ={ $$ = 'N'; } /* under bar */ | DOT =   yyval, eht[p2]-ebase[p2]-VERT(1), treg, p2, p2); printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\*(%d\\\n", p2, p1, -eht[p2]+ebase[p2]-ebase[p1], p1); printf("\\h'-\\n(%du-\\n(%du-2u/2u'\\v'%du'\\l'\\n(%du'\\v'%du'\n", treg, p1, ebase[p1], treg, VERT(1)); ebase[yyval] = b; eht[yyval] = h; ofree(p2); ofree(treg); } bshiftb(p1, dir, p2) int p1, dir, p2; { int shval, sh1, sh2, effps, effps2, d1, h1, b1, h2, b2, h; int diffps; yyval = p1; h1 = eht[p1]; b1 = ebase[p1]; h2 = eht[p2]; b2 = ebase[p2];tf(".\tsqrt: S%d <- S%d;b=%d, h=%d\n", p2, p2, ebase[p2], eht[p2]); } lpile(type, p1, p2) int type, p1, p2; { int bi, hi, i, gap, h, b, j, nlist, nlist2, mid; yyval = oalloc(); gap = VERT(1); if( type=='-' ) gap = 0; nlist = p2 - p1; nlist2 = (nlist+1)/2; mid = p1 + nlist2 -1; h = 0; for( i=p1; imid; i-- ) b =+ eht[lp[i]] + gap; ebase[yyval] = (nlist%2) ? b + ebase[lp[mid]] : b - VERT(1) - gap; if(dbg)1) - b3; d2 = VERT(1); if( VERT(1)+h3 < h1-b1 ) supsh = -(h1-b1) + (h3-b3) - d2; eht[yyval] = h1 + max(0, h3-VERT(1)) + max(0, h2-b1-d1); ebase[yyval] = b1+max(0, h2-b1-d1); nrwid(p2, effps, p2); nrwid(p3, effps, p3); printf(".nr %d \\n(%d\n", treg, p3); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2); printf(".as %d \\v'%du'\\*(%d\\h'-\\n(%du'\\v'%du'\\\n", p1, subsh, p2, p2, -subsh+supsh); printf("\\*(%d\\h'-\\n(%du+\\n(%du'\\v'%du'\n", p3, p3, treg, -supsh); ps =+ 2; o ++n; if( n<3 ) n=3; m = n - 3; } eht[yyval] = VERT(2 * n); ebase[yyval] = (n)/2 * VERT(2); if (n%2 == 0) ebase[yyval] =- VERT(1); v = b1 - h1/2 + VERT(1); printf(".ds %d \\v'%du'", yyval, v); switch( leftc ) { case 'n': /* nothing */ case '\0': break; case 'f': /* floor */ brack(m, "\\(bv", "\\(bv", "\\(lf"); break; case 'c': /* ceiling */ brack(m, "\\(lc", "\\(bv", "\\(bv"); break; case '{': printf("\\b'\\(lt"); for(j = 0; j < m; j =+ 2) printf("\\(bv"); prin{ $$ = 'D'; } | TILDE ={ $$ = 'T'; } | DOTDOT ={ $$ = 'U'; } /* umlaut = double dot */ ; from : FROM ; to : TO ; left : LEFT text ={ $$ = $2->c1; } | LEFT MQ ={ $$ = '{'; } ; right : RIGHT text ={ $$ = $2->c1; } | RIGHT MQ1 ={ $$ = '}'; } | ={ $$ = 0; } ; list : eqn ={ lp[ct++] = $1; } | list ABOVE eqn ={ lp[ct++] = $3; } ; lpile : LPILE ={ $$=ct; } ; cpile : CPILE ={ $$=ct; } ; pile : PILE ={ $$=ct; } ; rpile : RPILE ={ $$=ct; } ; size : SIZE text ; font : ROMAN | ITALIC | BOLD | FOnt ifile; extern int linect; /* line number in file */ extern int eqline; /* line where eqn started */ extern int svargc; extern char **svargv; extern int eht[100]; extern int ebase[100]; struct { char c1; char c2; }; extern int yyval; extern int *yypv; extern int yylval; extern int tht[30]; extern int tbase[30]; extern int ptr; extern struct { char *nptr; char *sptr; } deftab[100]; extern int eqnreg, eqnht; extern int lefteq, righteq; extern int lastchar; /* last character read by lex */ ne0.c if( dir > 0 ) { /* subscript */ d1 = VERT(1); shval = - d1 + h2 - b2; if( d1+b1 > h2 ) /* move little sub down */ shval = b1-b2; ebase[yyval] = b1 + max(0, h2-b1-d1); eht[yyval] = h1 + max(0, h2-b1-d1); } else { /* superscript */ d1 = VERT(1); ebase[yyval] = b1; shval = -VERT(1) - b2; if( VERT(1) + h2 < h1-b1 ) /* raise little super */ shval = -(h1-b1) + h2-b2 - d1; eht[yyval] = h1 + max(0, h2 - VERT(1)); } if(dbg)printf(".\tb:b shift b: S%d <- S%d vert %d S%d vert %d; b=%d, h { printf(".\tS%d <- %c pile of:", yyval, type); for( i=p1; i\\n(%d .nr %d \\n(%d\n", lp[i], yyval, yyval, lp[i]); } printf(".ds %d \\v'%du'\\h'%du*\\n(%du'\\\n", yyval, ebase[yyval], type=='R' ? 1 : 0, yyval); for(i = p2-1; i >=p1; i--) { hi = eht[lp[i]];free(p2); ofree(p3); ofree(treg); } ne2.c~Y # include "ne.h" fromto(p1, p2, p3) int p1, p2, p3; { int h, b, h1, b1, pss; yyval = oalloc(); h1 = eht[yyval] = eht[p1]; b1 = ebase[p1]; b = 0; nrwid(p1, ps, p1); printf(".nr %d \\n(%d\n", yyval, p1); if( p2>0 ) { nrwid(p2, pss, p2); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, yyval, yyval, p2); eht[yyval] =+ eht[p2]; b = eht[p2]; } if( p3>0 ) { nrwid(p3, pss, p3); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p3, yyvatf("\\(lk"); for(j = 0; j < m; j =+ 2) printf("\\(bv"); printf("\\(lb'"); break; case '(': brack(m, "\\(lt", "\\(bv", "\\(lb"); break; case '[': brack(m, "\\(lc", "\\(bv", "\\(lf"); break; default: brack(m, &leftc, &leftc, &leftc); break; } printf("\\v'%du'\\*(%d", -v, p1); if( rightc ) { printf("\\v'%du'", v); switch( rightc ) { case 'f': /* floor */ brack(m, "\\(bv", "\\(bv", "\\(rf"); break; case 'c': /* ceiling */ brack(m, "\\(rc", "\\(bv", "\\(NT text ; sub : SUB ={ shift(1); } ; sup : SUP ={ shift(-1); } ; pbox : MQ eqn MQ1 ={ $$ = $2; } | QTEXT ={ text('q',$1); } | CONTIG ={ text('c',$1); } | SPACE ={ text('~', $1); } | THIN ={ text('^', $1); } | TAB ={ text('\t', $1); } | SUM ={ funny('S'); } | PROD ={ funny('P'); } | INT ={ funny('I'); } | UNION ={ funny('U'); } | INTER ={ funny('A'); } /* intersection */ ; text : CONTIG | QTEXT | SPACE ={ $$ = & "\\|\\|"; } | THIN ={ $$ = & "\\|"; } ; %% tne.h~S#def~U#int dbg; int lp[40]; /* stack for things like piles and matrices */ int ct; /* pointer to lp */ int used[100]; /* available registers */ int ps; /* dflt init pt size */ int ft; /* dflt font */ int first; extern int fout, fin; int ifile; int linect; /* line number in file */ int eqline; /* line where eqn started */ int svargc; char **svargv; int eht[100]; int ebase[100]; int tht[30]; int tbase[30]; int ptr; struct { char *nptr; char *sptr; } deftab[100]; int eqnreg, eqnht; int lefteq, righteq; =%d\n", yyval, p1, shval, p2, -shval, ebase[yyval], eht[yyval]); printf(".as %d \\v'%du'\\*(%d\\v'%du'\n", yyval, shval, p2, -shval); ofree(p2); } eqnbox(p1, p2) int p1, p2; { int b, h; yyval = p1; b = max(ebase[p1], ebase[p2]); eht[yyval] = h = b + max(eht[p1]-ebase[p1], eht[p2]-ebase[p2]); ebase[yyval] = b; if(dbg)printf(".\te:eb: S%d <- S%d S%d; b=%d, h=%d\n", yyval, p1, p2, b, h); printf(".as %d \"\\*(%d\n", yyval, p2); ofree(p2); } size(p1, p2) { yyval = p2; } numb(p1) char *p bi = ebase[lp[i]]; switch(type) { case 'L': printf("\\v'%du'\\*(%d\\h'-\\n(%du'\\v'0-%du'\\\n", -bi, lp[i], lp[i], hi-bi+gap); continue; case 'R': printf("\\v'%du'\\h'-\\n(%du'\\*(%d\\v'0-%du'\\\n", -bi, lp[i], lp[i], hi-bi+gap); continue; case 'C': case '-': printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d", -bi, yyval, lp[i], lp[i]); printf("\\h'-\\n(%du-\\n(%du/2u'\\v'0-%du'\\\n", yyval, lp[i], hi-bi+gap); continue; } } printf("\\v'%du'\\h'%du*\\n(%du'\n", eht[yyvl, yyval, p3); eht[yyval] =+ eht[p3]; } printf(".ds %d ", yyval); /* bottom of middle box */ if( p2>0 ) { printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d", eht[p2]-ebase[p2]+b1, yyval, p2, p2); printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\\n", yyval, p2, -(eht[p2]-ebase[p2]+b1)); } printf("\\h'\\n(%du-\\n(%du/2u'\\*(%d\\h'\\n(%du-\\n(%du+2u/2u'\\\n", yyval, p1, p1, yyval, p1); if( p3>0 ) { printf("\\v'%du'\\h'-\\n(%du-\\n(%du/2u'\\*(%d\\h'\\n(%du-\\n(%du/2u'\\v'%du'\\\n", -(h1-b1+ebabv"); break; case '}': printf("\\b'\\(rt"); for(j = 0; j< m; j =+ 2)printf("\\(bv"); printf("\\(rk"); for(j = 0; j< m; j =+ 2) printf("\\(bv"); printf("\\(rb'"); break; case ']': brack(m, "\\(rc", "\\(bv", "\\(rf"); break; case ')': brack(m, "\\(rt", "\\(bv", "\\(rb"); break; default: brack(m, &rightc, &rightc, &rightc); break; } printf("\\v'%du'", -v); } printf("\n"); if(dbg)printf(".\tcurly: h=%d b=%d n=%d v=%d l=%c, r=%c\n", eht[yyval], ebase[yyval], n, v, leftc, rightc); } brack(m, t, c, b) int m; char *t, *c, *b; { int j; printf("\\b'%s", t); for( j=0; j=", "\\(>=", "<=", "\\(<=", "==", "\\(==", "!=", "\\(!=", "+-", "\\(+-", "->", "\\(->", "<-", "\\(<-", "inf", "\\(if", "infinity", "\\(if", "partial", "\\(pd", "half", "\\fR\\(12\\fP", "prime", "\\(fm", "approx", "~\b\\d~\\u", "nothing", "", "cdot", "\\v'-.5'.\\v'.5'", "times", "\\|\\(mu\\|", "del", "\\(gr", "grad", "\\(g j = restab[i].resval; else { for( csp=psp=0; (c=p1[psp++])!='\0'; ){ trans(c,p1); if( csp>CSSIZE ){ p1[25] = '\0'; error(FATAL,"converted token %s... too long",p1); } } cs[csp] = '\0'; j = cs; } if(dbg)printf(".\t%ctext: S%d <- %s; b=%d,h=%d\n", t, yyval, j, ebase[yyval], eht[yyval]); printf(".ds %d \"%s\n", yyval, j); } trans(c,p1) int c; char *p1; { switch( c){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ':); printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n"); init(); yyparse(); if( eqnreg>0 ){ printf("'nr %d \\w'\\*(%d'\n", eqnreg, eqnreg); printf(".if %d>\\n(.v .ne %du\n", eqnht, eqnht); printf(".rn %d 10\n", eqnreg); if(!noeqn)printf("\\*(10\n"); } printf(".ps \\n(99\n.ft \\n(98\n"); printf(".EN"); if( lastchar == '\0' ){ putchar('\n'); break; } if( putchar(lastchar) != '\n' ) while( putchar(getch()) != '\n' ); flush(); } else if( type == lefteq ) in= argv; while( svargc > 0 && svargv[1][0] == '-'){ switch( svargv[1][1] ){ case 'd': lefteq=svargv[1][2]; righteq=svargv[1][3]; break; case 's': gsize = numb(&svargv[1][2]); break; case 'f': gfont = svargv[1][2]; break; case 'e': noeqn++; break; default: dbg = 1; } svargc--; svargv++; } ptr = 0; fout = dup(1); ifile = 1; linect = 1; if( svargc <= 0 ) fin = dup(0); else if( (fin = open(svargv[1], 0)) < 0) error( FATAL,"can't open file %s", svargv[1]); } yyerror(){;} init(){ l = 0; for( i=p1; i': case '<': if( p1[psp]=='=' ){ /* look ahead for == <= >= */ name4(c,'='); psp++; } else { shim(); cs[csp++] = c; shim(); } break; case '-': if( p1[psp]=='>' ){ shim(); name4('-','>'); psp++; } else { shim(); name4('m','i'); shim(); } break; case '/': name4('s','l'); break; case '~': caline(); else printf("%s",in); } flush(); exit(0); } getline(s) char *s; { char c; while((*s++=c=getch())!='\n' && c!='\0' && c!=lefteq ); if( c==lefteq ) s--; *s++ = '\0'; return(c); } inline() { int i,j,ds,t; printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n"); ds = oalloc(); printf(".ds %d \"\n", ds); do{ printf(".as %d \"%s\n", ds, in); init(); yyparse(); if( eqnreg > 0 ) { printf(".as %d \\*(%d\n", ds, eqnreg); ofree(eqnreg); } printf(".ps \\n(99\n.ft \\n(98\n"); } while( (ct = 0; ps = gsize; ft = gfont; first++; } error(fatal, s1, s2) int fatal; char *s1, *s2; { int sfout; if( fatal>0 ) printf("fatal error: "); printf(s1,s2); printf(" file %s, between lines %d and %d\n", svargv[ifile], eqline, linect); flush(fout); sfout = fout; fout = 2; if( fatal>0 ) printf("fatal error: "); printf(s1,s2); printf(" file %s, between lines %d and %d\n", svargv[ifile], eqline, linect); flush(2); fout = sfout; if( fatal > 0 ) exit(1); } ne5.c~`G; val[i] = yyval; j =+ nrow + 2; } yyval = oalloc(); eht[yyval] = eht[val[0]]; ebase[yyval] = ebase[val[0]]; if(dbg)printf(".\tmatrix S%d: r=%d, c=%d, h=%d, b=%d\n", yyval,nrow,ncol,eht[yyval],ebase[yyval]); printf(".ds %d \"", yyval); for( i=0; i 0 ) printf("\\x'0-%du'", before); printf("\\f%c\\s%d\\*(%d\\s\\n(99\\f\\n(98",gfont,gsize,p1); after = ebase[p1] - VERT(1); if( after > 0 ) printf("\\x'%du'", after); putchar('\n'); eqnreg = p#include "ne.h" mark(n) int n; { if( n ) printf(".as %d \\k(97\n", n); else { yyval = oalloc(); printf(".ds %d \\k(97\n", yyval); nrwid(yyval, ps, yyval); eht[yyval] = eht[n]; ebase[yyval] = ebase[n]; } if(dbg)printf(".\tmark %d as %d\n", n, yyval); } lineup(n) int n; { if( n ) { nrwid(n, ps, n); printf(".ds %d \\h'|\\n(97u-\\n(%du'\\*(%d\n", n, n, n); } else { yyval = oalloc(); printf(".ds %d \\h'|\\n(97u'\n", yyval); nrwid(yyval, ps, yyval); eht[yyval] = eht[n]; ebase[yyvSUP, ".EN", 0, "from", FROM, "to", TO, "sum", SUM, "hat", HAT, "vec", VEC, "dyad", DYAD, "dot", DOT, "dotdot", DOTDOT, "bar", BAR, "tilde", TILDE, "under", UNDER, "prod", PROD, "int", INT, "integral", INT, "union", UNION, "inter", INTER, "pile", PILE, "lpile", LPILE, "cpile", CPILE, "rpile", RPILE, "over", OVER, "sqrt", SQRT, "above", ABOVE, "size", SIZE, "font", FONT, "fat", FAT, "roman", ROMAN, "italic", ITALIC, "bold", BOLD, "left", LEFT, "right", RIGHT, "delim", DELIM, ebase[yyval] =- a; else if( dir==3 ) ebase[yyval] =+ a; */ if(dbg)printf(".\tmove %d dir %d amt %d; h=%d b=%d\n", p, dir, amt, eht[yyval], ebase[yyval]); } funny(n) int n; { int f, t; yyval = oalloc(); switch(n) { case 'S': f = "\\(*S"; break; case 'U': f = "\\(cu"; break; case 'A': /* intersection */ f = "\\(ca"; break; case 'P': f = "\\(*P"; break; case 'I': f = "\\(is"; break; } printf(".ds %d %s\n", yyval, f); eht[yyval] = VERT(2); ebase[yyval] = 0; if(dbg)printf(".\tfosh", "\\fRcosh\\fP", "lim", "\\fRlim\\fP", "log", "\\fRlog\\fP", "max", "\\fRmax\\fP", "min", "\\fRmin\\fP", "ln", "\\fRln\\fP", "exp", "\\fRexp\\fP", "det", "\\fRdet\\fP", 0, 0 }; int csp; int psp; #define CSSIZE 400 char cs[420]; text(t,p1) int t; char *p1; { int i,j,c; yyval = oalloc(); ebase[yyval] = 0; eht[yyval] = VERT(2); if( t=='q' ) j = p1; else if ( t == '~' ) j = &"\\ "; else if ( t == '^' ) j = &""; else if ( t == '\t' ) j = &"\\t"; else if( (i=lookup(p1,restab))>=0 )csp++] = c1; cs[csp++] = c2; } ne4.cщl #include "ne.h" #define SIGPIPE 13 /* troff has stopped reading */ int gsize 10; int gfont 'R'; char in[600]; /* input buffer */ int exit(); int noeqn; main(argc,argv) int argc; char *argv[];{ int i, type; first = 0; lefteq = righteq = '\0'; signal(SIGPIPE, &exit); setfile(argc,argv); while( (type=getline(in)) != '\0' ){ eqline = linect; if( in[0]=='.' && in[1]=='E' && in[2]=='Q' ){ for( i=11; i<100; used[i++]=0 ); printf("%s",in1; if(dbg)printf(".\tanswer <- S%d: h=%d, b=%d, before=%d, after=%d\n", p1, eht[p1], ebase[p1], before, after); } max(i,j) int i,j; { return( i>j ? i : j ); } oalloc(){ int i; for( i=11; i<100; i++) if( used[i]++ == 0 ) return(i); error( FATAL, "no strings left", i); } ofree(n) int n; { used[n] = 0; } setps(p) int p; { printf(".ps %d\n", p); } nrwid(n1, p, n2) int n1, p, n2; { printf(".nr %d \\w'\\*(%d'\n", n1, n2); } setfile(argc, argv) int argc; char *argv[]; { svargc = --argc; svargv al] = ebase[n]; } if(dbg)printf(".\tlineup %d in %d\n", n, yyval); } nne6.c~b#include "ne.h" column(type, p1, p2) int type, p1, p2; { int i, n; lp[p1] = ct - p1 - 1; if( dbg ){ printf(".\t%c column of", type); for( i=p1+1; i= 0){ lastchar = (peek<0) ? *swt[sw]++ : peek; peek = -1; if(lastchar != '\0')return(lastchar); peek = speek[sw--]; return(' '); } lastchar = (peek<0) ? getchar() : peek; if( lastchar=='\n' ) linect++; peek = -1; if( lastchar!= '\0' ) return(lastchar); if( ++ifile > svargc ){ peek = '\0'; return('\0'); } close(fin); linect = 1; if( (fin=open(svargv[ifile],0)) >= 0 ) goto loop; error(FATAL,"can't open file %s\n", svargv[ifile]); } yylex(){ int c, type; beg: while( (c=getch())==' ' || c=='\n'); yylval=c; switch(c){ case '\0': return('\0'); case '~': return(SPACE)l; } tbl[]; { register i,j, r; for(i=0; tbl[i].name!=0; i++){ /* table of tbl wds */ for( j=0; (r=tbl[i].name[j])==str[j] && r!='\0'; j++); if( r == str[j] ) return(i); } return( -1 ); } cstr(s,quote) char *s; int quote; { int del,c,i; while((del=getch()) == ' ' || del == '\t' || del == '\n'); if(quote) for(i=0; (c=getch()) != del;) s[i++] = c; else { s[0] = del; for(i=1; (c=getch())!=' ' && c!= '\t' && c!='\n';) s[i++]=c; } s[i] = '\0'; return(s); } define(type) int type; { yacc ne.g cc -o neqn -n ne*.c -ly cp neqn /usr/bin/neqn ln /usr/bin/neqn /usr/bin/eqn eport.cp0/* * Approximate old portable C library using new Standard I/O Library * * (ad hoc version for tbl only) */ # include "stdio.h" # undef getchar int cin = stdin; int cout; cclose(fd) { fclose(fd); } cexit(n) { fclose(stdout); exit(n); } copen(fn, type) { char *mode; switch(type) { case 'r': mode = "r"; break; case 'w': mode = "w"; break; case 'a': mode = "a"; break; } return(fopen(fn, mode)); } gets(ss) char *ss; { register c; regisevenup[MAXCOL], evenflg; int F1 0; int F2 0; int allflg 0; int leftover 0; int textflg 0; int left1flg 0; int rightl 0; char *cstore, *cspace; char *last; struct colstr *table[MAXLIN]; int style[MAXHEAD][MAXCOL]; int ctop[MAXHEAD][MAXCOL]; char font[MAXHEAD][MAXCOL][2]; char csize[MAXHEAD][MAXCOL][4]; int lefline[MAXHEAD][MAXCOL]; char cll[MAXCOL][CLLEN]; int stynum[MAXLIN+1]; int nslin, nclin; int sep[MAXCOL]; int fullbot[MAXLIN]; int instead[MAXLIN]; int used[MAXCOL], lused[MAXCOL], rused[MAXCOL]; int lin                        & , 2 ! ' - 3 " ( . 4 # ) / 5 $ * 0 6 % + 1 7 8 > D J 9 ? E K : @ F L ; A G M < B; case '^': return(THIN); case '\t': return(TAB); case '{': return(MQ); case '}': return(MQ1); case '"': for(asp=0; (c=getch())!='"'; ){ if(c !='\\')token[asp++]=c; else { if((c=getch())!= '"')token[asp++]='\\'; token[asp++] = c; } if( asp>=SSIZE ) error(FATAL,"quoted string %.20s... too long", token); } token[asp]='\0'; yylval= &token[0]; return(QTEXT); } if( c==righteq ) return('\0'); getstr(token, c); if((type = lookup(token,deftab)) >= 0){ if(sw >= 9) /* char *alloc (); */ int i, c; while( (c=getch())==' ' || c=='\n' ); getstr(token,c); if( type == DEFINE ) { if((i = lookup(token,deftab)) >= 0){ yyval = i; free(deftab[yyval].sptr); } else { yyval = ptr++; for(i=0; token[i] != '\0'; i++); deftab[yyval].nptr = alloc(i+1); for(i=0; deftab[yyval].nptr[i]=token[i]; i++); } if(dbg)printf(".\tdefine %s\n",deftab[yyval].nptr); } cstr(token,1); if( type != DEFINE ) return; for(i=0; token[i] != '\0'; i++); deftab[yyval].sptr =port.c is a set of adaptor routines to make the new standard io library (libS) look enough like the old portable io library (libp) to make tbl work. See run to recompile tbl ter char *s; s = ss; while ((c = getc(cin)) >= 0) if (c == '\n') { *s = '\0'; return(ss); } else *s++ = c; return(0); } getchar() { return(getc(cin)); } gt..c~# define MAXLIN 200 # define MAXHEAD 30 # define MAXCOL 20 # define MAXCHS 2000 # define CLLEN 10 extern int nlin, ncol, iline, nclin, nslin; extern int style[MAXHEAD][MAXCOL]; extern int ctop[MAXHEAD][MAXCOL]; extern char font[MAXHEAD][MAXCOL][2]; extern char csize[MAXHEAD][MAXCOL][4]; extern char cll[MAXCOLestop[MAXLIN]; int nlin, ncol; int iline 1; char *ifile "Input"; int texname 'a'; char *exstore, *exlim; t1.c~P# # include "t..c" # define BROKPIPE 13 # ifdef unix # define MACROS "/usr/lib/tmac.s" # endif # ifdef gcos # define MACROS "cc/troff/smac" # endif # define ever (;;) main(argc,argv) char *argv[]; { #ifdef gcos if(!intss()) cout = copen("*qq", 'w'); /* default media code is type 5 */ #endif # ifdef unix int badsig(); signal(BROKPIPE, badsig); # endif cexit(tbl(argc,argv)tnam; lp++) *(lp->optadd) = 0; texname='a'; tab = '\t'; gets1(line); /* see if this is a command line */ if (index(line,';') < 0) { backrest(line); return; } for(cp=line; (c = *cp) != ';'; cp++) { if (!letter(c)) continue; for(lp= options; lp->optadd; lp++) { if (prefix(lp->optnam, cp)) { *(lp->optadd) = 1; while (letter(*cp)) cp++; if (lp->optadd == &tab) { while (*cp==' ')cp++; if (*cp == '('){ *(lp->optadd) = *++cp; cp++; } } break; } } if (error(FATAL,"definitions nested > 9", sw); swt[++sw] = deftab[type].sptr; speek[sw] = peek; peek = -1; goto beg; } type = lookup(token,keytab); if( type < 0 ) return(CONTIG); if( keytab[type].keyval==DEFINE || keytab[type].keyval==TDEFINE ) { define(keytab[type].keyval); goto beg; } else if( keytab[type].keyval==DELIM ) { delim(); goto beg; } else if( keytab[type].keyval==GSIZE ){ globsize(); goto beg; } else if( keytab[type].keyval==GFONT ) { globfont(); goto beg; } e alloc(i+1); for(i=0; deftab[yyval].sptr[i] = token[i]; i++); if(dbg)printf(".\tname %s defined as %s\n", deftab[yyval].sptr, deftab[yyval].sptr); } delim() { char *s; yyval = eqnreg = 0; cstr(token,0); lefteq = token[0]; righteq = token[1]; if( (lefteq == 'o' && righteq == 'f') || (lefteq == 'O' && righteq == 'F') ) lefteq = righteq = '\0'; } globsize() { extern int gsize; int c; while( (c=getch())==' ' || c=='\n' ); getstr(token,c); gsize = numb(token); yyval = eqnreg = 0; setps(gsizear x src.a cc -o tbl -n t?.c port.c -lS ][CLLEN]; extern int stynum[]; extern int F1, F2; extern int lefline[MAXHEAD][MAXCOL]; extern int fullbot[]; extern int instead[]; extern int expflg; extern int ctrflg; extern int evenflg; extern int evenup[]; extern int boxflg; extern int dboxflg; extern int tab; extern int allflg; extern int textflg; extern int left1flg; extern int rightl; struct colstr {char *col, *rcol;}; extern struct colstr *table[]; extern char *cspace, *cstore; extern char *exstore, *exlim; extern int sep[]; extern int used[], lused); } tbl(argc,argv) char *argv[]; { char line[512]; for ever { if (argc>1) { argc--; argv++; if (match("-ms", *argv)) *argv = MACROS; cin = copen(ifile= *argv, 'r'); iline=1; if (cin < 0) { printf(2, "can't open input file %s\n", ifile); return(1); } } while (gets1(line)) { puts(line); if (prefix(".TS", line)) tableput(); } cclose(cin); if (argc <= 1) break; } return(0); } # ifdef unix badsig() { signal(BROKPIPE, 1); cexit(0); } # endif t2.c~# include "t..letter(*cp)) error("Illegal option"); cp--; } cp++; backrest(cp); return; } backrest(cp) char *cp; { char *s; for(s=cp; *s; s++); un1getc('\n', cin); while (s>cp) un1getc(*--s, cin); return; } +t4.c~4# include "t..c" getspec() { int icol, i; for(icol=0; icol=SSIZE ) error(FATAL,"token %.20s... too long",s); c = getch(); } if( c=='{' || c=='}' || c=='"' || c=='~' || c=='^' || c=='\t' || c==righteq ) peek = c; s[asp]='\0'; yylval = s; } lookup(str,tbl) char *str; struct { char *name; char *va); } globfont() { extern int gfont; while( (gfont=getch())==' ' || gfont=='\n' ); yyval = eqnreg = 0; printf(".ft %c\n", gfont); } cp tbl /usr/bin rm tbl *.o rm t?.c port.c [], rused[]; extern int linestop[]; extern int leftover; extern char *last, *ifile; extern int cin, cout; extern int texname; # define CRIGHT 80 # define CLEFT 40 # define CMID 60 # define S1 31 # define S2 32 # define TMP 38 # define SF 35 # define SIND 37 /* this refers to the relative position of lines */ # define LEFT 1 # define RIGHT 2 # define THRU 3 # define TOP 1 # define BOT 2 t0.c~# # include "t..c" int expflg 0; int ctrflg 0; int boxflg 0; int dboxflg 0; int tab '\t'; int c" tableput() { savefill(); ifdivert(); getcomm(); getspec(); gettbl(); getstop(); checkuse(); choochar(); maktab(); runout(); release(); rstofill(); endoff(); } t3.c~# include "t..c" struct optstr {char *optnam; int *optadd;} options [] { "expand", &expflg, "center", &ctrflg, "box", &boxflg, "allbox", &allflg, "doublebox", &dboxflg, "frame", &boxflg, "doubleframe", &dboxflg, "tab", &tab, 0,0}; getcomm() { char line[200], *cp; struct optstr *lp; int c; for(lp= options; lp->op left1flg=rightl=0; readspec(); } readspec() { int icol, c, sawchar, stopc, i; char sn[10], *snp, *temp; sawchar=icol=0; while (c=get1char()) { switch(c) { default: if (c != tab) error("bad table specification character"); case ' ': /* note this is also case tab */ continue; case '\n': if(sawchar==0) continue; case ',': case '.': /* end of table specification */ ncol = max(ncol, icol); if (lefline[nclin][ncol]>0) {ncol++; rightl++;}; if(sawchar) nclin++; if (nclin>=MAXHEAD) error("too many lines in specification"); icol=0; if (ncol==0 || nclin==0) error("no specification"); if (c== '.') { while ((c=get1char()) && c != '\n'); /* fix up sep - default is 3 except at edge */ for(icol=0; icoltemp) break; else *snp++=c; else if (digit(c)) *snp++ = c; else break; if (snp-temp>4) error("point size too large"); } *snp=0; un1getc(c,cin); continue; case 'w': case 'W': snp = cll [icol-1]; if (*snp) { printf (2, "Ignored second width specification"); continue; } stopc=0; while (c = get1char()) { if (se '_': fullbot[nlin]= '-'; continue; case '=': fullbot[nlin]= '='; continue; } stynum[nlin] = nslin; nslin = min(nslin+1, nclin-1); for (icol = 0; icol =0; ik--) printf("-\\n(%d",CRIGHT+icol-ik); printf("\n"); printf(".if \\n(%d>0 .nr %d \\n(%d/%d\n", TMP, TMP, TMP, k); printf(".if \\n(%d<0 .nr %d 0\n", TMP, TMP); for(ik=1; ik<=k; ik++) { if (doubled[icol-k+ik]) printf(",icol+CRIGHT, icol+CLEFT); if (doubled[icol]) { printf(".nr %d +\\n(%d\n", icol+CMID, icol+CLEFT); /* printf(".if n .if \\n(%d%%24>0 .nr %d +12u\n",icol+CMID, icol+CMID); */ } tsep=sep[icol]; } if (rightl) printf(".nr %d (\\n(%d+\\n(%d)/2\n",ncol+CRIGHT-1, ncol+CLEFT-1, ncol+CRIGHT-2); printf(".nr TW \\n(%d\n", ncol+CRIGHT-1); if (boxflg || allflg || dboxflg) printf(".nr TW +%d*\\n(%d\n", sep[ncol-1], TMP); printf(".if t .if (\\n(TW+\\n(.o)>7.75i .tm Table at line %d file %s is too wide - \\n(T'-': case '^': case 'c': case 's': case 'n': case 'r': case 'l': case 'a': style[nclin][icol]=c; if (c== 's' && icol<=0) error("first column can not be S-type"); if (c=='s' && style[nclin][icol-1] == 'a') { printf(".tm warning: can't span a-type cols, changed to l\n"); style[nclin][icol-1] = 'l'; } if (c=='s' && style[nclin][icol-1] == 'n') { printf(".tm warning: can't span n-type cols, changed to c\n"); style[nclin][icol-1] = 'c'; } icol++; if (c==np==cll[icol-1] && c=='(') { stopc = ')'; continue; } if ( !stopc && (c>'9' || c< '0')) break; if (stopc && c== stopc) break; *snp++ =c; } *snp=0; if (snp-cll[icol-1]>CLLEN) error ("column width too long"); if (!stopc) un1getc(c); continue; case 'e': case 'E': if (icol<1) continue; evenup[icol-1]=1; evenflg=1; continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': sn switch(ctype(nlin,icol)) /* numerical or alpha, subcol */ { case 'n': table[nlin][icol].rcol = maknew(table[nlin][icol].col); break; case 'a': table[nlin][icol].rcol = table[nlin][icol].col; table[nlin][icol].col = ""; break; } } while (ctype(nlin,icol+1)== 's') /* spanning */ table[nlin][++icol].col = ""; if (ch == '\0') break; } while (++icol \\n(%d .nr %d \\n(%d\n", icol+CRIGHT, TMP, TMP, icol+CRIGHT); } for(icol=0; icol0) putfont(fn); if (*size) putsize(size); printf("%s", s); if (*fn>0) putfont("P"); if (*size) putsize("0"); printf("%c",F1); } else printf("\\n(%c-", s); } Tt7.c~ X# include "t..c" # define realsplit ((ct=='a'||ct=='n') && table[i][c].rcol) runout() { int i, c; if (boxflg || allflg || dboxflg) need(); if (ctrflg) { printf(".nr #I \\n(.i\n"); printf('^' && nclin<=0) error("first row can not contain vertical span"); if (icol>=MAXCOL) error("too many columns in table"); sawchar=1; continue; case 'b': case 'i': c =+ 'A'-'a'; case 'B': case 'I': if (icol==0) continue; snp=font[nclin][icol-1]; snp[0]= (c=='I' ? '2' : '3'); snp[1]=0; continue; case 't': case 'T': if (icol>0) ctop[nclin][icol-1] = 1; continue; case 'f': case 'F': if (icol==0) continue; snp=font[nclin][icol-1]; snp[0]=snp[1]=stopc=0[0] = c; snp=sn+1; while (digit(*snp++ = c = get1char())) ; un1getc(c,cin); sep[icol-1] = max(sep[icol-1], numb(sn)); continue; case '|': lefline[nclin][icol]++; if (icol==0) left1flg=1; continue; } } error("EOF reading table specification"); } t5.c~ # include "t..c" gettbl() { int icol, ch; cstore=cspace= chspace(); textflg=0; for (nlin=nslin=0; gets1(cstore); nlin++) { stynum[nlin]=nslin; if (prefix(".TE", cstore)) { leftover=0; break; } i++; if (cstore-cspace > MAXCHS) cstore = cspace = chspace(); } last = cstore; permute(); if (textflg) untext(); return; } nodata(il) { int c; for (c=0; c= '0' && c<= '9') break; } if (stopc) if (get1char()!=stopc) error("Nonterminated font name"); continue; case 'P': case 'p': if (icol<=0) continue; temp = snp = csize[nclin][icol-1]; whilef (prefix(".TC", cstore) || prefix(".T&", cstore)) { readspec(); nslin++; } if (nlin>=MAXLIN) { leftover=1; break; } fullbot[nlin]=0; if (cstore[0] == '.' && letter(cstore[1])) { instead[nlin] = cstore; while (*cstore++); continue; } else instead[nlin] = 0; while (nodata(nlin)) { if (ch = oneh(nlin)) fullbot[nlin]= ch; nlin++; nslin++; instead[nlin]=fullbot[nlin]=0; } table[nlin] = alocv(ncol*sizeof(table[0][0])); if (cstore[1]==0) switch(cstore[0]) { cascol=\\n(%d .nr %d \\n(%du+2n\n",S2,icol+CRIGHT,icol+CRIGHT,S2); if (doubled[icol]) { printf(".nr %d \\n(%d\n", icol+CMID, S1); printf(".nr %d \\n(%d+\\n(%d\n",TMP,icol+CMID,S2); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n",TMP,icol+CRIGHT,icol+CRIGHT,TMP); printf(".if \\n(%d<\\n(%d .nr %d +(\\n(%d-\\n(%d)/2\n",TMP,icol+CRIGHT,icol+CMID,icol+CRIGHT,TMP); } if (cll[icol][0]) { printf(".nr %d %sn\n", TMP(%d", icol+CRIGHT); printf("\n"); printf(".nr %d \\n(.l-\\n(%d\n", TMP, TMP); if (boxflg || dboxflg || allflg) tsep =+ 1; else tsep =- sep[ncol-1]; printf(".nr %d \\n(%d/%d\n", TMP, TMP, tsep); printf(".if \\n(%d<0 .nr %d 0\n", TMP, TMP); } else printf(".nr %d 1n\n", TMP); printf(".nr %d 0\n",CRIGHT-1); tsep= (boxflg || allflg || dboxflg || left1flg) ? 1 : 0; for(icol=0; icol0 .nr #%c \\n(#T\n",linestop[i]+'a'-1); if (boxflg || allflg || dboxflg) /* bottom of table line */ if (fullbot[nlin-1]==0) { printf(".if \\n(T. .vs2p\n"); printf(".if \\n(T. "); drawline(nlin-1,0,ncol, dboxflg ? '=' : 'f(".nr #- \\n(#^\n"); /* current line position relative to bottom */ } vspf=0; for(c=0; c=0 && vspen(table[lf][c].col)) printf(".if (\\n(%c|+\\n(^%c-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(^%c-\\n(#--1v)\n",s,'a'+c,s,'a'+c); else printf(".if (\\n(%c|+\\n(#^-1v)>\\n(#- .nr #- +(\\n(%c|+\\n(#^-\\n(#--1v)\n",s,s); } if (instead[nl]) { puts(instead[nl]); return; } if (fullbot[nl]) { switch (ct=fullbotncol; c++) if (vspen(table[nl][c].col) && (nl==0 || (lf=prev(nl))<0 || !vspen(table[lf][c].col))) printf(".nr ^%c \\n(#^u\n", 'a'+c); } } puttext(s,fn, size, ilin, icol) char *s, *size, *fn; { int ip, cmidx; /***/ register int *ct; if (point(s)) { putfont(fn); putsize(size); ip = prev(ilin); /*** Temporary fudge because of stack overflow in c1 cmidx = ctop[stynum[ilin]][icol]==0; ***/ ct = ctop[stynum[ilin]]; cmidx = ct[icol]==0; if (ip>=0) if (vspen(table[ip][icol].col)) { printf("\\v'-(rintf(".mk %d\n", S2); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", S2, S1, S1, S2); } printf(".sp |\\n(%du\n", S1); } putfont(fn) char *fn; { if (fn && *fn) printf( fn[1] ? "\\f(%.2s" : "\\f%.2s", fn); } putsize(s) char *s; { if (s && *s) printf("\\s%s",s); } ot9.c~# include "t..c" yetmore() { int icol, ch; while (gets1(cstore=cspace)) { if (prefix(".TE", cstore)) break; if (cstore[0] == '.' && letter(cstore[1])) { puts(cstore); continue; } instead[0]=fullbot[0]=0pvecs[spcount++]= pp = calloc(MAXCHS+200,1); if (pp== -1) error("no space for characters"); return(pp); } # define MAXPC 50 char *thisvec; int tpcount -1; char *tpvecs[MAXPC]; alocv(n) { int *tp; if (tpcount<0 || thisvec+n > tpvecs[tpcount]+MAXCHS) { tpcount++; if (tpvecs[tpcount]==0) { tpvecs[tpcount] = calloc(MAXCHS,1); } thisvec = tpvecs[tpcount]; if (thisvec == -1) error("no space for vectors"); } tp=thisvec; thisvec=+n; return(tp); } release() { extern char *exstore; /* give back unwante; return(p); } # define BACKMAX 500 char backup[BACKMAX]; char *backp backup; un1getc(c, f) { if (c=='\n') iline--; *backp++ = c; if (backp >= backup+BACKMAX) error("too much backup"); } get1char() { int c; if (backp>backup) c = *--backp; else c=getchar(); if (c== '\n') iline++; return(c); } tf.c~# include "t..c" savefill() { /* remembers the status of fill mode in nr 45 (SF) */ /* nr SF = 0 means no fill, 1 means fill */ printf(".nr %d \\n(.u\n", SF); printf(".nf\n"); } rstofill-',1); printf("\n.if \\n(T. .vs\n"); /* T. is really an argument to a macro but because of eqn we don't dare pass it as an argument and reference by $1 */ } for(c=0; c=0) { printf(".if \\n(#%c>0 .sp -1\n",linestop[lf]+'a'-1); printf(".if \\n(#%c>0 ", linestop[lf]+'a'-1); tohcol(c); drawvert(lf, nlin-1, c, lwid); printf("\\h'|\\n(TWu'\n"); } } if (boxflg || allflg || dboxflg) /* right hand line */ { printf(".if \\n(#a>0[nl]) { case '=': case '-': fullwide(nl,ct); } return; } if (allflg && once>0 ) fullwide(i,'-'); once=1; runtabs(i); if (allh(i)) printf(".vs 2p\n"); printf("\\&"); for(c=0; c=0) { tohcol(c); drawvert(lf, i, c, lwid); } if ((form=ctype(i,c))!='s') printf("\\h'|\\n(%du'", ((form=='n'||form=='a')&&lused[c]==0)?c+CMID:c+CLEFT); s= table[nl][c].col; fn = font[stynum[i]][c]; size = csize[sty\\n(\\*(#du-\\n(^%cu", icol+'a'); if (cmidx) printf("-((\\n(#-u-\\n(^%cu)/2u)", icol+'a'); printf("'"); } printf("%s",s); if (ip>=0) if (vspen(table[ip][icol].col)) { printf("\\v'(\\n(\\*(#du-\\n(^%cu", icol+'a'); if (cmidx) printf("-((\\n(#-u-\\n(^%cu)/2u)", icol+'a'); printf("'"); } if (*fn>0) putfont("P"); if (size!=0) putsize("0"); } else watchout=1; } funnies( stl, lin) { /* write out funny diverted things */ int c, s; char *fn; /***/ register int *ct; printf(".mk ##\n"); /; if (cstore[1]==0) switch(cstore[0]) { case '_': fullbot[0]= '-'; putline(nlin-1,0); continue; case '=': fullbot[0]= '='; putline(nlin-1, 0); continue; } for (icol = 0; icol 'z') error("Too many text block diversions"); printf(".br\n"); printf(".di %c+\n", texname); if (textflg==0) .sp -1\n"); printf(".if \\n(#a>0 \\h'|\\n(TWu'"); drawvert (0, nlin-1, ncol, dboxflg? 2 : 1); printf("\n"); } printf("..\n"); printf(".ec\n"); } t8.cDU# include "t..c" # define realsplit ((ct=='a'||ct=='n') && table[nl][c].rcol) int watchout; int once; putline(i, nl) /* i is line number for deciding format */ /* nl is line number for finding data usually identical */ { int c, lf, ct, form, lwid, vspf; char *s, *size, *fn; watchout=vspf=0; if (i==0) once=0; if (i==0 && ( alnum[i]][c]; if (*size==0)size=0; switch(ct=ctype(i, c)) { case 'n': case 'a': if (table[nl][c].rcol) { if (lused[c]) /*Zero field width*/ { printf("%c%c",F1,F2); puttext(table[nl][c].col,fn,size,nl,c); printf("%c",F1); } s= table[nl][c].rcol; form=1; break; } case 'c': form=3; break; case 'r': form=2; break; case 'l': form=1; break; case '-': case '=': makeline(i,c,ct); continue; default: continue; } if (realsplit ? ru* rmember current vertical position */ printf(".nr %d \\n(##\n", S1); /* bottom position */ for(c=0; c=0) if (vspen(table[lf][c].col)) vspf=1; } if (vspf) { printf(".nr #^ \\n(\\*(#du\n"); printsed[c]: used[c]) /*Zero field width*/ ; else continue; /* form: 1 left, 2 right, 3 center adjust */ if (ifline(s)) { makeline(i,c,ifline(s)); continue; } printf("%c", F1); if (form!= 1) printf("%c", F2); if (vspen(s)) vspf=1; else puttext(s, fn, size, nl,c); if (form !=2) printf("%c", F2); printf("%c", F1); /* if lines need to be split for gcos here is the place for a backslash */ } printf("\n"); if (allh(i)) printf(".vs\n"); if (watchout) funnies(i,nl); if (vspf) { for(c=0; c0 && vspen(table[prev(stl)][c].col)) { printf(".sp |\\n(^%cu\n", 'a'+c); /*** temporary fudge because of stack overflow in c1 if (ctop[stynum[stl]][c]==0) ***/ ct = ctop[stynum[stl]]; if (ct[c]==0) { printf(".nr %d \\n(#-u-\\n(^%c-\\n(%c|+1v\n",TMP, 'a'+c, s); printf(".if \\n(%d>0 .sp \\n(%du/2u\n", TMP, TMP); } } printf(".%c+\n",s); printf(".in -\\n(%du\n", SIND); if (*fn>0) putfont("P"); pn'||k=='a')) { lused[c] =| real(table[i][c].col); rused[c]=| real(table[i][c].rcol); if( !real(table[i][c].rcol)) used[c] =| real(table[i][c].col); } else used[c] =| real(table[i][c].col); } } } real(s) char *s; { if (s==0) return(0); if (!point(s)) return(1); if (*s==0) return(0); return(1); } int spcount 0; # define MAXVEC 20 char *spvecs[MAXVEC]; chspace() { char *pp; if (spvecs[spcount]) return(spvecs[spcount++]); if (spcount>=MAXVEC) error("Too many characters in table"); sF1==0 || F2==0) error("couldn't find characters to use for delimiters"); return; } point(s) { return(s>= 128 || s<0); } ste.c~# include "t..c" error(s) char *s; { printf(2, "\n%s: line %d: %s\n", ifile, iline, s); # ifdef unix printf(2, "tbl quits\n"); cexit(1); # endif # ifdef gcos printf(2, "run terminated due to error condition detected by tbl preprocessor\n"); cexit(0); # endif } gets1(s) char *s; { char *p; iline++; p=gets(s); while (*s) s++; s--; if (*s == '\\') gets1(s).vs\n"); printf(".br\n"); printf(".di\n"); printf(".nr %c| \\n(dn\n", texname); printf(".nr %c- \\n(dl\n", texname); /* copy remainder of line */ if (line[2]) tcopy (sp, line+3); else *sp=0; return(texname++); } untext() { printf(".nf\n"); printf(".ll \\n(%du\n", TMP); } ti.c~# include "t..c" /* determine local environment for intersections */ interv(i,c) { int ku, kl; if (c>=ncol) { if (dboxflg) { if (i==0) return(BOT); if (i>=nlin-1) return(TOP); return(THRU); } return(0); } ku = i>0 ? lefdata(i-1,c) : 0; if (i+1 >= nlin) kl=0; else kl = lefdata(allh(i) ? i+1 : i, c); if (ku==2 && kl==2) return(THRU); if (ku ==2) return(TOP); if (kl==BOT) return(2); return(0); } interh(i,c) { int kl, kr; if (fullbot[i]== '=' || (dboxflg && (i==0 || i>= nlin-1))) { if (c==ncol) return(LEFT); if (c==0) return(RIGHT); return(THRU); } if (i>=nlin) return(0); kl = c>0 ? thish (i,c-1) : 0; if (kl<=1 && i>0 && allh(up1(i))) kl = c>0 ? thish(up1(i),c-1) : 0; kr = thish(i,c); if (kr< return(k); } digit(x) { return(x>= '0' && x<= '9'); } max(a,b) { return( a>b ? a : b); } index (s,c) char *s; { int k; for(k=0; s[k]; k++) if (s[k]==c) return(k); return(-1); } tcopy (s,t) char *s, *t; { while (*s++ = *t++); } tt.c~# include "t..c" ctype(il, ic) { if (instead[il]) return(0); if (fullbot[il]) return(0); il = stynum[il]; return(style[il][ic]); } min(a,b) { return(a1) { switch(inli=i); if (prev(li)== -1) li=0; *lwidp=kind; return(li); } lefdata(i,c) { int ck; if (i>=nlin) i=nlin-1; if (ctype(i,c) == 's') { for(ck=c; ctype(i,ck)=='s'; ck--); if (thish(i,ck)==0) return(0); } i =stynum[i]; i = lefline[i][c]; if (i>0) return(i); if (dboxflg && c==0) return(2); if (allflg)return(1); if (boxflg && c==0) return(1); return(0); } next(i) { while (i+1 =0 && (fullbot[i] || instead[i])) ; retuintf("\\L'|\\n(#%cu-1v", linestop[start]+'a'-1); if (ext1) printf("-%s",ext1); if (ext2) printf("+%s", ext2); if (exb1) printf("-%s", exb1); if (exb2) printf("-%s", exb2); /* the string #d is either "nl" or ".d" depending on diversions; on GCOS not the same */ printf("'\\v'\\n(\\*(#du-\\n(#%cu+1v", linestop[start]+'a'-1); if (ext1) printf("+%s",ext1); if (ext2) printf("-%s", ext2); printf("'"); } } midbar(i,c) { int k; k = midbcol(i,c); if (k==0 && c>0) k = midbcol(i, c-1); retu.if \n(mo=1 .ds mo January .if \n(mo=2 .ds mo February .if \n(mo=3 .ds mo March .if \n(mo=4 .ds mo April .if \n(mo=5 .ds mo May .if \n(mo=6 .ds mo June .if \n(mo=7 .ds mo July .if \n(mo=8 .ds mo August .if \n(mo=9 .ds mo September .if \n(mo=10 .ds mo October .if \n(mo=11 .ds mo November .if \n(mo=12 .ds mo December .if \n(dw=1 .ds dw Sunday .if \n(dw=2 .ds dw Monday .if \n(dw=3 .ds dw Tuesday .if \n(dw=4 .ds dw Wednesday .if \n(dw=5 .ds dw Thursday .if \n(dw=6 .ds dw Friday .if \n(dw=7 .ds dw Saturday =1 && i>0 && allh(up1(i))) kr = c>0 ? thish(up1(i), c) : 0; if (kl== '=' && kr == '=') return(THRU); if (kl== '=') return(LEFT); if (kr== '=') return(RIGHT); return(0); } up1(i) { i--; while (instead[i] && i>0) i--; return(i); } ftm.c~# include "t..c" maknew(str) char *str; { /* make two numerical fields */ int dpoint, c; char *p, *q, *ba; p = str; for (ba= 0; c = *str; str++) if (c == '\\' && *(str+1)== '&') ba=str; str=p; if (ba==0) { for (dpoint=0; *str; str++) ctype(i,c) != 's') return(0); c++; if (c < ncol && ctype(i,c)== 's') return(0); for(k=0; ctype(i,--c) == 's'; k++); return(k); } ctspan(i,c) { int k; c++; for(k=1; c1) { switch(interv(i,cr+1)) { case TOP: exhr = ln==0 ? "-1p" : "+1p"; break; case BOT: exhr = ln==1 ? "-rn(i); } tv.c~ # include "t..c" drawvert(start,end, c, lwid) { char *exb1, *exb2, *ext1, *ext2; int sl, ln, tp, pos; tp =exb1 =exb2 =ext1 = ext2 = 0; end++; while (instead[end]) end++; for(ln=0; lnp && digit(*(str-1)) || digit(*(str+1)))) dpoint=str; if (!dpoint && *(str-1)== '$') return(0); if (dpoint==0) for(; str>p; str--) { if (digit( * (str-1) ) ) break; } if (!dpoint && p==str) /* not numerical, don't split */ return(0); if (dpoint) str=dpoint; } else str = ba; p =str; if (exstore ==0 || exstore >exlim) { exstore = chspace(); exlim= exstore+MAXCHS; } q = exstore; while (*exstore++ = *str++); *p = 0; return(q);col; c++) { k = thish(i,c); if (k==0) return(0); if (k==1) continue; one=1; } return(one); } thish(i,c) { int t; char *s; if (c<0)return(0); if (i<0) return(0); t = ctype(i,c); if (t=='_' || t == '-') return('-'); if (t=='=')return('='); if (t=='^') return(1); if (fullbot[i] ) return(fullbot[i]); if (t=='s') return(thish(i,c-1)); if (t==0) return(1); s= table[i][c].col; if (s==0 || (point(s) && *s==0)) return(1); if (vspen(s)) return(1); if (t=barent( s)) return(t); return(0); 1p" : "+1p"; break; case THRU: exhr = "-1p"; break; } } else if (lcount==1) { switch(interv(i,cr+1)) { case TOP: case BOT: exhr = "+1p"; break; case THRU: exhr = "-1p"; break; } } if (cr+1>=ncol) printf("\\l'|\\n(TWu%s\\(ul'", exhr); else printf("\\l'(|\\n(%du+|\\n(%du)/2u%s\\(ul'", cr+CRIGHT, cr+1+CLEFT, exhr); } if (oldpos!=0) printf("\\v'%dp'", -oldpos); if (!nodata) printf("\\v'+.5m'"); } getstop() { int i,c,k,junk, stopp; stopp=1; for(i=0; i1) switch(interh(end, c)) { case THRU: exb2 ="-1p"; break; case RIGHT: exb2 = ln==0 ? "1p" : "-1p";break; case LEFT: exb2 = ln==1 ? "1p" : "-1p"; break; } if (lwid==1) switch(interh(end,c)) { case THRU: exb2 = "-1p"; break; case RIGHT: case LEFT: exb2 = "1p"; break; } if (start>0) { sl = start-1; while (instead[sl]&&sl>=0) sl--; if (fullbot[sl] || allh(sl)) ext1 = "0p"; else if (sl>=0) switch(midbar(sl,c)) { case '-': ext1= ".5m"; brea.br .nr zz 11 .de cl .ie \\n+(cl<\n(zz \{\ . po +\\n(.lu/\n(zzu . rt\} .el \{.po 26i/27u\} .. .nr cl 0 1 .di zz .ta .3iR .nf .ps 8 .vs 10 ad 4 af 8 am 7 as 7 bd 2 bp 3 br 4 c2 10 cc 10 ce 4 ch 7 cs 2 cu 10 da 7 de 7 di 7 ds 7 dt 7 ec 10 el 16 em 7 eo 10 ev 17 ex 18 fc 9 fi 4 fl 20 fp 2 ft 2 hc 13 hw 13 hy 13 ie 16 if 16 ig 20 in 6 it 7 lc 9 lg 10 li 10 ll 6 ls 5 lt 14 mc 20 mk 3 na 4 ne 3 nf 4 nh 13 nm 15 nn 15 nr 8 ns 5 nx 19 os 5 pc 14 pi 19 pl 3 pm 20 pn 3 po 3 ps 2 rd 18 rm 7 rn 7 rr 8 rs 5 rt 3 so 19 see \fBde\fR) 11.1 \fB\e\fR(space) Unpaddable space-size space character 11.1 \fB\e0\fR Digit width space .tr || 11.1 \fB\e\||\fR 1\(sl6\|em narrow space character (zero width in \*(NR) .tr | 11.1 \fB\e^\fR 1\(sl12\|em half-narrow space character (zero width in \*(NR) .tr && 4.1 \fB\e&\fR Non-printing, zero width character .tr &. 10.6 \fB\e!\fR Transparent line indicator 10.7 \fB\e"\fR Beginning of comment 7.3 \fB\e$\fIN\fR Interpolate argument 1\(<=\fIN\fR\(<=9 13 \fB\e%\fR Default optional hyphenation char } ts.c~match (s1, s2) char *s1, *s2; { while (*s1 == *s2) if (*s1++ == '\0') return(1); else s2++; return(0); } prefix(small, big) char *small, *big; { int c; while ((c= *small++) == *big++) if (c==0) return(1); return(c==0); } letter (ch) { if (ch >= 'a' && ch <= 'z') return(1); if (ch >= 'A' && ch <= 'Z') return(1); return(0); } numb(str) char *str; { /* convert to integer */ int k; for (k=0; *str >= '0' && *str <= '9'; str++) k = k*10 + *str - '0'; } tu.c~ # include "t..c" makeline(i,c,lintype) { int cr, type; type = thish(i,c); if (type==0) return; if (c>0 && thish(i,c-1) == type)return; for(cr=c; cr < ncol && (ctype(i,cr)=='s'||type==thish(i,cr)); cr++); drawline(i, c, cr-1, lintype,0); } fullwide(i, lintype) { int cr, cl; printf(".vs 2p\n"); cr= 0; while (cr0 && vspand(i-1,cl)) cl++; for(cr=cl; cr0 && vspand(i-1,cr)) break; if (cl=0 && linestop[k]==0) linestop[k]= ++stopp; } if (boxflg || allflg || dboxflg) linestop[0]=1; } left(i,c, lwidp) int *lwidp; { int kind, li; /* returns -1 if no line to left */ /* returns number of line where it starts */ /* stores into lwid the kind of line */ *lwidp=0; kind = lefdata(i,c); if (kind==0) return(-1); if (i+1=0 && lefdata(i,c)==kind) i=prev(k; case '=': ext1= "(.5m+1p)"; break; default: ext1 = "-2p"; break; } else ext1 = "2p"; } if (lwid>1) switch(interh(start,c)) { case THRU: ext2 = "1p"; break; case LEFT: ext2 = ln==0 ? "1p" : "-1p"; break; case RIGHT: ext2 = ln==1 ? "1p" : "-1p"; break; } else if (lwid==1) switch(interh(start,c)) { case THRU: ext2 = "1p"; break; case LEFT: case RIGHT: ext2 = "-1p"; break; } if (exb1) printf("\\v'%s'", exb1); if (exb2) printf("\\v'%s'", exb2); prp 5 ss 2 sv 5 ta 9 tc 9 ti 6 tl 14 tm 20 tr 10 uf 10 ul 10 vs 5 wh 7 .di .nr aa \n(dn/\n(zz .ne \\n(aau+10p .sp .ftB Alphabetical Request and Section Number Cross Reference .ft .sp.3 .wh \n(nlu+\n(aau cl .nr qq \n(nlu+\n(aau .ps .vs .mk .zz .rt .sp \n(.tu .ch cl 12i .sp acter 2.1 \fB\e(\fIxx\fR Character named \fIxx\fR 7.1 \fB\e\(**\fIx\fR,|\fB\e\(**(\fIxx\fR Interpolate string \fIx\fR or \fIxx\fR 9.1 \fB\ea\fR Non-interpreted leader character 12.3 \fB\eb\fI\'abc...\|\'\fR Bracket building function 4.2 \fB\ec\fR Interrupt text processing 11.1 \fB\ed\fR Forward (down) 1\(sl2\|em vertical motion (1\(sl2 line in \*(NR) 2.2 \fB\ef\fIx\fR,\fB\ef(\fIxx\fR,\fB\ef\fIN\fR Change to font named \fIx\fR or \fIxx\fR, or position \fIN\fR 11.1 \fB\eh\fI\'N|\'\fR Local horizontal motion; move right \fIN\fR \fI(negative left)\fR 11.3 \fB\ek\fIx\fR Mark horizontal \fIinput\fR place in register \fIx\fR 12.4 \fB\el\fI\|\'Nc\|\'\fR Horizontal line drawing function (optionally with \fIc\fR\|) 12.4 \fB\eL\fI\'Nc\|\'\fR Vertical line drawing function (optionally with \fIc\fR\|) 8 \fB\en\fIx\fR,\fB\en(\fIxx\fR Interpolate number register \fIx\fR or \fIxx\fR 12.1 \fB\eo\fI\'abc...\|\'\fR Overstrike characters \fIa, b, c, ...\fR 4.1 \fB\ep\fR Break and spread output line 11.1 \fB\er\fR Reverse 1\|em vt into a printable, paginated document having a user-designed style. \*(NR and \*(TR offer unusual freedom in document styling, including: arbitrary style headers and footers; arbitrary style footnotes; multiple automatic sequence numbering for paragraphs, sections, etc; multiple column output; dynamic font and point-size control; arbitrary horizontal and vertical local motions at any point; and a family of automatic overstriking, bracket construction, and line drawing functions. .pg \*(NR and \*(TR are hig=1) to allow paper loading or changing, and will resume upon receipt of a newline. \*(TR will stop the phototypesetter every \fIN\fR pages, produce a trailer to allow changing cassettes, and will resume after the phototypesetter \s-1START\s+1 button is pressed. .bt \fB\-m\fIname\fR Prepends the macro file \fB\(slusr\(sllib\(sltmac.\fIname\fR to the input \fIfiles\fR. .bt \fB\-r\fIaN\fR Register \fIa\fR (one-character) is set to \fIN\fR. .bt \fB\-i\fP Read standard input after the input files are exhauste\fP Send a printable \s-1(ASCII)\s+1 approximation of the results to the standard output. .bt \fB\-p\fIN\fR Print all characters in point size \fIN\fR while retaining all prescribed spacings and motions, to reduce phototypesetter elasped time. .bt \fB\-g\fR Prepare output for the Murray Hill Computation Center phototypesetter and direct it to the standard output. .ll .in0 .xx .pg Each option is invoked as a separate argument; for example, .x1 \fBnroff \-o\fI4,8\-10 \fB\-T\fI300S \fB\-m\fIabc file1 fitorial is [5]. .sp.4i .ta 4i Joseph F. Ossanna .sp.4 .ps -1 .vs -1p .pg .ftB References .pg .ta .3i .in .3i .ti0 [1] K. Thompson, D. M. Ritchie, .ul UNIX Programmer's Manual, Sixth Edition (May 1975). .sp.4 .ti0 [2] B. W. Kernighan, L. L. Cherry, .ul Typesetting Mathematics \(em User's Guide (Second Edition), Bell Laboratories internal memorandum. .sp.4 .ti0 [3] M. E. Lesk, .ul Tbl \(em A Program to Format Tables, Bell Laboratories internal memorandum. .sp.4 .ti0 [4] Internal on-line documentation, on \s-1sition 1\(<=\fIN\fR\(<=4. .mh Page Control .bt \fB&pl\fI\|\(+-N\fR 11\|in 11\|in \fBv\fR Page length. .b1 \fB&bp|\fI\(+-N\fR \fIN\(eq\fR1 - B\(dd,\fBv\fR \ Eject current page; next page number \fIN\fR. .fn .sp.2 \(ddThe use of "\ \fB\'\fR\ " as control character (instead of "\fB.\fR") suppresses the break function. .ef .b1 \fB&pn\fI|\(+-N N\(eq\fR1 ignored - Next page number \fIN\fR. .b1 \fB&po\fI|\(+-N\fR 0;|26\(sl27\|in previous \fBv\fR Page offset. .b1 \fB&ne\fI|N\fR - \fIN\(eq\fR1\fIV\fR D,\fBv\fR Need ertical motion (reverse line in \*(NR) 2.3 \fB\es\fIN\fR,\|\fB\es\fI\(+-N\fR Point-size change function 9.1 \fB\et\fR Non-interpreted horizontal tab 11.1 \fB\eu\fR Reverse (up) 1\(sl2\|em vertical motion (1\(sl2 line in \*(NR) 11.1 \fB\ev\fI\'N\|\|\'\fR Local vertical motion; move down \fIN\fR \fI(negative up)\fR 11.2 \fB\ew\fI\'string\|\'\fR Interpolate width of \fIstring\fR 5.2 \fB\ex\fI\'N\|\|\'\fR Extra line-space function \fI(negative before, positive after)\fR 12.2 \fB\ez\fIc\fR Print \fIc\fR with zerhly compatible with each other and it is almost always possible to prepare input acceptable to both. Conditional input is provided that enables the user to embed input expressly destined for either program. \*(NR can prepare output directly for a variety of terminal types and is capable of utilizing the full resolution of each terminal. .pg .ftB Usage .pg The general form of invoking \*(NR (or \*(TR) at \s-1UNIX\s+1 command level is .x1 \fBnroff \fIoptions files\fR\ \h'|2i'(or \fBtroff \fIoptions filesd. .bt \fB\-q\fR \ Invoke the simultaneous input-output mode of the \fBrd\fR request. .sp .ne 3 .ftI .bd I 3 \*(NR Only .br .bd I .ft .bt \fB\-T\fIname\fR Specifies the name of the output terminal type. Currently defined names are \fB37\fR for the (default) Model 37 teletype, \fBtn300\fR for the GE TermiNet\ 300 (or any terminal without half-line capabilities), \fB300S\fR for the \s-1DASI\s+1-300S, \fB300\fR for the \s-1DASI\s+1-300, and \fB450\fR for the \s-1DASI\s+1-450 (Diablo Hyterm). .bt \fB\-e\fRle2\fR .x2 requests formatting of pages 4, 8, 9, and 10 of a document contained in the files named \fIfile1\fR and \fIfile2\fR, specifies the output terminal as a \s-1DASI\s+1-300S, and invokes the macro package \fIabc\fR. .pg Various pre- and post-processors are available for use with \*(NR and \*(TR. These include the equation preprocessors \s-1NEQN\s+1 and \s-1EQN\s+1\*u2\*d (for \*(NR and \*(TR respectively), and the table-construction preprocessor \s-1TBL\s+1\*u3\*d. A reverse-line postprocessor \s-1COUNIX\s+1. .sp.4 .ti0 [5] B. W. Kernighan, \fIA TROFF Tutorial\fR, Bell Laboratories internal memorandum. .in0 .ps .vs \fIN\fR vertical space (\fIV\fR = vertical spacing). .b1 \fB&mk|\fIR\fR none internal D Mark current vertical place in register \fIR\fR. .b1 \fB&rt\fI|\(+-N\fR none internal D,\fBv\fR Return \fI(upward only)\fR to marked vertical place. .mh Text Filling, Adjusting, and Centering .bt \fB&br\fR - - B Break. .b1 .lg0 \fB&fi\fR \(fill - B,E Fill output lines. .lg .b1 \fB&nf\fR fill - B,E No filling or adjusting of output lines. .b1 \fB&ad\fI|c\fR adj,both adjust E Adjust output lines with mode \fIc\fR. .b1 \fB&o width (without spacing) 16 \fB\e{\fR Begin conditional input 16 \fB\e}\fR End conditional input 10.7 \fB\e\fR(newline) Concealed (ignored) newline - \fB\e\fIX\fR \fIX\fR, any character \fInot\fR listed above .TE .fi .sp The escape sequences \fB\e\e\fR, \fB\e\^.\fR, \fB\e"\fR, \fB\e$\fR, \fB\e\(**\fR, \fB\ea\fR, \fB\en\fR, \fB\et\fR, and \fB\e\fR(newline) are interpreted in \fIcopy mode\fR (\(sc7.2). \fR) .x2 where \fIoptions\fR represents any of a number of option arguments and \fIfiles\fR represents the list of files containing the document to be formatted. An argument consisting of a single minus (\fB\-\fR) is taken to be a file name corresponding to the standard input. If no file names are given input is taken from the standard input. The options, which may appear in any order so long as they appear before the files, are: .sp .ta .2i 1.0i .ftI .bd I 3 Option Effect .br .bd I .ftR .ta .3i 1.0i .in 1 \ Produce equally-spaced words in adjusted lines, using full terminal resolution. .sp .ne 3 .ftI .bd I 3 \*(TR Only .br .bd I .ft .bt \fB\-t\fP Direct output to the standard output instead of the phototypesetter. .bt \fB\-f\fP Refrain from feeding out paper and stopping phototypesetter at the end of the run. .bt \fB\-w\fP Wait until phototypesetter is available, if currently busy. .bt \fB\-b\fR \*(TR will report whether the phototypesetter is busy or available. No text processing is done. .bt \fB\-aL\s+1\*u4\*d is available for multiple-column \*(NR output on terminals without reverse-line ability; \s-1COL\s+1 expects the Model 37 Teletype escape sequences that \*(NR produces by default. \s-1TK\s+1\*u4\*d is a 37 Teletype simulator postprocessor for printing \*(NR output on a Tektronix 4014. \s-1TCAT\s+1\*u4\*d is phototypesetter-simulator postprocessor for \*(TR that produces an approximation of phototypesetter output on a Tektronix 4014. For example, in .x1 \fBtbl \fIfiles \fB| eqn | troff \-t.pn3 .br .tr | .ce .ftB SUMMARY AND INDEX .ftR .de mx .ev2 .nf .h1 .in .sp .fi .ev .ns .. .xx .h1 \s-1#\s+1 * .fn .sp.3 *Values separated by "\fB;\fR" are for \*(NR and \*(TR respectively. .sp.2 \s-1#\s+1Notes are explained at the end of this Summary and Index .ef .mh General Explanation .mh Font and Character Size Control .bt \fB&ps\fI\|\(+-N\fR 10\|point previous E Point size; also \fB\es\fI\(+-N\fR.\(dg .b1 \fB&ss\fI|N\fR 12\(sl36\|em ignored E Space-character size set to \fIN\fR\(sl36\|em.\(dg .b1 \fB&cna\fR adjust - E No output line adjusting. .b1 \fB&ce\fI|N\fR off \fIN\(eq\fR1 B,E Center following \fIN\fR input text lines. .mh Vertical Spacing .bt \fB&vs\fI|N\fR 1\(sl6in;12pts previous E,\fBp\fR Vertical base line spacing (\fIV\fR\^). .b1 \fB&ls\fI|N N\(eq\fR1 previous E Output \fIN\(mi\fR1 \fIV\^\fRs after each text output line. .b1 \fB&sp\fI|N\fR - \fIN\(eq\fR1\fIV\fR B,\fBv\fR Space \ vertical distance \fIN\fR \fIin either direction\fR. .b1 \fB&sv\fI|N\fR - \fIN\(eq\fR1\fIV\fR \fBv\fR Save vertical .br .rs .sp |1.50i .ce1000 .ps12 .ftB \*(Nr\(sl\*(Tr User's Manual .sp .2i .ftI .ps10 Joseph F. Ossanna .ftR .sp Bell Laboratories Murray Hill, New Jersey 07974 .ce0 .sp2 .ps \n(PS .fi .ftB Introduction .pg \*(NR and \*(TR are text processors under the \s-1PDP\s+1-11 \s-1UNIX\s+1 Time-Sharing System\*u1\*d that format text for typewriter-like terminals and for a \%Graphic Systems phototypesetter, respectively. They accept lines of text interspersed with lines of format control information and format the tex.0i .ll-.3i .bt \fB\-o\fIlist\fR \ Print only pages whose page numbers appear in \fIlist\fR, which consists of comma-separated numbers and number ranges. A number range has the form \fIN\-M\fR and means pages \fIN\fR through \fIM;\fR a initial \fI\-N\fR means from the beginning to page \fIN;\fR and a final \fIN\-\fR means from \fIN\fR to the end. .bt \fB\-n\fIN\fR Number first generated page \fIN\fR. .bt \fB\-s\fIN\fR Stop every \fIN\fR pages. \*(NR will halt prior to every \fIN\fR pages (default \fIN\fR b Q W ] c R X ^ S Y _ e T Z \fIoptions \fB| tcat\fR .x2 the first \|\fB|\fR\| indicates the piping of \s-1TBL\s+1's output to \s-1EQN\s+1's input; the second the piping of \s-1EQN\s+1's output to \*(TR's input; and the third indicates the piping of \*(TR's output to \s-1TCAT\s+1. \s-1GCAT\s+1\*u4\*d can be used to send \*(TR (\fB\-g\fR) output to the Murray Hill Computation Center. .br .pg The remainder of this manual consists of: a Summary and Index; a Reference Manual keyed to the index; and a set of Tutorial Examples. Another tus\fI\|F\|N\|M\fR off - P Constant character space (width) mode (font \fIF\^\fR\^).\(dg .b1 \fB&bd\fI|F|N\fR off - P Embolden font \fIF\fR by \fIN\fR\(mi1 units.\(dg .b1 \fB&bd|S|\fIF|N\fR off - P Embolden Special Font when current font is \fIF\fR.\(dg .fn .sp.2 \(dgNo effect in \*(NR. .ef .b1 \fB&ft\fI|F\fR Roman previous E Change to font \fIF\fR|= \fIx\fR, \fIxx\fR, or 1-4. Also \fB\ef\fIx\fR,\|\fB\ef(\fIxx\fR,\|\fB\ef\fIN\fR. .b1 \fB&fp\fI|N|F\fR R,I,B,S ignored - Font named \fIF\fR mounted on physical podistance \fIN\fR. .b1 \fB&os\fR - - - Output saved vertical distance. .b1 \fB&ns\fR space - D Turn no-space mode on. .b1 \fB&rs\fR - - D Restore spacing; turn no-space mode off. .mh Line Length and Indenting .bt \fB&ll\fI|\(+-N\fR 6.5\|in previous E,\fBm\fR Line length. .b1 \fB&in\fI|\(+-N\fR \fIN\(eq\fR\^0 previous B,E,\fBm\fR Indent. .b1 \fB&ti\fI|\(+-N\fR - ignored B,E,\fBm\fR Temporary indent. .mh Macros, Strings, Diversion, and Position Traps .bt \fB&de\fI|xx|yy\fR - \fI.yy=\fB..\fR - Define or redefine macro \fIxx;\fR end at call of \fIyy\fR. .b1 \fB&am\fI|xx|yy\fR - \fI.yy=\fB..\fR - Append to a macro. .b1 \fB&ds\fI|xx|string\fR - ignored - Define a string \fIxx\fR containing \fIstring\fR. .b1 \fB&as\fI|xx|string\fR - ignored - Append \fIstring\fR to string \fIxx\fR. .b1 \fB&rm\fI|xx\fR - ignored - Remove request, macro, or string. .b1 \fB&rn\fI|xx|yy\fR - ignored - Rename request, macro, or string \fIxx\fR to \fIyy\fR. .b1 \fB&di\fI|xx\fR - end D Divert output to macro \fIxx\fR. .b1 \fB&da\fI|xx\fR - Output Conventions and Character Translations .bt \fB&ec\fI|c\fR \e \e - Set escape character. .b1 \fB&eo\fR on - - Turn off escape character mechanism. .b1 \fB&lg\fI|N\fR -;\|on on - Ligature mode on if \fIN\fR>0. .b1 \fB&ul\fI|N\fR off \fIN\(eq\fR1 E Underline (italicize in \*(TR) \fIN\fR input lines. .b1 \fB&cu\fI|N\fR off \fIN\(eq\fR1 E Continuous underline in \*(NR; like \fBul\fR in \*(TR. .b1 \fB&uf\fI|F\fR Italic Italic - Underline font set to \fIF\fR (to be switched to by \fBul\fR). .b1 \fB&cc\fI|c\thing\fR. .b1 \fB&if|!\fI\|\'string1\|\'string2\|\'|anything\fR - If \fIstring1\fR not identical to \fIstring2\fR, accept \fIanything\fR. .b1 \fB&ie\fI|c|anything\fR - \fBu\fR If portion of if-else; all above forms (like \fBif\fR). .b1 \fB&el\fI|anything\fR - - Else portion of if-else. .mh Environment Switching. .bt \fB&ev\fI|N\fR \fIN\(eq\fR0 previous - Environment switched (\fIpush down\fR). .mh Insertions from the Standard Input .bt \fB&rd\fI|prompt\fR\fR - \fIprompt=\s-1\fRBEL\s+1 - Read insertion. .b1.pn8 .tr | .tr ~| .rm mx .br .ce .ftB .ps+2 .rs .sp1.0i REFERENCE MANUAL .ftR .ps-2 .sp .mh General Explanation .sc Form of input. Input consists of \fItext lines\fR, which are destined to be printed, interspersed with \fIcontrol lines\fR, which set parameters or otherwise control subsequent processing. Control lines begin with a \fIcontrol character\fR\(em\ normally \fB.\fR (period) or \fB\'\fR (acute accent)\(em\ followed by a one or two character name that specifies a basic \fIrequest\fR or the substitute). .sc Numerical parameter input. Both \*(NR and \*(TR accept numerical input with the appended scale indicators shown in the following table, where \fIS\fR is the current type size in points, \fIV\fR is the current vertical line spacing in basic units, and \fIC\fR is a \fInominal character width\fR in basic units. .TS center box; c|c|ls c|c|ll c|l|l|l. Scale Number of basic units Indicator Meaning \*(TR \*(NR _ \fBi\fR Inch 432 240 \fBc\fR Centimeter 432\(mu50\(sl127 240\(mu50\(sl127 \fBP\fR Pica = 1\(sl k q w } l r x ~ s y  end D Divert and append to \fIxx\fR. .b1 \fB&wh\fI|N|xx\fR - - \fBv\fR Set location trap; negative is w.r.t. page bottom. .b1 \fB&ch\fI|xx|N\fR - - \fBv\fR Change trap location. .b1 \fB&dt\fI|N|xx\fR - off D,\fBv\fR Set a diversion trap. .b1 \fB&it\fI|N|xx\fR - off E Set an input-line count trap. .b1 \fB&em\fI|xx\fR none none - End macro is \fIxx\fI. .mh Number Registers .bt \fB&nr\fI|R|\(+-N|M\fR - \fBu\fR Define and set number register \fIR\fR; auto-increment by \fIM\fR. .b1 \fB&af\fI|R|c\fR arabic - - AsfR \fB. .\fR E Set control character to \fIc\fR. .b1 \fB&c2\fI|c\fR \fB\' \'\fR E Set nobreak control character to \fIc\fR. .b1 \fB&tr\fI|abcd....\fR none - O Translate \fIa\fR to \fIb\fR, etc. on output. .mh Local Horizontal and Vertical Motions, and the Width Function .mh Overstrike, Bracket, Line-drawing, and Zero-width Functions .mh Hyphenation. .bt \fB&nh\fR hyphenate - E No hyphenation. .b1 \fB&hy\fI|N\fR hyphenate hyphenate E Hyphenate; \fIN =\fR mode. .b1 \fB&hc\fI|c\fR \fB\e% \e%\fR E Hyphenation i \fB&ex\fR - - - \ Exit from \*(NR\(sl\*(TR. .mh Input\(slOutput File Switching .bt \fB&so\fI|filename\fR - - Switch source file \fI(push down)\fR. .b1 \fB&nx\fI|filename\fR end-of-file - Next file. .b1 \fB&pi\fI|program\fR - - Pipe output to \fIprogram\fR (\*(NR only). .mh Miscellaneous .bt \fB&mc\fI|c|N\fR - off E,\fBm\fR Set margin character \fIc\fR and separation \fIN\fR. .b1 \fB&tm\fI|string\fR - newline - Print \fIstring\fR on terminal \ (\s-1UNIX\s+1 standard message output). .b1 \fB&ig\fI|yy\fR -ion of a user-defined \fImacro\fR in place of the control line. The control character \fB\'\fR suppresses the \fIbreak\fR function\(em\ the forced output of a partially filled line\(em\ caused by certain requests. The control character may be separated from the request/macro name by white space (spaces and/or tabs) for esthetic reasons. Names must be followed by either space or newline. Control lines with unrecognized names are ignored. .pg Various special functions may be introduced anywhere in the input b6 inch 72 240\(sl6 \fBm\fR Em = \fIS\fR points 6\(mu\fIS\fR \fIC\fR \fBn\fR En = Em\(sl2 3\(mu\fIS\fR \fIC, same as Em\fR \fBp\fR Point = 1\(sl72 inch 6 240\(sl72 \fBu\fR Basic unit 1 1 \fBv\fR Vertical line space \fIV\fR \fIV\fR none Default, see below .TE In \*(NR, \fIboth\fR the em and the en are taken to be equal to the \fIC\fR, which is output-device dependent; common values are 1\(sl10 and 1\(sl12 inch. Actual character widths in \*(NR need not be all the same and constructed characters such as \(mi> the vertical or horizontal place \fIN\fR. For vertically-oriented requests and functions, \fB~\|\fIN\fR becomes the distance in basic units from the current vertical place on the page or in a \fIdiversion\fR (\(sc7.4) to the the vertical place \fIN\fR. For \fIall\fR other requests and functions, \fB~\|\fIN\fR becomes the distance from the current horizontal place on the \fIinput\fR line to the horizontal place \fIN\fR. For example, .x1 \&\fB.sp ~\|3.2c\fR .x2 will space \fIin the required direction\fR to 3 ` f U [ a g h n z i o u { j p v |ndicator character \fIc\fR. .b1 \fB&hw\fI|word1|...\fR ignored - Exception words. .mh Three Part Titles. .bt \fB&tl\fI|\'left\|\'center\|\'right\|\'\fR - - Three part title. .b1 \fB&pc\fI|c\fR \fB%\fR off - Page number character. .b1 \fB<\fI|\(+-N\fR 6.5\|in previous E,\fBm\fR Length of title. .mh Output Line Numbering. .bt \fB&nm\fI|\(+-N|M|S|I\fR off E Number mode on or off, set parameters. .b1 \fB&nn\fI|N\fR - \fIN\(eq\fR1 E Do not number next \fIN\fR lines. .mh Conditional Acceptance of Input .bt \fB& \fI.yy=\fB..\fR - Ignore till call of \fIyy\fR. .b1 \fB&pm\fI|t\fR - all - Print macro names and sizes; .b1 if \fIt\fR present, print only total of sizes. .b1 .lg0 \fB&fl\fR - - B Flush output buffer. .lg .mh Output and Error Messages .xx .nf .rm mx .ftR \l'\n(.lu' .ftB .xx .ta .3iC .6i Notes- .xx .ftR B Request normally causes a break. D Mode or relevant parameters associated with current diversion level. E Relevant parameters are a part of the current environment. O Must stay in effect until logy means of an \fIescape\fR character, normally \fB\e\fR. For example, the function \fB\en\fIR\fR causes the interpolation of the contents of the \fInumber register R\fR in place of the function; here \fIR\fR is either a single character name as in \fB\en\fIx\fR, or left-parenthesis-introduced, two-character name as in \fB\en(\fIxx\fR. .sc Formatter and device resolution. \*(TR internally uses 432 units\(slinch, corresponding to the Graphic Systems phototypesetter which has a horizontal resolution of 1\(sl43(\(->) are often extra wide. The default scaling is ems for the horizontally-oriented requests and functions \fBll\fR, \fBin\fR, \fBti\fR, \fBta\fR, \fBlt\fR, \fBpo\fR, \fBmc\fR, \fB\eh\fR, and \fB\el\fR; \fIV\^\fRs for the vertically-oriented requests and functions \fBpl\fR, \fBwh\fR, \fBch\fR, \fBdt\fR, \fBsp\fR, \fBsv\fR, \fBne\fR, \fBrt\fR, \fB\ev\fR, \fB\ex\fR, and \fB\eL\fR; \fBp\fR for the \fBvs\fR request; and \fBu\fR for the requests \fBnr\fR, \fBif\fR, and \fBie\fR. \fIAll\fR other requests ignore.2\|centimeters from the top of the page. .sc .tr && Numerical expressions. Wherever numerical input is expected an expression involving parentheses, the arithmetic operators \fB\(pl\fR, \fB\(mi\fR, \fB\(sl\fR, \fB\(**\fR, \fB%\fR (mod), and the logical operators \fB<\fR, \fB>\fR, \fB<\(eq\fR, \fB>\(eq\fR, \fB\(eq\fR (or \fB\(eq\(eq\fR), \fB&\fR\ (and), \fB:\fR\ (or) may be used. Except where controlled by parentheses, evaluation of expressions is left-to-right; there is no operator precedence. In the case sign format to register \fIR\fR (\fIc=\fB1\fR, \fBi\fR, \fBI\fR, \fBa\fR, \fBA\fR). .b1 \fB&rr\fI|R\fR - - - Remove register \fIR\fR. .mh Tabs, Leaders, and Fields .bt \fB&ta\fI|Nt|...\fR 0.8;|0.5in none E,\fBm\fR Tab settings; \fIleft\fR type, unless \fIt=\fBR\fR(right), \fBC\fR(centered). .b1 \fB&tc\fI|c\fR none none E Tab repetition character. .b1 \fB&lc\fI|c\fR \fB.\fR none E Leader repetition character. .b1 \fB&fc\fI|a|b\fR off off - Set field delimiter \fIa\fR and pad character \fIb\fR. .mh Input and if\fI|c|anything\fR - - If condition \fIc\fR true, accept \fIanything\fR as input, .b1 for multi-line use \fI\e{anything\|\e}\fR. .b1 \fB&if|!\fIc|anything\fR - - If condition \fIc\fR false, accept \fIanything\fR. .b1 \fB&if\fI|N|anything\fR - \fBu\fR If expression \fIN\fR > 0, accept \fIanything\fR. .b1 \fB&if|!\fIN|anything\fR - \fBu\fR If expression \fIN\fR \(<= 0, accept \fIanything\fR. .b1 \fB&if\fI|\|\'string1\|\'string2\|\'|anything\fR - If \fIstring1\fR identical to \fIstring2\fR, accept \fIanyical output. P Mode must be still or again in effect at the time of physical output. \fBv\fR,\fBp\fR,\fBm\fR,\fBu\fR Default scale indicator; if not specified, scale indicators are \fIignored\fR. .so cross .bp .so escapes .bp .so registers .in0 .fi 2 inch and a vertical resolution of 1\(sl144 inch. \*(NR internally uses 240 units\(slinch, corresponding to the least common multiple of the horizontal and vertical resolutions of various typewriter-like output devices. \*(TR rounds horizontal\(slvertical numerical parameter input to the actual horizontal\(slvertical resolution of the Graphic Systems typesetter. \*(NR similarly rounds numerical input to the actual resolution of the output device indicated by the \fB\(miT\fR option (default Model 37 Teletyp any scale indicators. When a number register containing an already appropriately scaled number is interpolated to provide numerical input, the unit scale indicator \fBu\fR may need to be appended to prevent an additional inappropriate default scaling. The number, \fIN\fR, may be specified in decimal-fraction form but the parameter finally stored is rounded to an integer number of basic units. .pg The \fIabsolute position\fR indicator \fB~\fR may be prepended to a number \fIN\fR to generate the distance to of certain requests, an initial \fB\(pl\fR or \fB\(mi\fR is stripped and interpreted as an increment or decrement indicator respectively. In the presence of default scaling, the desired scale indicator must be attached to \fIevery\fR number in an expression for which the desired and default scaling differ. For example, if the number register \fBx\fR contains 2 and the current point size is 10, then .br .tr &. .x1 .ftB \&.ll (4.25i\(pl\enxP\(pl3)\(sl2u .ftR .x2 will set the line length to 1\(sl2 the sum of 4.25 inches \(pl 2 picas \(pl 30 points. .sc Notation. Numerical parameters are indicated in this manual in two ways. \(+-\fIN\fR means that the argument may take the forms \fIN\fR, \(pl\fIN\fR, or \(mi\fIN\fR and that the corresponding effect is to set the affected parameter to \fIN\fR, to increment it by \fIN\fR, or to decrement it by \fIN\fR respectively. Plain \fIN\fR means that an initial algebraic sign is \fInot\fR an increment indicator, but merely the sign of \fIN\fR. Generally, unreasonable numericively or by their names (Table II). The \s-1ASCII\s+1 characters \fB@\fR, \fB#\fR, \fB"\fR, \fB\(aa\fR, \fB\(ga\fR, \fB<\fR, \fB>\fR, \fB\e\fR, \fB{\fR, \fB}\fR, \fB~\fR, \fB^\fR, and \fB\(ul\fR exist only on the Special Font and are printed as a 1-em space if that Font is not mounted. .pg .tr ~| \*(NR understands the entire \*(TR character set, but can in general print only \s-1ASCII\s+1 characters, additional characters as may be available on the output device, such characters as may be able to be constru Graphic Systems typesetter are 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, and 36. This is a range of 1\(sl12 inch to 1\(sl2 inch. The \fBps\fR request is used to change or restore the point size. Alternatively the point size may be changed between any two characters by imbedding a \fB\es\fIN\fR at the desired point to set the size to \fIN\fR, or a \fB\es\fI\(+-N\fR (1\(<=\fIN\fR\(<=9) to increment\(sldecrement the size by \fIN\fR; \fB\es0\fR restores the \fIprevious\fR size. Requested point size vch one twice, separated by \fIN\fR\^\(mi1 basic units. A reasonable value for \fIN\fR is 3 when the character size is in the vicinity of 10 points. If \fIN\fR is missing the embolden mode is turned off. The column heads above were printed with \fB.bd|I|3\fR. The mode must be still or again in effect when the characters are physically printed. Ignored in \*(NR. .bt \fB&bd|S|\fIF|N\fR off - P The characters in the Special Font will be emboldened whenever the current font is \fIF\fR. This manual was printed wiut 1\(sl27|inch from the left edge of the 8|inch wide, continuous roll paper. The physical limitations on \*(NR output are output-device dependent. .h1 .bt \fB&pl\fI|\(+-N\fR 11\|in 11\|in \fBv\fR Page length set to \fI\(+-N\fR. The internal limitation is about 75|inches in \*(TR and about 136|inches in \*(NR. The current page length is available in the \fB.p\fR register. .bt \fB&bp\fI|\(+-N\fR \fIN\(eq\fR1 - B*,\fBv\fR Begin page. .fn .xx *The use of "\ \fB\'\fR\ " as control character (instead of "\fB.\fRternal register (both associated with the current diversion level), or in register \fIR\fR, if given. See \fBrt\fR request. .bt \fB&rt\fI|\(+-N\fR none internal D,\fBv\fR Return \fIupward only\fR to a marked vertical place in the current diversion. If \fI\(+-N\fR (w.r.t. current place) is given, the place is \fI\(+-N\fR from the top of the page or diversion or, if \fIN\fR is absent, to a place marked by a previous \fBmk\fR. Note that the \fBsp\fR request (\(sc5.3) may be used in all cases instead of \fBrt\fal input is either ignored or truncated to a reasonable value. For example, most requests expect to set parameters to non-negative values; exceptions are \fBsp\fR, \fBwh\fR, \fBch\fR, \fBnr\fR, and \fBif\fR. The requests \fBps\fR, \fBft\fR, \fBpo\fR, \fBvs\fR, \fBls\fR, \fBll\fR, \fBin\fR, and \fBlt\fR restore the \fIprevious\fR parameter value in the \fIabsence\fR of an argument. .pg Single character arguments are indicated by single lower case letters and one/two character arguments are indicated by a paicted by overstriking or other combination, and those that can reasonably be mapped into other printable characters. The exact behavior is determined by a driving table prepared for each device. The characters \fB\'\fR, \fB\`\fR, and \fB\(ul\fR print as themselves. .sc Fonts. The default mounted fonts are Times Roman (\fBR\fR), Times Italic (\fBI\fR), Times Bold (\fBB\fR), and the Special Mathematical Font (\fBS\fR) on physical typesetter positions 1, 2, 3, and 4 respectively. These fonts are used in this doalues that are between two valid sizes yield the larger of the two. The current size is available in the \fB.s\fR register. \*(NR ignores type size control. .h1 * .fn .xx *Notes are explained at the end of the Summary and Index above. .ef .bt \fB&ps\fI|\(+-N\fR 10\|point previous E Point size set to \(+-\fIN\fR. Alternatively imbed \fB\es\fIN\fR or \fB\es\fI\(+-N\fR. Any positive size value may be requested; if invalid, the next larger valid size will result, with a maximum of 36. A paired sequence \(pl\fINth \fB.bd\|S\|B\|3\fR. The mode must be still or again in effect when the characters are physically printed. .bt \fB&ft|\fIF\fR Roman previous E Font changed to \fIF\fR. Alternatively, imbed \fB\ef\fIF\fR. The font name \fBP\fR is reserved to mean the previous font. .bt \fB&fp|\fIN|F\fR R,I,B,S ignored - Font position. This is a statement that a font named \fIF\fR is mounted on position \fIN\fR (1-4). It is a fatal error if \fIF\fR is not known. The phototypesetter has four fonts physically mounted. Each fo") suppresses the break function. .ef The current page is ejected and a new page is begun. If \fI\(+-N\fR is given, the new page number will be \fI\(+-N\fR. Also see request \fBns\fR. .bt \fB&pn\fI|\(+-N\fR \fIN\fR\(eq1 ignored - Page number. The next page (when it occurs) will have the page number \fI\(+-N\fR. A \fBpn\fR must occur before the initial pseudo-page transition to effect the page number of the first page. The current page number is in the \fB%\fR register. .bt \fB&po\fI|\(+-N\fR 0;|26\(sl27\|inR by spacing to the absolute place stored in a explicit register; e.|g. using the sequence \fB.mk|\fIR\fR ... \fB.sp|~\|\en\fIR\fBu\fR. .mh Text Filling, Adjusting, and Centering .sc Filling and adjusting. Normally, words are collected from input text lines and assembled into a output text line until some word doesn't fit. An attempt is then made the hyphenate the word in effort to assemble a part of it into the output line. The spaces between the words on the output line are then increased to spread out thr of lower case letters. Character string arguments are indicated by multi-character mnemonics. .mh Font and Character Size Control .sc Character set. The \*(TR character set consists of the Graphics Systems Commercial|II character set plus a Special Mathematical Font character set\(emeach having 102 characters. These character sets are shown in the attached Table|I. All \s-1ASCII\s+1 characters are included, with some on the Special Font. With three exceptions, the \s-1ASCII\s+1 characters are input as thecument. The \fIcurrent\fR font, initially Roman, may be changed (among the mounted fonts) by use of the \fBft\fR request, or by imbedding at any desired point either \fB\ef\fIx\fR, \fB\ef(\fIxx\fR, or \fB\ef\fIN\fR where \fIx\fR and \fIxx\fR are the name of a mounted font and \fIN\fR is a numerical font position. It is \fInot\fR necessary to change to the Special font; characters on that font are automatically handled. A request for a named but not-mounted font is \fIignored\fR. \*(TR can be informed that a\fR,\|\(mi\fIN\fR will work because the previous requested value is also remembered. Ignored in \*(NR. .bt \fB&ss\fI|N\fR 12\(sl36\|em ignored E Space-character size is set to \fIN\fR\(sl36\|ems. This size is the minimum word spacing in adjusted text. Ignored in \*(NR. .bt \fB&cs\|\fIF\|N\|M\fR off - P Constant character space (width) mode is set on for font \fIF\fR (if mounted); the width of every character will be taken to be \fIN\fR\(sl36 ems. If \fIM\fR is absent, the em is that of the character's pointnt consists of a film strip which can be mounted on a numbered quadrant of a wheel. The default mounting sequence assumed by \*(TR is R, I, B, and S on positions 1, 2, 3 and 4. .mh Page control .pg Top and bottom margins are \fInot\fR automatically provided; it is conventional to define two \fImacros\fR and to set \fItraps\fR for them at vertical positions 0 (top) and \fI\(miN\fR (\fIN\fR from the bottom). See \(sc7 and Tutorial Examples \(scT2. A pseudo-page transition onto the \fIfirst\fR page occurs eith\(dg previous \fBv\fR Page offset. .fn .xx \(dgValues separated by ";" are for \*(NR and \*(TR respectively. .ef The current \fIleft margin\fR is set to \fI\(+-N\fR. The \*(TR initial value provides about 1|inch of paper margin including the physical typesetter margin of 1\(sl27|inch. In \*(TR the maximum (line-length)+(page-offset) is about 7.54 inches. See \(sc6. The current page offset is available in the \fB.o\fR register. .bt \fB&ne\fI|N\fR - \fIN\(eq\fR1\|\fIV\fR D,\fBv\fR Need \fIN\fR vertical space.e line to the current \fIline length\fR minus any current \fIindent\fR. A \fIword\fR is any string of characters delimited by the \fIspace\fR character or the beginning/end of the input line. Any adjacent pair of words that must be kept together (neither split across output lines nor spread apart in the adjustment process) can be tied together by separating them with the \fIunpaddable space\fR character "\fB\e\ \ \fR" (backslash-space). The adjusted word spacings are uniform in \*(TR and the minimum interwomselves, and non-\s-1ASCII\s+1 characters are input in the form \fB\e(\fIxx\fR where \fIxx\fR is a two-character name given in the attached Table|II. The three \s-1ASCII\s+1 exceptions are mapped as follows: .TS center box; cs|cs cc|cc cl|cl. \s-1ASCII\s+1 Input Printed by \*(TR Character Name Character Name _ \' acute accent ' close quote \` grave accent ` open quote \(mi minus - hyphen .TE .tr ~~ The characters \fB\'\fR, \fB\`\fR, and \fB\-\fR may be input by \fB\e\'\fR, \fB\e\`\fR, and \fB\e\-\fR respectny particular font is mounted by use of the \fBfp\fR request. The list of known fonts is installation dependent. In the subsequent discussion of font-related requests, \fIF\fR represents either a one\(sltwo-character font name or the numerical font position, 1-4. The current font is available (as numerical position) in the read-only number register \fB.f\fR. .pg \*(NR understands font control and normally underlines Italic characters (see \(sc10.5). .sc Character size. Character point sizes available on the size; if \fIM\fR is given, the em is \fIM\fR-points. All affected characters are centered in this space, including those with an actual width larger than this space. Special Font characters occurring while the current font is \fIF\fR are also so treated. If \fIN\fR is absent, the mode is turned off. The mode must be still or again in effect when the characters are physically printed. Ignored in \*(NR. .bt \fB&bd\fI|F|N\fR off - P The characters in font \fIF\fR will be artificially emboldened by printing eaer when the first \fIbreak\fR occurs or when the first \fInon-diverted\fR text processing occurs. Arrangements for a trap to occur at the top of the first page must be completed before this transition. In the following, references to the \fIcurrent diversion\fR (\(sc7.4) mean that the mechanism being described works during both ordinary and diverted output (the former considered as the top diversion level). .pg The useable page width on the Graphic Systems phototypesetter is about 7.54|inches, beginning abo If the distance, \fID\fR, to the next trap position (see \(sc7.5) is less than \fIN\fR, a forward vertical space of size \fID\fR occurs, which will spring the trap. If there are no remaining traps on the page, \fID\fR is the distance to the bottom of the page. If \fID\|<\|V\fR, another line could still be output and spring the trap. In a diversion, \fID\fR is the distance to the \fIdiversion trap\fR, if any, or is very large. .bt \fB&mk\fI|R\fR none internal D Mark the \fIcurrent\fR vertical place in an inrd spacing can be controlled with the \fBss\fR request (\(sc2). In \*(NR, they are normally nonuniform because of quantization to character-size spaces; however, the command line option \fB\-e\fR causes uniform spacing with full output device resolution. Filling, adjustment, and hyphenation (\(sc13) can all be prevented or controlled. The \fItext length\fR on the last line output is available in the \fB.n\fR register, and text base-line position on the page for this line is in the \fBnl\fR register. The text base-line high-water mark (lowest place) on the current page is in the \fB.h\fR register. .pg An input text line ending with \fB.\fR\^, \fB?\fR, or \fB!\fR is taken to be the end of a \fIsentence\fR, and an additional space character is automatically provided during filling. Multiple inter-word space characters found in the input are retained, except for trailing spaces; initial spaces also cause a \fIbreak\fR. .pg When filling is in effect, a \fB\ep\fR may be imbedded or attached to a word to cause a \fIed directly to output lines \fIwithout regard\fR for the current line length. .bt \fB&ad\fI|c\fR adj,both adjust E \ Line adjustment is begun. If fill mode is not on, adjustment will be deferred until fill mode is back on. If the type indicator \fIc\fR is present, the adjustment type is changed as shown in the following table. .TS center box; c|c c|l. Indicator Adjust Type _ \fBl\fR adjust left margin only \fBr\fR adjust right margin only \fBc\fR center \fBb\fR or \fBn\fR adjust both margins absent unchanges around their parameter (here \fB\'\fR\|), the delimiter choice is arbitrary, except that it can't look like the continuation of a number expression for \fIN\fR. If \fIN\fR is negative, the output line containing the word will be preceded by \fIN\fR extra vertical space; if \fIN\fR is positive, the output line containing the word will be followed by \fIN\fR extra vertical space. If successive requests for extra space apply to the same line, the maximum values are used. The most recently utilized post-line write any still remembered \fIN\fR. .bt \fB&os\fR - - - Output saved vertical space. No-space mode has \fIno\fR effect. Used to finally output a block of vertical space requested by an earlier \fBsv\fR request. .bt \fB&ns\fR space - D No-space mode turned on. When on, the no-space mode inhibits \fBsp\fR requests and \fBbp\fR requests \fIwithout\fR a next page number. The no-space mode is turned off when a line of output occurs, or with \fBrs\fR. .bt \fB&rs\fR space - D Restore spacing. The no-space mode is q\^\fR0 previous B,E,\fBm\fR Indent is set to \fI\(+-N\fR. The indent is prepended to each output line. .bt \fB&ti\fI|\(+-N\fR - ignored B,E,\fBm\fR Temporary indent. The \fInext\fR output text line will be indented a distance \fI\(+-N\fR with respect to the current indent. The resulting total indent may not be negative. The current indent is not changed. .mh Macros, Strings, Diversion, and Position Traps .sc Macros and strings. A \fImacro\fR is a named set of arbitrary \fIlines\fR that may be invoked by naminated. \*+ Comments indicated by \fB\e"\fR are eliminated. \*+ \fB\et\fR and \fB\ea\fR are interpreted as \s-1ASCII\s+1 horizontal tab and \s-1SOH\s+1 respectively (\(sc9). \*+ \fB\e\e\fR is interpreted as \fB\e\fR. \*+ \fB\e.\fR is interpreted as "\fB.\fR". .x2 These interpretations can be suppressed by prepending a \fB\e\fR. For example, since \fB\e\e\fR maps into a \fB\e\fR, \fB\e\en\fR will copy as \fB\en\fR which will be interpreted as a number register indicator when the macro or string is reread. .break\fR at the \fIend\fR of the word and have the resulting output line \fIspread out\fR to fill the current line length. .pg .tr && A text input line that happens to begin with a control character can be made to not look like a control line by prefacing it with the non-printing, zero-width filler character \fB\e&\fR. Still another way is to specify output translation of some convenient character into the control character using \fBtr\fR (\(sc10.5). .tr &. .sc Interrupted text. The copying of a input line d .TE .bt \fB&na\fR adjust - E Noadjust. Adjustment is turned off; the right margin will be ragged. The adjustment type for \fBad\fR is not changed. Output line filling still occurs if fill mode is on. .bt \fB&ce\fI|N\fR off \fIN\fR\(eq1 B,E Center the next \fIN\fR input text lines within the current (line-length minus indent). If \fIN\fR\(eq\^0, any residual count is cleared. A break occurs after each of the \fIN\fR input lines. If the input line is too long, it will be left adjusted. .mh Vertical Spacing extra line-space is available in the \fB.a\fR register. .sc Blocks of vertical space. A block of vertical space is ordinarily requested using \fBsp\fR, which honors the \fIno-space\fR mode and which does not space \fIpast\fR a trap. A contiguous block of vertical space may be reserved using \fBsv\fR. .h1 .bt \fB&vs\fI\|N\fR 1\(sl6in;12pts previous E,\fBp\fR Set vertical base-line spacing size \fIV\fR. Transient \fIextra\fR vertical space available with \fB\ex\fI\'N\|\|\'\fR (see above). .bt \fB&ls\fI\|N\fR turned off. .bt Blank|text|line. - B Causes a break and output of a blank line exactly like \fBsp|1\fR. me or with a \fItrap\fR. A \fIstring\fR is a named string of \fIcharacters\fR, \fInot\fR including a newline character, that may be interpolated by name at any point. Request, macro, and string names share the \fIsame\fR name list. Macro and string names may be one or two characters long and may usurp previously defined request, macro, or string names. Any of these entities may be renamed with \fBrn\fR or removed with \fBrm\fR. Macros are created by \fBde\fR and \fBdi\fR, and appended to by \fBam\fR and \fBsc Arguments. When a macro is invoked by name, the remainder of the line is taken to contain up to nine arguments. The argument separator is the space character, and arguments may be surrounded by double-quotes to permit imbedded space characters. Pairs of double-quotes may be imbedded in double-quoted arguments to represent a single double-quote. If the desired arguments won't fit on a line, a concealed newline may be used to continue on the next line. .pg When a macro is invoked the \fIinput level\fR is \in \fInofill\f (non-fill) mode can be \fIinterrupted\fR by terminating the partial line with a \fB\ec\fR. The \fInext\fR encountered input text line will be considered to be a continuation of the same line of input text. Similarly, a word within \fIfilled\fR text may be interrupted by terminating the word (and line) with \fB\ec\fR; the next encountered text will be taken as a continuation of the interrupted word. If the intervening control lines cause a break, any partial line will be forced out along with .sc Base-line spacing. The vertical spacing \fI(V)\fR between the base-lines of successive output lines can be set using the \fBvs\fR request with a resolution of 1\(sl144\|inch\|\(eq\|1\(sl2|point in \*(TR, and to the output device resolution in \*(NR. \fIV\fR must be large enough to accommodate the character sizes on the affected output lines. For the common type sizes (9-12 points), usual typesetting practice is to set \fIV\fR to 2\ points greater than the point size; \*(TR default is 10-point type on a \fIN\(eq\^\fR1 previous E \fILine\fR spacing set to \fI\(+-N\fR. \fIN\(mi\fR1 \fIV\fR\^s \fI(blank lines)\fR are appended to each output text line. Appended blank lines are omitted, if the text or previous appended blank line reached a trap position. .bt \fB&sp\fI|N\fR - \fIN\fR\(eq1\fIV\fR B,\fBv\fR Space vertically in \fIeither\fR direction. If \fIN\fR is negative, the motion is \fIbackward\fR (upward) and is limited to the distance to the top of the page. Forward (downward) motion is truncated to the dis.tr | .rm mx .br .mh Line Length and Indenting .pg The maximum line length for fill mode may be set with \fBll\fR. The indent may be set with \fBin\fR; an indent applicable to \fIonly\fR the \fInext\fR output line may be set with \fBti\fR. The line length includes indent space but \fInot\fR page offset space. The line-length minus the indent is the basis for centering with \fBce\fR. The effect of \fBll\fR, \fBin\fR, or \fBti\fR is delayed, if a partially collected line exists, until after that line is outpuda\fR; \fBdi\fR and \fBda\fR cause normal output to be stored in a macro. Strings are created by \fBds\fR and appended to by \fBas\fR. A macro is invoked in the same way as a request; a control line beginning \fB.\fIxx\fR will interpolate the contents of macro \fIxx\fR. The remainder of the line may contain up to nine \fIarguments\fR. The strings \fIx\fR and \fIxx\fR are interpolated at any desired point with \fB\e\(**\fIx\fR and \fB\e\(**(\fIxx\fR respectively. String references and macro invocations may b any partial word. .h1 .bt \fB&br\fR - - B Break. The filling of the line currently being collected is stopped and the line is output without adjustment. Text lines beginning with space characters and empty text lines (blank lines) also cause a break. .bt .lg0 \fB&fi\fR \(fill|on - B,E Fill subsequent output lines. .lg The register \fB.u\fR is 1 in fill mode and 0 in nofill mode. .bt \fB&nf\fR fill|on - B,E Nofill. Subsequent output lines are \fIneither\fR filled \fInor\fR adjusted. Input text lines are copi12-point spacing (as in this document). The current \fIV\fR is available in the \fB.v\fR register. Multiple-\fIV\|\fR line separation (e.\|g. double spacing) may be requested with \fBls\fR. .sc Extra line-space. If a word contains a vertically tall construct requiring the output line containing it to have extra vertical space before and\(slor after it, the \fIextra-line-space\fR function \fB\ex\fI\'N\|\|\'\fR can be imbedded in or attached to that word. In this and other functions having a pair of delimitertance to the nearest trap. If the no-space mode is on, no spacing occurs (see \fBns\fR, and \fBrs\fR below). .bt \fB&sv\fI|N\fR - \fIN\(eq\fR1\fIV\fR \fBv\fR Save a contiguous vertical block of size \fIN\fR. If the distance to the next trap is greater than \fIN\fR, \fIN\fR vertical space is output. No-space mode has \fIno\fR effect. If this distance is less than \fIN\fR, no vertical space is immediately output, but \fIN\fR is remembered for later output (see \fBos\fR). Subsequent \fBsv\fR requests will overt. In fill mode the length of text on an output line is less than or equal to the line length minus the indent. The current line length and indent are available in registers \fB.l\fR and \fB.i\fR respectively. The length of \fIthree-part titles\fR produced by \fBtl\fR (see \(sc14) is \fIindependently\fR set by \fBlt\fR. .h1 .bt \fB&ll\fI|\(+-N\fR 6.5\|in previous E,\fBm\fR Line length is set to \(+-\fIN\fR. In \*(TR the maximum (line-length)+(page-offset) is about 7.54 inches. .bt \fB&in\fI|\(+-N\fR \fIN\(ee nested. .sc Copy mode input interpretation. During the definition and extension of strings and macros (not by diversion) the input is read in \fIcopy mode\fR. The input is copied without interpretation \fIexcept\fR that: .x1 .ds + \v'-.1m'\s-4\(bu\s+4\v'+.1m' \*+ The contents of number registers indicated by \fB\en\fR are interpolated. \*+ Strings indicated by \fB\e\(**\fR are interpolated. \*+ Arguments indicated by \fB\e$\fR are interpolated. \*+ Concealed newlines indicated by \fB\e\fR(newline) are elifIpushed down\fR and any arguments available at the previous level become unavailable until the macro is completely read and the previous level is restored. A macro's own arguments can be interpolated at \fIany\fR point within the macro with \fB\e$\fIN\fR, which interpolates the \fIN\fR\^th argument (1\(<=\fIN\fR\^\(<=9). If an invoked argument doesn't exist, a null string results. For example, the macro \fIxx\fR may be defined by .x1 .ftB .ta .75i &de xx \e"begin definition Today is \e\e$1 the \e\e$2. &. \e"end definition .ftR .x2 and called by .x1 .ftB &xx Monday 14th .ftR .x2 to produce the text .x1 .ftB Today is Monday the 14th. .ftR .x2 Note that the \fB\e$\fR was concealed in the definition with a prepended \fB\e\fR. The number of currently available arguments is in the \fB.$\fR register. .pg No arguments are available at the top (non-macro) level in this implementation. Because string referencing is implemented as a input-level push down, no arguments are available from \fIwithin\fR a string. No argumeciated macro, no-space mode, the internally-saved marked place (see \fBmk\fR and \fBrt\fR), the current vertical place (\fB.d\fR register), the current high-water text base-line (\fB.h\fR register), and the current diversion name (\fB.z\fR register). .sc Traps. Three types of trap mechanisms are available\(empage traps, a diversion trap, and an input-line-count trap. Macro-invocation traps may be planted using \fBwh\fR at any page position including the top. This trap position may be changed using \fBch\fR.he absence of \fIyy\fR, the definition is terminated by a line beginning with "\fB..\fR". A macro may contain \fBde\fR requests provided the terminating macros differ or the contained definition terminator is concealed. \&"\fB..\fR" can be concealed as \fB\e\e..\fR which will copy as \fB\e..\fR and be reread as "\fB..\fR". .bt \fB&am\fI|xx|yy\fR - \fI.yy=\fB..\fR - Append to macro (append version of \fBde\fR). .bt \fB&ds\fI|xx|string\fR - ignored - Define a string \fIxx\fR containing \fIstring\fR. Any initie \fIcurrent\fR diversion to invoke macro \fIxx\fR. Another \fBdt\fR will redefine the diversion trap. If no arguments are given, the diversion trap is removed. .bt \fB&it\fI|N|xx\fR - off E Set an input-line-count trap to invoke the macro \fIxx\fR after \fIN\fR lines of \fItext\fR input have been read (control or request lines don't count). The text may be in-line text or text interpolated by inline or trap-invoked macros. .bt \fB&em\fI|xx\fR none none - The macro \fIxx\fR will be invoked when all input haemented by \fIM\fR \fIN+M\fR \fB\en\-(\fIxx\fR \fIxx\fR decremented by \fIM\fR \fIN\-M\fR .TE When interpolated, a number register is converted to decimal (default), decimal with leading zeros, lower-case Roman, upper-case Roman, lower-case sequential alphabetic, or upper-case sequential alphabetic according to the format specified by \fBaf\fR. .h1 .bt \fB&nr\fI|R|\(+-N|M\fR - \fBu\fR \ The number register \fIR\fR is assigned the value \fI\(+-N\fR with respect to the previous value, if any. The increment foce of repeated character or motion. There are three types of internal tab stops\(em\ \fIleft\fR adjusting, \fIright\fR adjusting, and \fIcentering\fR. In the following table: \fID\fR is the distance from the current position on the \fIinput\fR line (where a tab or leader was found) to the next tab stop; \fInext-string\fR consists of the input characters following the tab (or leader) up to the next tab (or leader) or end of line; and \fIW\fR is the width of \fInext-string\fR. .TS center box; c2|c2|c c2|c2|c nts are available within a trap-invoked macro. .pg Arguments are copied in \fIcopy mode\fR onto a stack where they are available for reference. The mechanism does not allow an argument to contain a direct reference to a \fIlong\fR string (interpolated at copy time) and it is advisable to conceal string references (with an extra \fB\e\fR\|) to delay interpolation until argument reference time. .sc Diversions. Processed output may be diverted into a macro for purposes such as footnote processing (see Tutorial Trap positions at or below the bottom of the page have no effect unless or until moved to within the page or rendered effective by an increase in page length. Two traps may be planted at the \fIsame\fR position only by first planting them at different positions and then moving one of the traps; the first planted trap will conceal the second unless and until the first one is moved (see Tutorial Examples \(scT5). If the first one is moved back, it again conceals the second trap. The macro associated with a pal double-quote in \fIstring\fR is stripped off to permit initial blanks. .bt \fB&as\fI|xx|string\fR - ignored - Append \fIstring\fR to string \fIxx\fR (append version of \fBds\fR). .bt \fB&rm\fI|xx\fR - ignored - Remove request, macro, or string. The name \fIxx\fR is removed from the name list and any related storage space is freed. Subsequent references will have no effect. .bt \fB&rn\fI|xx|yy\fR - ignored - Rename request, macro, or string \fIxx\fR to \fIyy\fR. If \fIyy\fR exists, it is first removed. .bs ended. The effect is the same as if the contents of \fIxx\fR had been at the end of the last file processed. .mh Number Registers .pg A variety of parameters are available to the user as predefined, named \fInumber registers\fR (see Summary and Index, page 7). In addition, the user may define his own named registers. Register names are one or two characters long and \fIdo not\fR conflict with request, macro, or string names. Except for certain predefined read-only registers, a number register can be read,r auto-incrementing is set to \fIM\fR. .bt \fB&af\fI|R|c\fR arabic - - Assign format \fIc\fR to register \fIR\fR. The available formats are: .TS center box; c2|c c2|c c2|l. Numbering Format Sequence _ \fB1\fR 0,1,2,3,4,5,... \fB001\fR 000,001,002,003,004,005,... \fBi\fR 0,i,ii,iii,iv,v,... \fBI\fR 0,I,II,III,IV,V,... \fBa\fR 0,a,b,c,...,z,aa,ab,...,zz,aaa,... \fBA\fR 0,A,B,C,...,Z,AA,AB,...,ZZ,AAA,... .TE An arabic format having \fIN\fR digits specifies a field width of \fIN\fR digits (example 2 above). Thc2|c2|l. Tab Length of motion or Location of type repeated characters \fInext-string\fR _ Left \fID\fR Following \fID\fR Right \fID\-W\fR Right adjusted within \fID\fR Centered \fID\-W\(sl\fR2 Centered on right end of \fID\fR .TE The length of generated motion is allowed to be negative, but that of a repeated character string cannot be. Repeated character strings contain an integer number of characters, and any residual distance is prepended as motion. Tabs or leaders found after the last tab stop are ignor \(scT5) or determining the horizontal and vertical size of some text for conditional changing of pages or columns. A single diversion trap may be set at a specified vertical position. The number registers \fBdn\fR and \fBdl\fR respectively contain the vertical and horizontal size of the most recently ended diversion. Processed text that is diverted into a macro retains the vertical size of each of its lines when reread in \fInofill\fR mode regardless of the current \fIV\fR. Constant-spaced (\fBcs\fR) or emage trap is automatically invoked when a line of text is output whose vertical size \fIreaches\fR or \fIsweeps past\fR the trap position. Reaching the bottom of a page springs the top-of-page trap, if any, provided there is a next page. The distance to the next trap position is available in the \fB.t\fR register; if there are no traps between the current position and the bottom of the page, the distance returned is the distance to the page bottom. .pg A macro-invocation trap effective in the current diversit \fB&di|\fIxx\fR - end D Divert output to macro \fIxx\fR. Normal text processing occurs during diversion except that page offsetting is not done. The diversion ends when the request \fBdi\fR or \fBda\fR is encountered without an argument; extraneous requests of this type should not appear when nested diversions are being used. .bt \fB&da|\fIxx\fR - end D Divert, appending to \fIxx\fR (append version of \fBdi\fR). .bt \fB&wh\fI|N|xx\fR - - \fBv\fR Install a trap to invoke \fIxx\fR at page position \fIN;\fR written, automatically incremented or decremented, and interpolated into the input in a variety of formats. One common use of user-defined registers is to automatically number sections, paragraphs, lines, etc. A number register may be used any time numerical input is expected or desired and may be used in numerical \fIexpressions\fR (\(sc1.4). .pg Number registers are created and modified using \fBnr\fR, which specifies the name, numerical value, and the auto-increment size. Registers are also modified, ife read-only registers and the \fIwidth\fR function (\(sc11.2) are always arabic. .bt \fB&rr\fI|R\fR - ignored - Remove register \fIR\fR. If many registers are being created dynamically, it may become necessary to remove no longer used registers to recapture internal storage space for newer registers. ed, but may be used as \fInext-string\fR terminators. .pg Tabs and leaders are not interpreted in \fIcopy mode\fR. \fB\et\fR and \fB\ea\fR always generate a non-interpreted tab and leader respectively, and are equivalent to actual tabs and leaders in \fIcopy mode\fR. .sc Fields. A \fIfield\fR is contained between a \fIpair\fR of \fIfield delimiter\fR characters, and consists of sub-strings separated by \fIpadding\fR indicator characters. The field length is the distance on the \fIinput\fR line from the posiboldened (\fBbd\fR) text that is diverted can be reread correctly only if these modes are again or still in effect at reread time. One way to do this is to imbed in the diversion the appropriate \fBcs\fR or \fBbd\fR requests with the \fItransparent\fR mechanism described in \(sc10.6. .pg Diversions may be nested and certain parameters and registers are associated with the current diversion level (the top non-diversion level may be thought of as the 0th diversion level). These are the diversion trap and assoon may be planted using \fBdt\fR. The \fB.t\fR register works in a diversion; if there is no subsequent trap a \fIlarge\fR distance is returned. For a description of input-line-count traps, see \fBit\fR below. .h1 .bt \fB&de\fI|xx|yy\fR - \fI.yy=\fB..\fR - Define or redefine the macro \fIxx\fR. The contents of the macro begin on the next input line. Input lines are copied in \fIcopy mode\fR until the definition is terminated by a line beginning with \fB.\fIyy\fR, whereupon the macro \fIyy\fR is called. In ta \fInegative N\fR will be interpreted with respect to the page \fIbottom\fR. Any macro previously planted at \fIN\fR is replaced by \fIxx\fR. A zero \fIN\fR refers to the \fItop\fR of a page. In the absence of \fIxx\fR, the first found trap at \fIN\fR, if any, is removed. .bt \fB&ch\fI|xx|N\fR - - \fBv\fR Change the trap position for macro \fIxx\fR to be \fIN\fR. In the absence of \fIN\fR, the trap, if any, is removed. .bt \fB&dt\fI|N|xx\fR - off D,\fBv\fR Install a diversion trap at position \fIN\fR in th accessed with an auto-incrementing sequence. If the registers \fIx\fR and \fIxx\fR both contain \fIN\fR and have the auto-increment size \fIM\fR, the following access sequences have the effect shown: .TS center box; c2|c2|c c2|c2|c2 l2|c2|c2 l2|c2|c2 l2|l2|c2. Effect on Value Sequence Register Interpolated _ \fB\en\fIx\fR none \fIN\fR \fB\en(\fIxx\fR none \fIN\fR \fB\en+\fIx\fR \fIx\fR incremented by \fIM\fR \fIN+M\fR \fB\en\-\fIx\fR \fIx\fR decremented by \fIM\fR \fIN\-M\fR \fB\en+(\fIxx\fR \fIxx\fR incr.tr | .rm mx .mh Tabs, Leaders, and Fields .sc Tabs and leaders. The \s-1ASCII\s+1 horizontal tab character and the \s-1ASCII\s+1 \s-1SOH\s+1 (hereafter known as the \fIleader\fR character) can both be used to generate either horizontal motion or a string of repeated characters. The length of the generated entity is governed by internal \fItab stops\fR specifiable with \fBta\fR. The default difference is that tabs generate motion and leaders generate a string of periods; \fBtc\fR and \fBlc\fR offer the choition where the field begins to the next tab stop. The difference between the total length of all the sub-strings and the field length is incorporated as horizontal padding space that is divided among the indicated padding places. The incorporated padding is allowed to be negative. For example, if the field delimiter is \fB#\fR and the padding indicator is \fB^\fR, \fB#^\fIxxx\fB^\fIright\|\fB#\fR specifies a right-adjusted string with the string \fIxxx\fR centered in the remaining space. .h1 .bt \fB&ta\fI|N|...\fR 0.8;|0.5in none E,\fBm\fR \ Set tab stops and types. \fIt=\fBR\fR, right adjusting; \fIt=\fBC\fR, centering; \fIt\fR absent, left adjusting. \*(TR tab stops are preset every 0.5in.; \*(NR every 0.8in. The stop values are separated by spaces, and a value preceded by \fB+\fR is treated as an increment to the previous stop value. .bt \fB&tc\fI|c\fR none none E \ The tab repetition character becomes \fIc\fR, or is removed specifying motion. .bt \fB&lc\fI|c\fR \fB.\fR none E \ The leader repetition charaven in the Summary and Index on page 6. \fB\e\fR should not be confused with the \s-1ASCII\s+1 control character \s-1ESC\s+1 of the same name. The escape character \fB\e\fR can be input with the sequence \fB\e\e\fR. The escape character can be changed with \fBec\fR, and all that has been said about the default \fB\e\fR becomes true for the new escape character. \fB\ee\fR can be used to print whatever the current escape character is. If necessary or convenient, the escape mechanism may be turned off with \fBt-device-dependent subset of \fIreasonable\fR characters. .h1 .bt \fB&ul\fI|N\fR off \fIN\(eq\fR1 E \ Underline in \*(NR (italicize in \*(TR) the next \fIN\fR input text lines. Actually, switch to \fIunderline\fR font, saving the current font for later restoration; \fIother\fR font changes within the span of a \fBul\fR will take effect, but the restoration will undo the last change. Output generated by \fBtl\fR (\(sc14) \fIis\fR affected by the font change, but does \fInot\fR decrement \fIN\fR. If \fIN\fR\^\fR to \fIoutput\fR time. .sc Transparent throughput. An input line beginning with a \fB\e!\fR is read in \fIcopy mode\fR and \fItransparently\fR output (without the initial \fB\e!\fR); the text processor is otherwise unaware of the line's presence. This mechanism may be used to pass control information to a post-processor or to imbed control lines in a macro created by a diversion. .sc Comments and concealed newlines. An uncomfortably long input line that must stay one line (e. g. a string definition, or n l2|l2|l2||l2|ls2. \fB\*X\eu\fR \(12 em up \(12 line up \fB\*X\e0\fR Digit-size space .TC l2|l2|l2||_2|_2_2. \fB\*X\ed\fR \(12 em down \(12 line down x x x .TC l2|l2|l2||l2|l2|l2. \fB\*X\er\fR 1 em up 1 line up \fB\*X\e\||\fR 1\(sl6 em space ignored \fB\*X\e^\fR 1\(sl12 em space ignored .sp.4 .TE .rm X .tr | As an example, \fBE\s-2\v'-.4m'2\v'.4m'\s+2\fR could be generated by the sequence \fBE\es\-2\ev\'\-0.4m\'2\ev\'0.4m\'\es+2\fR; it should be noted in this example that the 0.4|em vertical motions are erstriking. Automatically centered overstriking of up to nine characters is provided by the \fIoverstrike\fR function \fB\eo\'\fIstring\fB\|\'\fR. The characters in \fIstring\fR overprinted with centers aligned; the total width is that of the widest character. \fIstring\fR should \fInot\fR contain local vertical motion. As examples, \fB\eo\'e\e\'\'\fR produces \fB\o'e\''\fR, and \fB\eo\'\e(mo\e(sl\'\fR produces \fB\o'\(mo\(sl'\fR. .sc Zero-width characters. The function \fB\ez\fIc\fR will output \fIc\fR witcter becomes \fIc\fR, or is removed specifying motion. .bt \fB&fc\fI|a|b\fR off off - \ The field delimiter is set to \fIa\fR; the padding indicator is set to the \fIspace\fR character or to \fIb\fR, if given. In the absence of arguments the field mechanism is turned off. .mh Input and Output Conventions and Character Translations .sc Input character translations. Ways of inputting the graphic character set were discussed in \(sc2.1. The \s-1ASCII\s+1 control characters horizontal tab (\(sc9.1), \s-1SOH\s+1eo\fR, and restored with \fBec\fR. .h1 .bt \fB&ec\fI|c\fR \fB\e\fR \fB\e\fR - \ Set escape character to \fB\e\fR, or to \fIc\fR, if given. .bt \fB&eo\fR on - - Turn escape mechanism off. .sc Ligatures. .lg0 Five ligatures are available in the current \*(TR character set \(em \fB\(fi\fR, \fB\(fl\fR, \fB\(ff\fR, \fB\(Fi\fR, and \fB\(Fl\fR. They may be input (even in \*(NR) by \fB\e(fi\fR, \fB\e(fl\fR, \fB\e(ff\fR, \fB\e(Fi\fR, and \fB\e(Fl\fR respectively. .lg The ligature mode is normally on in \*(TR, and \f>\^1, there is the risk that a trap interpolated macro may provide text lines within the span; environment switching can prevent this. .bt \fB&cu\fI|N\fR off \fIN\(eq\fR1 E \ A variant of \fBul\fR that causes \fIevery\fR character to be underlined in \*(NR. Identical to \fBul\fR in \*(TR. .bt \fB&uf\fI|F\fR Italic Italic - \ Underline font set to \fIF\fR. In \*(NR, \fIF\fR may \fInot\fR be on position 1 (initially Times Roman). .sc Control characters. Both the control character \fB.\fR and the \fIno-break\fofilled text) can be split into many physical lines by ending all but the last one with the escape \fB\e\fR. The sequence \fB\e\fR(newline) is \fIalways\fR ignored\(em\ except in a comment. Comments may be imbedded at the \fIend\fR of any line by prefacing them with \fB\e"\fR. The newline at the end of a comment cannot be concealed. A line beginning with \fB\e"\fR will appear as a blank line and behave like \fB.sp|1\fR; a comment can be on a line by itself by beginning the line with \fB.\e"\fR. .mh Local Hoat the smaller size. .sc Width Function. The \fIwidth\fR function \fB\ew\'\fIstring\fB\|\'\fR generates the numerical width of \fIstring\fR (in basic units). Size and font changes may be safely imbedded in \fIstring\fR, and will not affect the current environment. For example, \&\fB.ti|\-\\w\'1.|\'u\fR could be used to temporarily indent leftward a distance equal to the size of the string "\fB1.|\fR". .pg The width function also sets three number registers. The registers \fBst\fR and \fBsb\fR are set respechout spacing over it, and can be used to produce left-aligned overstruck combinations. As examples, \fB\ez\e(ci\e(pl\fR will produce \fB\z\(ci\(pl\fR, and \fB\e(br\ez\e(rn\e(ul\e(br\fR will produce the smallest possible constructed box \fB\(br\z\(rn\(ul\(br\fR\|. .sc Large Brackets. The Special Mathematical Font contains a number of bracket construction pieces (\|\|\(lt\|\|\(lb\|\|\(rt\|\|\(rb\|\|\(lk\|\|\(rk\|\|\(bv\|\|\(lf\|\|\(rf\|\|\(lc\|\|\(rc\|\|) that can be combined into various bracket styles. The (\(sc9.1), and backspace (\(sc10.3) are discussed elsewhere. The newline delimits input lines. In addition, \s-1STX\s+1, \s-1ETX\s+1, \s-1ENQ\s+1, \s-1ACK\s+1, and \s-1BEL\s+1 are accepted, and may be used as delimiters or translated into a graphic with \fBtr\fR (\(sc10.5). \fIAll\fR others are ignored. .pg The \fIescape\fR character \fB\e\fR introduces \fIescape sequences\fR\(em\ causes the following character to mean another character, or to indicate some function. A complete list of such sequences is giIautomatically\fR invokes ligatures during input. .h1 .bt \fB&lg\fI|N\fR off;|on on - Ligature mode is turned on if \fIN\fR is absent or non-zero, and turned off if \fIN\(eq\^\fR0. If \fIN\fR\(eq\^2, only the two-character ligatures are automatically invoked. Ligature mode is inhibited for request, macro, string, register, or file names, and in \fIcopy mode\fR. No effect in \*(NR. .sc Backspacing, underlining, overstriking, etc. Unless in \fIcopy mode\fR, the \s-1ASCII\s+1 backspace character is replaced bR control character \fB\'\fR may be changed, if desired. Such a change must be compatible with the design of any macros used in the span of the change, and particularly of any trap-invoked macros. .h1 .bt \fB&cc\fI|c\fR \fB.\fR \fB.\fR E \ The basic control character is set to \fIc\fR, or reset to "\fB.\fR". .bt \fB&c2\fI|c\fR \fB\' \'\fR E The \fInobreak\fR control character is set to \fIc\fR, or reset to "\fB\'\fR". .sc Output translation. One character can be made a stand-in for another character using \rizontal and Vertical Motions, and the Width Function .sc Local Motions. The functions \fB\ev\'\fIN\fB\|\'\fR and \fB\eh\'\fIN\fB\|\'\fR can be used for \fIlocal\fR vertical and horizontal motion respectively. The distance \fIN\fR may be negative; the \fIpositive\fR directions are \fIrightward\fR and \fIdownward\fR. A \fIlocal\fR motion is one contained \fIwithin\fR a line. To avoid unexpected vertical dislocations, it is necessary that the \fInet\fR vertical local motion within a word in filled text and ottively to the highest and lowest extent of \fIstring\fR relative to the baseline; then, for example, the total \fIheight\fR of the string is \fB\en(stu\-\en(sbu\fR. In \*(TR the number register \fBct\fR is set to a value between 0|and|3: 0 means that all of the characters in \fIstring\fR were short lower case characters without descenders (like \fBe\fR); 1 means that at least one character has a descender (like \fBy\fR); 2 means that at least one character is tall (like \fBH\fR); and 3 means that both tall function \fB\eb\'\fIstring\fB\|\'\fR may be used to pile up vertically the characters in \fIstring\fR (the first character on top and the last at the bottom); the characters are vertically separated by 1|em and the total pile is centered 1\(sl2\|em above the current baseline (\(12 line in \*(NR). For example, \fB\eb\'\|\e(lc\e(lf\|\'E\e\|~\|\eb\'\|\e(rc\e(rf\|\'\|\ex\'\|\-0.5m\'\|\ex\'0.5m\'\|\fR produces \x'-.5m'\x'.5m'\fB\b'\(lc\(lf'E\|\b'\(rc\(rf'\fR. .sc Line drawing. .tr && The function \fB\e\|l\|\'\fI y a backward horizontal motion having the width of the space character. Underlining as a form of line-drawing is discussed in \(sc12.4. A generalized overstriking function is described in \(sc12.1. .pg \*(NR automatically underlines characters in the \fIunderline\fR font, specifiable with \fBuf\fR, normally that on font position 2 (normally Times Italic, see \(sc2.2). In addition to \fBft\fR and \fB\ef\fIF\fR, the underline font may be selected by \fBul\fR and \fBcu\fR. Underlining is restricted to an outpufBtr\fR. All text processing (e. g. character comparisons) takes place with the input (stand-in) character which appears to have the width of the final character. The graphic translation occurs at the moment of output (including diversion). .h1 .bt \fB&tr\fI|abcd....\fR none - O Translate \ \fIa\fR into \fIb\fR, \fIc\fR into \fId\fR, etc. If an odd number of characters is given, the last one will be mapped into the space character. To be consistent, a particular translation must stay in effect from \fIinputherwise within a line balance to zero. The above and certain other escape sequences providing local motion are summarized in the following table. .tr || .ds X \0\0\0 .TS center box; c2|cs2||c2|cs2 c1|c2c2||c2|c2c2. Vertical Effect in Horizontal Effect in Local Motion \*(TR \*(NR Local Motion \*(TR \*(NR _ .sp.4 .TC l2|ls2||l2|ls2. \fB\*X\ev\'\fIN\|\^\fB\'\fR Move distance \fIN\fR \ \fB\*X\eh\'\fIN\|\^\fB\'\fR Move distance \fIN\fR .TC _2|_2_2||l2|ls2. x x x \fB\*X\e\fR(space) Unpaddable space-size space .TCcharacters and characters with descenders are present. .sc Mark horizontal place. The escape sequence \fB\ek\fIx\fR will cause the \fIcurrent\fR horizontal position in the \fIinput line\fR to be stored in register \fIx\fR. As an example, the construction \fB\ekx\fIword\|\fB\eh\'\|~\|\enxu+2u\'\fIword\fB\fR will embolden \fIword\fR by backing up to almost its beginning and overprinting it, resulting in \kz\fIword\fR\h'|\nzu+2u'\fIword\fR. .mh Overstrike, Bracket, Line-drawing, and Zero-width Functions .sc OvNc\fB\|\'\fR will draw a string of repeated \fIc\fR\|'s towards the right for a distance \fIN\fR. (\|\fB\el\fR is \fB\e\fR(lower case L). If \fIc\fR looks like a continuation of an expression for \fIN\fR, it may insulated from \fIN\fR with a \fB\e&\fR. If \fIc\fR is not specified, the \fB\(ru\fR (baseline rule) is used (underline character in \*(NR). If \fIN\fR is negative, a backward horizontal motion of size \fIN\fR is made \fIbefore\fR drawing the string. Any space resulting from \fIN\fR\|\(sl(size of \fIc\fR) having a remainder is put at the beginning (left end) of the string. In the case of characters that are designed to be connected such as baseline-rule\ \fB\(ru\fR\|, underrule\ \fB\(ul\fR\|, and root-en\ \fB\(rn\fR\|, the remainder space is covered by over-lapping. If \fIN\fR is \fIless\fR than the width of \fIc\fR, a single \fIc\fR is centered on a distance \fIN\fR. As an example, a macro to underscore a string can be written .br .tr &. .x1 .ftB .ne 2.1 &de us \e\e$1\e\|l\|\'\|~\|0\e(ul\' && .ftR .xing \&.nf \e"avoid possibly overflowing word buffer .tr || \&\eh\'\-.5n\'\eL\'\||\|\e\enau\-1\'\el\'\e\en(.lu+1n\e(ul\'\eL\'\-\||\|\e\enau+1\'\el\'\||\|0u\-.5n\e(ul\' \e"draw box .tr | .lg0 \&.fi .lg \&.. .ftR .x2 will draw a box around some text whose beginning vertical place was saved in number register \fIa\fR (e. g. using \fB.mk|a\fR) as done for this paragraph. .eb are implied; i.|e. \fIdig\-it\fR implies \fIdig\-its\fR. This list is examined initially \fIand\fR after each suffix stripping. The space available is small\(emabout 128 characters. .mh Three Part Titles. .pg The titling function \fBtl\fR provides for automatic placement of three fields at the left, center, and right of a line with a title-length specifiable with \fBlt\fR. \fBtl\fR may be used anywhere, and is independent of the normal text collecting process. A common use is in header and footer macros. .in digit-spaces. Further, it can be specified that only those line numbers that are multiples of some number \fIM\fR are to be printed (the others will appear as blank number fields). .br .nm .ll .h1 .bt \fB&nm\fI|\(+-N|M|S|I\fR off E \ Line number mode. If \fI\(+-N\fR is given, line numbering is turned on, and the next output line numbered is numbered \fI\(+-N\fR. Default values are \fIM=\fR\|1, \fIS=\fR\|1, and \fII=\fR\|0. Parameters corresponding to missing arguments are unaffected; a non-numeric argume!\fR signifies \fInot\fR, \fIN\fR is a numerical expression, \fIstring1\fR and \fIstring2\fR are strings delimited by any non-blank, non-numeric character \fInot\fR in the strings, and \fIanything\fR represents what is conditionally accepted. .h1 .bt \fB&if\fI|c|anything\fR - - If condition \fIc\fR true, accept \fIanything\fR as input; in multi-line case use \fI\e{anything\|\e}\fR. .bt \fB&if|!\fIc|anything\fR - - If condition \fIc\fR false, accept \fIanything\fR. .bt \fB&if\fI|N|anything\fR - \fBu\fR If e subsequent and matching \fBel\fR (else) request then uses the reverse sense of that state. \fBie\fR|-|\fBel\fR pairs may be nested. .pg Some examples are: .x1 .ftB .ne 1 &if e .tl \'\|Even Page %\'\'\' .ftR .x2 which outputs a title if the page number is even; and .x1 .ftB .ne 3.1 &ie \en%>1 \e{\e \&\'sp 0.5i &tl \'\|Page %\'\'\' \&\'sp ~\|1.2i|\e} &el .sp ~\|2.5i .ftR .x2 which treats page 1 differently from other pages. .mh Environment Switching. .pg A number of the parameters that control the text proce2 .ne2.1 .de xu \\$1\l'|0\(ul' .. or one to draw a box around a string .x1 .ftB &de bx \e(br\e\|~\|\e\e$1\e\|~\|\e(br\e\|l\|\'\|~\|0\e(rn\'\e\|l\|\'\|~\|0\e(ul\' && .ftR .x2 .de bx \(br\|\\$1\|\(br\l'|0\(rn'\l'|0\(ul' .. such that .x1 .ftB &ul "underlined words" .ftR .x2 and .x1 .ftB &bx "words in a box" .ftR .x2 yield .xu "underlined words" and .bx "words in a box" \h'-\w'.'u'. .pg The function \fB\eL\'\|\fINc\fB\|\'\fR will draw a vertical line consisting of the (optional) character \fIc\fR stacked vertic.tr | .mh Hyphenation. .pg The automatic hyphenation may be switched off and on. When switched on with \fBhy\fR, several variants may be set. A \fIhyphenation indicator\fR character may be imbedded in a word to specify desired hyphenation points, or may be prepended to suppress hyphenation. In addition, the user may specify a small exception word list. .pg Only words that consist of a central alphabetic string surrounded by (usually null) non-alphabetic strings are considered candidates for automatic hyphenh1 .bt \fB&tl\fI|\'left\|\'center\|\'right\|\'\fR - - \ The strings \fIleft\fR, \fIcenter\fR, and \fIright\fR are respectively left-adjusted, centered, and right-adjusted in the current title-length. Any of the strings may be empty, and overlapping is permitted. If the page-number character (initially \fB%\fR) is found within any of the fields it is replaced by the current page number having the format assigned to register \fB%\fR. Any character may be used as the string delimiter. .bt \fB&pc\fI|c\fR \fB%\f   xpression \fIN\fR > 0, accept \fIanything\fR. .bt \fB&if|!\fIN|anything\fR - \fBu\fR If expression \fIN\fR \(<= 0, accept \fIanything\fR. .bt \fB&if\fI|\|\'string1\|\'string2\|\'|anything\fR - If \fIstring1\fR identical to \fIstring2\fR, accept \fIanything\fR. .bt \fB&if|!\fI\|\'string1\|\'string2\|\'|anything\fR - If \fIstring1\fR not identical to \fIstring2\fR, accept \fIanything\fR. .bt \fB&ie\fI|c|anything\fR - \fBu\fR If portion of if-else; all above forms (like \fBif\fR). .bt \fB&el\fI|anything\fR - ssing are gathered together into an \fIenvironment\fR, which can be switched by the user. The environment parameters are those associated with requests noting E in their \fINotes\fR column; in addition, partially collected lines and words are in the environment. Everything else is global; examples are page-oriented parameters, diversion-oriented parameters, number registers, and macro and string definitions. All environments are initialized with default parameter values. .h1 .bt \fB&ev\fI|N\fR \fIN\(eq\fR0 ally apart 1\|em (1 line in \*(NR), with the first two characters overlapped, if necessary, to form a continuous line. The default character is the \fIbox rule\fR |\(br| (\fB\|\e(br\fR); the other suitable character is the \fIbold vertical\fR \|\(bv\| (\fB\|\e(bv\fR). The line is begun without any initial motion relative to the current base line. A positive \fIN\fR specifies a line drawn downward and a negative \fIN\fR specifies a line drawn upward. After the line is drawn \fIno\fR compensating motions are ation. Words that were input containing hyphens (minus), em-dashes (\fB\e(em\fR), or hyphenation indicator characters\ \(emsuch as mother-in-law\(em\ are \fIalways\fR subject to splitting after those characters, whether or not automatic hyphenation is on or off. .h1 .bt \fB&nh\fR hyphenate - E \ Automatic hyphenation is turned off. .bt \fB&hy\fIN\fR on,\fIN=\fR1 on,\fIN=\fR1 E \ Automatic hyphenation is turned on for \fIN\fR\|\(>=1, or off for \fIN=\fR\|0. If \fIN=\fR\|2, \fIlast\fR lines (ones that will caR off - The page number character is set to \fIc\fR, or removed. The page-number register remains \fB%\fR. .bt \fB<\fI|\(+-N\fR 6.5\|in previous E,\fBm\fR Length of title set to \fI\(+-N\fR. The line-length and the title-length are \fIindependent\fR. Indents do not apply to titles; page-offsets do. .mh Output Line Numbering. .pg .ll -\w'0000'u .nm 1 3 Automatic sequence numbering of output lines may be requested with \fBnm\fR. When in effect, a three-digit, arabic number plus a digit-space is prepended tont is considered missing. In the absence of all arguments, numbering is turned off; the next line number is preserved for possible further use in number register \fBln\fR. .bt \fB&nn\fI|N\fR - \fIN=\fR1 E The next \fIN\fR text output lines are not numbered. .pg .ll -\w'0000'u .nm +0 As an example, the paragraph portions of this section are numbered with \fIM=\fR\|3: \&\fB.nm|1|3\fR was placed at the beginning; \&\fB.nm\fR was placed at the end of the first paragraph; and \fB.nm|+0\fR was placed in front of - Else portion of if-else. .pg The built-in condition names are: .TS center box; c2|c2 c2|c2 c2|l2. Condition Name True If _ \fBo\fR Current page number is odd \fBe\fR Current page number is even \fBt\fR Formatter is \*(TR \fBn\fR Formatter is \*(NR .TE If the condition \fIc\fR is \fItrue\fR, or if the number \fIN\fR is greater than zero, or if the strings compare identically (including motions and character size and font), \fIanything\fR is accepted as input. If a \fB!\fR precedes the condition, number, orprevious - Environment switched to environment 0\(<=\fIN\fR\(<=2. Switching is done in push-down fashion so that restoring a previous environment \fImust\fR be done with \fB.ev\fR rather than specific reference. .mh Insertions from the Standard Input .pg The input can be temporarily switched to the system \fIstandard input\fR with \fBrd\fR, which will switch back when \fItwo\fR newlines in a row are found (the \fIextra\fR blank line is not used). This mechanism is intended for insertions in form-letter-likemade; the instantaneous baseline is at the \fIend\fR of the line. .pg .de eb .sp -1 .nf \h'-.5n'\L'|\\nzu-1'\l'\\n(.lu+1n\(ul'\L'-|\\nzu+1'\l'|0u-.5n\(ul' .fi .. .ne 2i .mk z The horizontal and vertical line drawing functions may be used in combination to produce large boxes. The zero-width \fIbox-rule\fR and the \(12-em wide \fIunderrule\fR were \fIdesigned\fR to form corners when using 1-em vertical spacings. For example the macro .x1 .ftB \&.de eb \&.sp \-1 \e"compensate for next automatic base-line spacuse a trap) are not hyphenated. For \fIN=\fR\|4 and 8, the last and first two characters respectively of a word are not split off. These values are additive; i.|e. \fIN=\fR\|14 will invoke all three restrictions. .bt \fB&hc\fI|c\fR \fB\e% \e%\fR E Hyphenation indicator character is set to \fIc\fR or to the default \fB\e%\fR. The indicator does not appear in the output. .bt \fB&hw\fI|word1|...\fR ignored - Specify hyphenation points in words with imbedded minus signs. Versions of a word with terminal \fIs\fR output text lines. The text lines are thus offset by four digit-spaces, and otherwise retain their line length; a reduction in line length may be desired to keep the right margin aligned with an earlier margin. Blank lines, other vertical spaces, and lines generated by \fBtl\fR are \fInot\fR numbered. Numbering can be temporarily suspended with \fBnn\fR, or with an \fB.nm\fR followed by a later \fB.nm|+0\fR. In addition, a line number indent \fII\fR, and the number-text separation \fIS\fR may be specified this paragraph; and \fB.nm\fR finally placed at the end. Line lengths were also changed (by \fB\ew\'0000\'u\fR) to keep the right side aligned. Another example is \&\fB.nm|+5|5|x|3\fR which turns on numbering with the line number of the next line to be 5 greater than the last numbered line, with \fIM=\fR\|5, with spacing \fIS\fR untouched, and with the indent \fII\fR set to 3. .br .ll .nm .mh Conditional Acceptance of Input .pg In the following, \fIc\fR is a one-character, built-in \fIcondition\fR name, \fB string comparison, the sense of the acceptance is reversed. .pg Any spaces between the condition and the beginning of \fIanything\fR are skipped over. The \fIanything\fR can be either a single input line (text, macro, or whatever) or a number of input lines. In the multi-line case, the first line must begin with a left delimiter \fB\e{\fR and the last line must end with a right delimiter \fB\e}\fR. .pg The request \fBie\fR (if-else) is identical to \fBif\fR except that the acceptance state is remembered. A documentation. On \s-1UNIX\s+1, the \fIstandard input\fR can be the user's keyboard, a \fIpipe\fR, or a \fIfile\fR. .h1 .bt \fB&rd\fI|prompt\fR - \fIprompt=\fR\s-1BEL\s+1 - \ Read insertion from the standard input until two newlines in a row are found. If the standard input is the user's keyboard, \fIprompt\fR (or a \s-1BEL\s+1) is written onto the user's terminal. \fBrd\fR behaves like a macro, and arguments may be placed after \fIprompt\fR. .bt \fB&ex\fR - - - Exit from \*(NR\(sl\*(TR. Text processing is terminated exactly as if all input had ended. .pg If insertions are to be taken from the terminal keyboard \fIwhile\fR output is being printed on the terminal, the command line option \fB\-q\fR will turn off the echoing of keyboard input and prompt only with \s-1BEL\s+1. The regular input and insertion input \fIcannot\fR simultaneously come from the standard input. .pg As an example, multiple copies of a form letter may be prepared by entering the insertions for all the copies in one file to be used as thee line) is read in \fIcopy mode\fR and written on the user's terminal. .bt \fB&ig\fI|yy\fR - \fI.yy=\fB..\fR - Ignore \ input lines. \fBig\fR behaves exactly like \fBde\fR (\(sc7) except that the input is discarded. The input is read in \fIcopy mode\fR, and any auto-incremented registers will be affected. .bt \fB&pm\fI|t\fR - all - \ Print macros. The names and sizes of all of the defined macros and strings are printed on the user's terminal; if \fIt\fR is given, only the total of the sizes is printed. The .pn 27 .ds H T .tr | .tr ~| .de x1 .xx .ftB .in .2i .nf .ne 2.1 .ta 1i .. .de x2 .fi .in0 .ftR .xx .. .br .ce .ftB .rs .sp 0.5i TUTORIAL EXAMPLES .ftR .sp2 .nr p 0 .2C .ns .mh .mk Introduction .pg Although \*(NR and \*(TR have by design a syntax reminiscent of earlier text processors* .fn .xx *For example: P.|A.|Crisman, Ed., .ul The Compatible Time-Sharing System, MIT Press, 1965, Section|AH9.01 (Description of RUNOFF program on MIT's CTSS system). .ef with the intent of easing their use, it is almost alwa). In fill mode, the output line that springs the footer trap was typically forced out because some part or whole word didn't fit on it. If anything in the footer and header that follows causes a \fIbreak\fR, that word or part word will be forced out. In this and other examples, requests like \fBbp\fR and \fBsp\fR that normally cause breaks are invoked using the \fIno-break\fR control character \fB\'\fR to avoid this. When the header\(slfooter design contains material requiring independent text processing,            "    #  e suitable in \*(NR. The choice of remaining space to test for in the \fBne\fR is the smallest amount greater than one line (the \fB.V\fR is the available vertical resolution). .pg A macro to automatically number section headings might look like: .x1 &de sc \e"section & --- \e"force font, etc. &sp 0.4 \e"prespace &ne 2.4+\e\en(.Vu \e"want 2.4+ lines .lg 0 &fi .lg \e\en+S. && &nr S 0 1 \e"init S .x2 The usage is \fB.sc\fR, followed by the section heading text, followed by \fB.pg\fR. The \fBne\fR test value standard input, and causing the file containing the letter to reinvoke itself using \fBnx\fR (\(sc19); the process would ultimately be ended by an \fBex\fR in the insertion file. .mh Input\(slOutput File Switching .h1 .bt \fB&so\fI|filename\fR - - Switch source file. The top input (file reading) level is switched to \fIfilename\fR. The effect of an \fBso\fR encountered in a macro is not felt until the input level returns to the file level. When the new file ends, input is again taken from the original filsizes is given in \fIblocks\fR of 128 characters. .bt .lg0 \fB&fl\fR - - B \c .lg Flush output buffer. Used in interactive debugging to force output. .mh Output and Error Messages. .pg The output from \fBtm\fR, \fBpm\fR, and the prompt from \fBrd\fR, as well as various \fIerror\fR messages are written onto \s-1UNIX\s+1's \fIstandard message\fR output. The latter is different from the \fIstandard output\fR, where \*(NR formatted output goes. By default, both are written onto the user's terminal, but they canys necessary to prepare at least a small set of macro definitions to describe most documents. Such common formatting needs as page margins and footnotes are deliberately not built into \*(NR and \*(TR. Instead, the macro and string definition, number register, diversion, environment switching, page-position trap, and conditional input mechanisms provide the basis for user-defined implementations. .pg The examples to be discussed are intended to be useful and somewhat realistic, but won't necessarily cover athe environment may be switched, avoiding most interaction with the running text. .pg A more realistic example would be .x1 &de hd \e"header &if t .tl \'\|\e(rn\'\'\e(rn\' \e"troff cut mark &if \e\en%>1 \e{\e \'sp ~\|0.5i\-1 \e"tl base at 0.5i &tl \'\'\- % \-\'\' \e"centered page number &ps \e"restore size &ft \e"restore font &vs \e} \e"restore vs \'sp ~\|1.0i \e"space to 1.0i &ns \e"turn on no-space mode && &de fo \e"footer &ps 10 \e"set footer\(slheader size &ft R \e"set font &vs 12p \e"set base-line sed in the running text. A better scheme is save and restore both the current \fIand\fR previous values as shown for size in the following: .x1 &de fo &nr s1 \e\en(.s \e"current size &ps &nr s2 \e\en(.s \e"previous size & --- \e"rest of footer && &de hd & --- \e"header stuff &ps \e\en(s2 \e"restore previous size &ps \e\en(s1 \e"restore current size && .x2 Page numbers may be printed in the bottom margin by a separate macro triggered during the footer's page ejection: .x1 &de bn \e"bottom number &tl \'\'\-includes one line of heading, 0.4 line in the following \fBpg\fR, and one line of the paragraph text. A word consisting of the next section number and a period is produced to begin the heading line. The format of the number may be set by \fBaf\fR (\(sc8). .pg Another common form is the labeled, indented paragraph, where the label protrudes left into the indent space. .x1 &de lp \e"labeled paragraph &pg &in 0.5i \e"paragraph indent &ta 0.2i 0.5i \e"label, paragraph &ti 0 \et\e\e$1\et\ec \e"flow into paragrape. \fBso\fR's may be nested. .bt \fB&nx\fI|filename\fR end-of-file - Next file is \fIfilename\fR. The current file is considered ended, and the input is immediately switched to \fIfilename\fR. .bt \fB&pi\fI|program\fR - - Pipe output to \fIprogram\fR (\*(NR only). This request must occur \fIbefore\fR any printing occurs. No arguments are transmitted to \fIprogram\fR. .mh Miscellaneous .pg .h1 .bt .mc \s12\(br\s0 \fB&mc\fI|c|N\fR - off E,\fBm\fR \ Specifies that a \fImargin\fR character \fIc\fR appear a di be independently redirected. .pg Various \fIerror\fR conditions may occur during the operation of \*(NR and \*(TR. Certain less serious errors having only local impact do not cause processing to terminate. Two examples are \fIword overflow\fR, caused by a word that is too large to fit into the word buffer (in fill mode), and \fIline overflow\fR, caused by an output line that grew too large to fit in the line buffer; in both cases, a message is printed, the offending excess is discarded, and the affected woll relevant contingencies. Explicit numerical parameters are used in the examples to make them easier to read and to illustrate typical values. In many cases, number registers would really be used to reduce the number of places where numerical information is kept, and to concentrate conditional parameter initialization like that which depends on whether \*(TR or \*(NR is being used. .mh Page Margins .pg As discussed in \(sc3, \fIheader\fR and \fIfooter\fR macros are usually defined to describe the top and bspacing &if \e\en%=1 \e{\e \'sp ~\|\e\en(.pu\-0.5i\-1 \e"tl base 0.5i up &tl \'\'\- % \-\'\' \e} \e"first page number \'bp && &wh 0 hd &wh \-1i fo .x2 which sets the size, font, and base-line spacing for the header\(slfooter material, and ultimately restores them. The material in this case is a page number at the bottom of the first page and at the top of the remaining pages. If \*(TR is used, a \fIcut mark\fR is drawn in the form of \fIroot-en\fR's at each margin. The \fBsp\fR's refer to absolute positio % \-\'\' \e"centered page number && &wh \-0.5i\-1v bn \e"tl base 0.5i up .x2 .mh Paragraphs and Headings .pg The housekeeping associated with starting a new paragraph should be collected in a paragraph macro that, for example, does the desired preparagraph spacing, forces the correct font, size, base-line spacing, and indent, checks that enough space remains for \fImore than one\fR line, and requests a temporary indent. .x1 &de pg \e"paragraph &br \e"break &ft R \e"force font, &ps 10 \e"size, &vs 12p \e"sh && .x2 The intended usage is "\fB.lp\fR \fIlabel\fR\|"; \fIlabel\fR will begin at 0.2\|inch, and cannot exceed a length of 0.3\|inch without intruding into the paragraph. The label could be right adjusted against 0.4\|inch by setting the tabs instead with \fB.ta|0.4iR|0.5i\fR. The last line of \fBlp\fR ends with \fB\ec\fR so that it will become a part of the first line of the text that follows. .mh Multiple Column Output .pg The production of multiple column pages requires the footer macro to decide whethstance \fIN\fR to the right of the right margin after each non-empty text line (except those produced by \fBtl\fR). If the output line is too-long (as can happen in nofill mode) the character will be appended to the line. If \fIN\fR is not given, the previous \fIN\fR is used; the initial \fIN\fR is 0.2|inches in \*(NR and 1\|em in \*(TR. The margin character used with this paragraph was a 12-point box-rule. .br .mc .bt \fB&tm\fI|string\fR - newline - \ After skipping initial blanks, \fIstring\fR (rest of thrd or line is marked at the point of truncation with a \(** in \*(NR and a \(lh in \*(TR. The philosophy is to continue processing, if possible, on the grounds that output useful for debugging may be produced. If a serious error occurs, processing terminates, and an appropriate message is printed. Examples are the inability to create, read, or write files, and the exceeding of certain internal limits that make future output unlikely to be useful. .pg .bp ottom page margin areas respectively. A trap is planted at page position 0 for the header, and at \fI\-N\fR (\fIN\fR from the page bottom) for the footer. The simplest such definitions might be .x1 &de hd \e"define header \'sp 1i && \e"end definition &de fo \e"define footer \'bp && \e"end definition &wh 0 hd &wh \-1i fo .x2 which provide blank 1|inch top and bottom margins. The header will occur on the \fIfirst\fR page, only if the definition and trap exist prior to the initial pseudo-page transition (\(sc3ns to avoid dependence on the base-line spacing. Another reason for this in the footer is that the footer is invoked by printing a line whose vertical spacing swept past the trap position by possibly as much as the base-line spacing. The \fIno-space\fR mode is turned on at the end of \fBhd\fR to render ineffective accidental occurrences of \fBsp\fR at the top of the running text. .pg The above method of restoring size, font, etc. presupposes that such requests (that set \fIprevious\fR value) are \fInot\fR upacing, &in 0 \e"and indent &sp 0.4 \e"prespace &ne 1+\e\en(.Vu \e"want more than 1 line &ti 0.2i \e"temp indent && .x2 The first break in \fBpg\fR will force out any previous partial lines, and must occur before the \fBvs\fR. The forcing of font, etc. is partly a defense against prior error and partly to permit things like section heading macros to set parameters only once. The prespacing parameter is suitable for \*(TR; a larger space, at least as big as the output device vertical resolution, would be morer it was invoked by other than the last column, so that it will begin a new column rather than produce the bottom margin. The header can initialize a column register that the footer will increment and test. The following is arranged for two columns, but is easily modified for more. .x1 &de hd \e"header & --- &nr cl 0 1 \e"init column count &mk \e"mark top of text && &de fo \e"footer &ie \e\en+(cl<2 \e{\e &po +3.4i \e"next column; 3.1+0.3 &rt \e"back to mark &ns \e} \e"no-space mode &el \e{\e &po \e\enMu \e"restore left margin & --- \'bp \e} && &ll 3.1i \e"column width &nr M \e\en(.o \e"save left margin .x2 Typically a portion of the top of the first page contains full width text; the request for the narrower line length, as well as another \fB.mk\fR would be made where the two column output was to begin. .mh Footnote Processing .pg The footnote mechanism to be described is used by imbedding the footnotes in the input text at the point of reference, demarcated by an initial \fB.fn\fR and a terminal \fB.ef\fmargin size &wh 0 hd \e"header trap &wh 12i fo \e"footer trap, temp position &wh \-\e\enbu fx \e"fx at footer position &ch fo \-\e\enbu \e"conceal fx with fo .x2 The header \fBhd\fR initializes a footnote count register \fBx\fR, and sets both the current footer trap position register \fBy\fR and the footer trap itself to a nominal position specified in register \fBb\fR. In addition, if the register \fBdn\fR indicates a leftover footnote, \fBfz\fR is invoked to reprocess it. The footnote start macro \fBfn\fRhe footer can result in the footnote rereading finishing before reaching the \fBfx\fR trap. .pg A good exercise for the student is to combine the multiple-column and footnote mechanisms. .mh The Last Page .pg After the last input file has ended, \*(NR and \*(TR invoke the \fIend macro\fR (\(sc7), if any, and when it finishes, eject the remainder of the page. During the eject, any traps encountered are processed normally. At the \fIend\fR of this last page, processing terminates \fIunless\fR a partial line, \fI(Continued next page.)\fP .br .rm cx \\.. .. .de pp 'ps \\n(PS .ftR 'tl ''- % -'' 'bp .. .wh 0 hd .wh 12i fo .wh \nmu fx .ch fo \nmu .de fn .da FN .ev1 .if \\n+x=1 .fs .fi .ti0 .. .de xf .ev1 .nf .FN .rm FN .di .ev .. .de fs .ti0 \l'1i' .br .. .de ef .br .ev .di .nr y -\\n(dn .if \\nx=1 .nr y -2p .ch fo \\nyu .if \\n(nl+\\n(.v-\\n(.p-\\ny .ch fo \\n(nlu+\\n(.vu .. .wh -.6i pp .de h1 .xx .ne 5 .nf .ta \\nau \\nbu \\ncu \\ndu +\\neu .ft I .bd I 3 Request Initial If No Form Value\\$2 Argument Notes\\$1 Explvailable at the current macro level. - \fB&A\fR Set to 1 in \*(TR, if \fB\-a\fR option used; always 1 in \*(NR. 11.1 \fB&H\fR Available horizontal resolution in basic units. - \fB&T\fR Set to 1 in \*(NR, if \fB\-T\fR option used; always 0 in \*(TR. 11.1 \fB&V\fR Available vertical resolution in basic units. 5.2 \fB&a\fR Post-line extra line-space most recently utilized \ using \fB\ex\fI\'N\|\'\fR. - \fB&c\fR Number of \fIlines\fR read from current input file. 7.4 \fB&d\fR Current vertical place in current d(*S \(*U \(*F \(*Q \(*W .br \(sr \(rn \(>= \(<= \(== \(ap \(~= \(!= \(-> \(<- \(ua \(da \(mu \(di \(+- \(cu \(ca \(sb \(sp \(ib \(ip \(if \(pd .br \(sc \(gr \(no \(is \(pt \(es \(mo \(dd \(rh \(lh \(bs \(or \(ci \(lt \(lb \(rt \(rb \(lk \(rk \(bv \(lf \(rf \(lc \(rc \(br .br .ss12 .nf .. .nf .ps12 .vs 14p .ft B .ce Table I .sp .ce Font Style Examples .sp .5i .ftR .ps 10 .fi .vs 12p .na The following fonts are printed in 12-point, with a vertical spacing of 14-point, and with non-alphanumeric characters sepaR: .x1 &fn \fIFootnote text and control lines...\fP &ef .x2 In the following, footnotes are processed in a separate environment and diverted for later printing in the space immediately prior to the bottom margin. There is provision for the case where the last collected footnote doesn't completely fit in the available space. .x1 &de hd \e"header & --- &nr x 0 1 \e"init footnote count &nr y 0\-\e\enb \e"current footer place &ch fo \-\e\enbu \e"reset footer trap &if \e\en(dn .fz \e"leftover footnote && &de fo begins a diversion (append) in environment 1, and increments the count \fBx\fR; if the count is one, the footnote separator \fBfs\fR is interpolated. The separator is kept in a separate macro to permit user redefinition. The footnote end macro \fBef\fR restores the previous environment and ends the diversion after saving the spacing size in register \fBz\fR. \fBy\fR is then decremented by the size of the footnote, available in \fBdn\fR; then on the first footnote, \fBy\fR is further decremented by the diffword, or partial word remains. If it is desired that another page be started, the end-macro .x1 &de en \e"end-macro \ec \'bp && &em en .x2 will deposit a null partial word, and effect another last page. anation .bd I .ft R .ft .fi .in \\ndu .. .de bt .ftR .xx .ne 1.1 .ti0 .. .de b1 .br .ti0 .. .de pg .ft R .fi .in0 .xx .ne 1.1 .. .de sc .pg \fI\\*H\\np.\\n+s.\|\\c .ftR .ul .. .de mh .nr s 0 .in0 .xx .ne 2.5 .ft B \\*H\\n+p. .. .de x1 .xx .in.5i .nf .. .de x2 .xx .in0 .fi .. .de EM .br \&\c 'bp .pl2i .. .em EM .de TS .sp .. .de TE .sp .ce 0 .ft R .ps \n(PS .ta \\nau \\nbu \\ncu \\ndu +\\neu .. iversion; equal to \fBnl\fR, if no diversion. 2.2 \fB&f\fR Current font as physical quadrant (1-4). 4 \fB&h\fR Text base-line high-water mark on current page or diversion. 6 \fB&i\fR Current indent. 6 \fB&l\fR Current line length. 4 \fB&n\fR Length of text portion on previous output line. 3 \fB&o\fR Current page offset. 3 \fB&p\fR Current page length. 2.3 \fB&s\fR Current point size. 7.5 \fB&t\fR Distance to the next trap. 4.1 \fB&u\fR Equal to 1 in fill mode and 0 in nofill mode. 5.1 \fB&v\fR Current vertirated by \(14\|em space. The Special Mathematical Font was specially prepared for Bell Laboratories by Graphic Systems, Inc. of Hudson, New Hampshire. The Times Roman, Italic, and Bold are among the many standard font available from that company. .sp.5i .ps12 .vs14p .ftR Times Roman .sp.5 .aa .sp .ftI Times Italic .sp.5 .aa .sp .ftB Times Bold .sp.5 .aa .sp .ftR Special Mathematical Font .sp.5 .fi .ll 5i .bb \e"footer &nr dn 0 \e"zero last diversion size &if \e\enx \e{\e &ev 1 \e"expand footnotes in ev1 &nf \e"retain vertical size &FN \e"footnotes &rm FN \e"delete it &if "\e\en(.z"fy" .di \e"end overflow diversion &nr x 0 \e"disable fx &ev \e} \e"pop environment & --- \'bp && &de fx \e"process footnote overflow &if \e\enx .di fy \e"divert overflow && &de fn \e"start footnote &da FN \e"divert (append) footnote &ev 1 \e"in environment 1 &if \e\en+x=1 .fs \e"if first, include separator .lg0 &fi \e"fill mode .erence in vertical base-line spacings of the two environments, to prevent the late triggering the footer trap from causing the last line of the combined footnotes to overflow. The footer trap is then set to the lower (on the page) of \fBy\fR or the current page position (\fBnl\fR) plus one line, to allow for printing the reference line. If indicated by \fBx\fR, the footer \fBfo\fR rereads the footnotes from \fBFN\fR in nofill mode in environment 1, and deletes \fBFN\fR. If the footnotes were too large to fi.so /usr/jfo/datemac .bd S B 3 .ds NR "\s-1NROFF\s+1 .ds TR "\s-1TROFF\s+1 .ds Nr "N\s-2ROFF\s+2 .ds Tr "T\s-2ROFF\s+2 .nr PS 10 .hy14 .ds u \v'-0.3m'\s-2 .ds d \s0\v'0.3m' .nr a .8i .nr b 1.6i .nr c 2.4i .nr d 2.9i .nr e 0.25i .nr p 0 1 .nr s 0 1 .af p 1 .af s 1 .nr m -1i .nr x 0 1 .nr y 0+\nmu .ev1 .ps \n(PS-2 .vs \n(PS .ll6.5i 'in 0 .ev .tr &. .de xx .sp 0.4 .. .de ht .tl `\*(Nr/\*(Tr User's Manual``` .tl 'October 11, 1976'''\".tl 'Version \n(mo/\n(dy/\n(yr''' .. .de hd .tl '\(rn''' .if \\n%>1 \{'sp |.33.ftB .nf Predefined General Number Registers .ft .TS c2l c2l2l n2l2l. .ftI .bd I 3 Section Register Reference Name Description .ftR .bd I .xx 3 \fB%\fR Current page number. 11.2 \fBct\fR Character type (set by \fIwidth\fR function). 7.4 \fBdl\fR Width (maximum) of last completed diversion. 7.4 \fBdn\fR Height (vertical size) of last completed diversion. - \fBdw\fR Current day of the week (1-7). - \fBdy\fR Current day of the month (1-31). 11.3 \fBhp\fR Current horizontal place on \fIinput\fR line. 15 \fBln\fcal line spacing. 11.2 \fB&w\fR Width of previous character. - \fB&x\fR Reserved version-dependent register. - \fB&y\fR Reserved version-dependent register. 7.4 \fB&z\fR Name of current diversion. .TE .pn32 .br .de mx .nf .ftI .ta .25iC .5i +.45i 3.25iC +.25i +.45i Input Character Input Character Char Name Name Char Name Name .ftR .sp.2 .nr cl 0 .mk .. .br .tr ~~ .nf .ps12 .vs 14p .ft B .ce Table II .sp .ce2 Input Naming Conventions for \', \`,and \- and for Non-ASCII Special Characters .sp .5i .ftR .ps10 .vs12p .ftB .bd I 3 Non-\s-1ASCII\s+1 characters and \fIminus\fP on the standard fonts. .sp .ftR .de cl .ie \\n+(cl<2 \{.po +3.0i .rt \} .el .sc .. .de sc .po 26i/27u .nr cl 0 .. .nr cl 0 1 .de qq lg && &de ef \e"end footnote &br \e"finish output &nr z \e\en(.v \e"save spacing &ev \e"pop ev &di \e"end diversion &nr y \-\e\en(dn \e"new footer position, &if \e\enx=1 .nr y \-(\e\en(.v\-\e\enz) \e \e"uncertainty correction &ch fo \e\enyu \e"y is negative &if (\|\e\en(nl+1v)>(\|\e\en(.p+\e\eny) \e &ch fo \e\en(nlu+1v \e"it didn't fit && &de fs \e"separator \el\'\|1i\' \e"1 inch rule &br && &de fz \e"get leftover footnote &fn &nf \e"retain vertical size &fy \e"where fx put it &ef && &nr b 1.0i \e"bottom t, the macro \fBfx\fR will be trap-invoked to redivert the overflow into \fBfy\fR, and the register \fBdn\fR will later indicate to the header whether \fBfy\fR is empty. Both \fBfo\fR and \fBfx\fR are planted in the nominal footer trap position in an order that causes \fBfx\fR to be concealed unless the \fBfo\fR trap is moved. The footer then terminates the overflow diversion, if necessary, and zeros \fBx\fR to disable \fBfx\fR, because the uncertainty correction together with a not-too-late triggering of ti .ht .ps \\n(S2 .ps \\n(S1 .ft 'sp |1i\} .nr x 0 1 .nr y 0+\\nmu .ch fo \\nmu .if \\n(dn .fz .ns .mx .nr cl 0 1 .mk .. .de fz .fn .nf .fy .fi .ef .. .de fx .if \\nx .di fy .. .de fo .cx .nr dn 0 .if \\nx .xf .nr x 0 \"disable fx .ie \\n(2C&(\\n+(cl<2) \{\ .po +3.4i .rt .nr y 0+\\nmu .ch fo \\nmu .if \\n(dn .fz .ns \} .el \{\ .po 26i/27u .nr S1 \\n(.s .ps .nr S2 \\n(.s .ps 10 'bp \} .. .de 2C .br .mk .nr 2C 1 .ll 3.1i .ev 1 .ll 3.1i .ev .. .de 1C .br .nr 2C 0 .ll 6.5i .ev1 .ll 6.5i .ev .. .de co .de cx .br R Output line number. - \fBmo\fR Current month (1-12). 4.1 \fBnl\fR Vertical position of last printed text base-line. 11.2 \fBsb\fR Depth of string below base line (generated by \fIwidth\fR function). 11.2 \fBst\fR Height of string above base line (generated by \fIwidth\fR function). - \fByr\fR Last two digits of current year. .TE .sp .ftB Predefined Read-Only Number Registers .ftR .TS c2l c2l2l n2l2l. .ftI .bd I 3 Section Register Reference Name Description .ftR .bd I .xx 7.3 \fB&$\fR Number of arguments a.pn 31 .rm mx .br .tr && .tr || .tr ~~ .de aa .nf abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 .ss9 ! $ % & ( ) ` ' * + \- . , / : ; = ? [ ] | .fi \(bu \(sq \(em \(hy \(ru \(14 \(12 \(34 \(fi \(fl \(ff \(Fi \(Fl \(de \(dg \(fm \(ct \(rg \(co .ss12 .. .de bb .ss9 .fi .ll5i " \' \e ^ \_ \` ~ \(sl < > { } # @ \(pl \(mi \(eq \(** .br \(*a \(*b \(*g \(*d \(*e \(*z \(*y \(*h \(*i \(*k \(*l \(*m \(*n \(*c \(*o \(*p \(*r \(*s \(ts \(*t \(*u \(*f \(*x \(*q \(*w .br \(*G \(*D \(*H \(*L \(*C \(*P \ \&' \' close quote ` \` open quote \(em \e(em 3\(sl4 Em dash - \- hyphen or \(hy \e(hy hyphen \- \e\- current font minus \(bu \e(bu bullet \(sq \e(sq square \(ru \e(ru rule \(14 \e(14 1\(sl4 \(12 \e(12 1\(sl2 \(34 \e(34 3\(sl4 \(fi \e(fi fi \(fl \e(fl fl \(ff \e(ff ff \(Fi \e(Fi ffi \(Fl \e(Fl ffl \(de \e(de degree \(dg \e(dg dagger \(fm \e(fm foot mark \(ct \e(ct cent sign \(rg \e(rg registered \(co \e(co copyright .. .di zz .lg0 .qq .di .lg .mx .nr aa \n(dn/2 .ne \n(aau+1 .nr bb \n(nl+\n(aa .wh \n(bbu cl .qq .sp |\n(bbu .ch cl 12i .fi .sp2 .ftB .bd I Non-\s-1ASCII\s+1 characters and \', \`, \_\|, \(pl, \(mi, \(eq, and \(** on the special font. .sp.4 .ftR .fi .ps10 The ASCII characters @, #, ", \', \`, <, >, \\, {, }, ~, ^, and \(ul exist \fIonly\fR on the special font and are printed as a 1-em space if that font is not mounted. The following characters exist only on the special font except for the upper case Greek letter names followed by \(dg which are mapped into upper case English \(~= \\(~= approx = \(ap \\(ap approximates \(!= \\(!= not equal \(-> \\(\(mi> right arrow \(<- \\(<\(mi left arrow \(ua \\(ua up arrow \(da \\(da down arrow \(mu \\(mu multiply \(di \\(di divide \(+- \\(+\(mi plus-minus \(cu \\(cu cup (union) \(ca \\(ca cap (intersection) \(sb \\(sb subset of \(sp \\(sp superset of \(ib \\(ib improper subset \(ip \\(ip improper superset \(if \\(if infinity \(pd \\(pd partial derivative \(gr \\(gr gradient \(no \\(no not \(is \\(is integral sign \(pt \The nroff/troff manual is printed in a number of pieces. m0 (pages 1-2) is usage section printed by- troff mac m0 m0a (pages 3-7) is the summary and index section; it contains so's to "cross", "escapes", and "registers" and is printed by- tbl esc.tbl >escapes tbl reg.tbl >registers troff mac m0a m1, m2, m3, and m4 (pages 8-26) are the reference manual, and are printed by- tbl m1 m2 m3 m4 | troff mac - m5 (pages 27-30) is the tutorial and is printed by- troff mac m5 table1 (page 31) is table 1, and is p"\033A", /*right*/ "\033Q \033P", /* horiz pitch .01 */ /*left*/ "\033Q\b\033P", /*codetab*/ #include "code.300" *square*/ "\001-", /*3/4 em*/ "\001_", /*rule*/ "\000\0", /*1/4*/ "\000\0", /*1/2*/ "\000\0", /*3/4*/ "\001-", /*minus*/ "\202fi", /*fi*/ "\202fl", /*fl*/ "\202ff", /*ff*/ "\203ffi", /*ffi*/ "\203ffl", /*ffl*/ "\000\0", /*degree*/ "\000\0", /*dagger*/ "\000\0", /*section*/ "\001'", /*foot mark*/ "\001'", /*acute accent*/ "\001`", /*grave accent*/ "\001_", /*underrule*/ "\001/", /*slash (longer)*/ "\000\0", /*half narrow space*/ "\001 ", /*unpaddable space*/ "\001\241c\202(\241", /*alpha*/l*/ "\001x", /*multiply*/ "\001/", /*divide*/ "\001+\b_", /*plus-minus*/ "\001U", /*cup (union)*/ "\000\0", /*cap (intersection)*/ "\000\0", /*subset of*/ "\000\0", /*superset of*/ "\000\0", /*improper subset*/ "\000\0", /* improper superset*/ "\002oo", /*infinity*/ "\001\200o\201\301`\241\341`\241\341`\201\301", /*partial derivative*/ "\001\242\\\343-\204-\303/\242", /*gradient*/ "\001\200-\202\341,\301\242", /*not*/ "\001\200|'\202`\243\306'\241`\202\346", /*integral sign*/ "\000\0", /*proportiletters in whatever font is mounted on font position one (default Times Roman). The special math plus, minus, and equals are provided to insulate the appearance of equations from the choice of standard fonts. .bd I 3 .nf .ps10 .sp .de sc .po 26i/27u .nr cl 0 'bp .. .ch cl \nmu-\n(.vu-1u .mx .lg 0 \(pl \e(pl math plus \(mi \e(mi math minus \(eq \e(eq math equals \(** \e(** math star \(sc \e(sc section \(aa \\(aa acute accent \(ga \\(ga grave accent \(ul \\(ul underrule \(sl \\(sl slash (matching bac\(pt proportional to \(es \\(es empty set \(mo \\(mo member of \(br \\(br box vertical rule \(dd \\(dd double dagger \(rh \\(rh right hand \(lh \\(lh left hand \(bs \\(bs Bell System logo \(or \\(or or \(ci \\(ci circle \(lt \\(lt left top of big curly bracket \(lb \\(lb left bottom \(rt \\(rt right top \(rb \\(rb right bot \(lk \\(lk left center of big curly bracket \(rk \\(rk right center of big curly bracket \(bv \\(bv bold vertical \(lf \\(lf left floor (left bottom of big square brarinted by- troff mac table1 table2 (page 32-33) is table 2, and is printed by- troff mac table2 "\001 ", /*space*/ "\001!", /*!*/ "\001\"", /*"*/ "\001#", /*#*/ "\001$", /*$*/ "\001%", /*%*/ "\001&", /*&*/ "\001'", /*' close*/ "\001(", /*(*/ "\001)", /*)*/ "\001*", /***/ "\001+", /*+*/ "\001,", /*,*/ "\001-", /*- hyphen*/ "\001.", /*.*/ "\001/", /*/*/ "\2010", /*0*/ "\2011", /*1*/ "\2012", /*2*/ "\2013", /*3*/ "\2014", /*4*/ "\2015", /*5*/ "\2016", /*6*/ "\2017", /*7*/ "\2018", /*8*/ "\2019", /*9*/ "\001:", /*:*/ "\001;", /*;*/ "\001<", /*<*/ "\001=", /*=*/ "\001>", /*>*/ "\001?", /*?*/ "\001@", /*@*/ "\001\200B\242\302\|\202\342", /*beta*/ "\001\200)\201/\241", /*gamma*/ "\001\200o\342<\302", /*delta*/ "\001<\b-", /*epsilon*/ "\001\200c\201\301,\241\343<\302", /*zeta*/ "\001\200n\202\302|\242\342", /*eta*/ "\001O\b-", /*theta*/ "\001i", /*iota*/ "\001k", /*kappa*/ "\001\200\\\304\241'\301\241'\345\202", /*lambda*/ "\001\200u\242,\202", /*mu*/ "\001\241(\203/\242", /*nu*/ "\001\200c\201\301,\241\343c\241\301`\201\301", /*xi*/ "\001o", /*omicron*/ "\001\341-\303\"\301\"\343", /*pi*/ "\001\200o\242\302 1 7 = , 2 8 > - 9 ?kslash) \(*a \\(*a alpha \(*b \\(*b beta \(*g \\(*g gamma \(*d \\(*d delta \(*e \\(*e epsilon \(*z \\(*z zeta \(*y \\(*y eta \(*h \\(*h theta \(*i \\(*i iota \(*k \\(*k kappa \(*l \\(*l lambda \(*m \\(*m mu \(*n \\(*n nu \(*c \\(*c xi \(*o \\(*o omicron \(*p \\(*p pi \(*r \\(*r rho \(*s \\(*s sigma \(ts \\(ts terminal sigma \(*t \\(*t tau \(*u \\(*u upsilon \(*f \\(*f phi \(*x \\(*x chi \(*q \\(*q psi \(*w \\(*w omega \(*A \\(*A Alpha\(dg \(*B \\(*B Beta\(dg \(*G \\(*G Gamma \(* ! ' ( . 4 : ) / ;#define INCH 240 /* Carousel 300 with Electronic Format Control nroff driving tables width and code tables */ struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { /*bset*/ 0, /*breset*/ 0, /*Hor*/ INCH/10, /*Vert*/ INCH/1 "\201A", /*A*/ "\201B", /*B*/ "\201C", /*C*/ "\201D", /*D*/ "\201E", /*E*/ "\201F", /*F*/ "\201G", /*G*/ "\201H", /*H*/ "\201I", /*I*/ "\201J", /*J*/ "\201K", /*K*/ "\201L", /*L*/ "\201M", /*M*/ "\201N", /*N*/ "\201O", /*O*/ "\201P", /*P*/ "\201Q", /*Q*/ "\201R", /*R*/ "\201S", /*S*/ "\201T", /*T*/ "\201U", /*U*/ "\201V", /*V*/ "\201W", /*W*/ "\201X", /*X*/ "\201Y", /*Y*/ "\201Z", /*Z*/ "\001[", /*[*/ "\001\\", /*\*/ "\001]", /*]*/ "\001^", /*^*/ "\001_", /*_ dash*/ "\001`", /*` open*/ "\201a", /*a*/ "\201|\342\202", /*rho*/ "\001\200o\301\202~\341\242", /*sigma*/ "\001\200t\301\202~\243~\201\341", /*tau*/ "\001v", /*upsilon*/ "\001o\b/", /*phi*/ "\001x", /*chi*/ "\001\200/-\302\202'\244'\202\342", /*psi*/ "\001\241u\203u\242", /*omega*/ "\001\242|\202\343-\303\202`\242", /*Gamma*/ "\001\242/\303-\204-\343\\\242", /*Delta*/ "\001O\b=", /*Theta*/ "\001\242/\204\\\242", /*Lambda*/ "\000\0", /*Xi*/ "\001\242[]\204[]\242\343-\303", /*Pi*/ "\001\200>\302-\345-\303", /*Sigma*/ "\000\0", /**/ "\001Y", /*Upsiloonal to*/ "\000\0", /*empty set*/ "\000\0", /*member of*/ "\001+", /*equation plus*/ "\001r\bO", /*registered*/ "\001c\bO", /*copyright*/ "\001|", /*box rule */ "\001c\b/", /*cent sign*/ "\000\0", /*dbl dagger*/ "\000\0", /*right hand*/ "\001*", /*left hand*/ "\001*", /*math * */ "\000\0", /*bell system sign*/ "\001|", /*or (was star)*/ "\001O", /*circle*/ "\001|", /*left top (of big curly)*/ "\001|", /*left bottom*/ "\001|", /*right top*/ "\001|", /*right bot*/ "\001|", /*left center of D \\(*D Delta \(*E \\(*E Epsilon\(dg \(*Z \\(*Z Zeta\(dg \(*Y \\(*Y Eta\(dg \(*H \\(*H Theta \(*I \\(*I Iota\(dg \(*K \\(*K Kappa\(dg \(*L \\(*L Lambda \(*M \\(*M Mu\(dg \(*N \\(*N Nu\(dg \(*C \\(*C Xi \(*O \\(*O Omicron\(dg \(*P \\(*P Pi \(*R \\(*R Rho\(dg \(*S \\(*S Sigma \(*T \\(*T Tau\(dg \(*U \\(*U Upsilon \(*F \\(*F Phi \(*X \\(*X Chi\(dg \(*Q \\(*Q Psi \(*W \\(*W Omega \(sr \\(sr square root \(rn \\(rn root en extender \(>= \\(>= >= \(<= \\(<= <= \(== \\(== identically equal cket) \(rf \\(rf right floor (right bottom) \(lc \\(lc left ceiling (left top) \(rc \\(rc right ceiling (right top) 2, /*Newline*/ INCH/6, /*Char*/ INCH/10, /*Em*/ INCH/10, /*Halfline*/ INCH/12, /*Adj*/ INCH/10, /*twinit*/ "", /*twrest*/ "", /*twnl*/ "\r\033D\033D", /*** Note: changed from "\n" because of *** hardware peculiarity of Carousel *** which only affects half-line *** motions ***/ /*hlr*/ "\033d", /*hlf*/ "\033D", /*flr*/ "\0337", /*bdon*/ "", /*bdoff*/ "", /*ploton*/ " \033P", /* set horiz pitch to 0 */ /*plotoff*/ "\033p\b", /* horiz pitch to .1 inch */ /*up*/ "\033a", /*down*/ b", /*b*/ "\201c", /*c*/ "\201d", /*d*/ "\201e", /*e*/ "\201f", /*f*/ "\201g", /*g*/ "\201h", /*h*/ "\201i", /*i*/ "\201j", /*j*/ "\201k", /*k*/ "\201l", /*l*/ "\201m", /*m*/ "\201n", /*n*/ "\201o", /*o*/ "\201p", /*p*/ "\201q", /*q*/ "\201r", /*r*/ "\201s", /*s*/ "\201t", /*t*/ "\201u", /*u*/ "\201v", /*v*/ "\201w", /*w*/ "\201x", /*x*/ "\201y", /*y*/ "\201z", /*z*/ "\001{", /*{*/ "\001|", /*|*/ "\001}", /*}*/ "\001~", /*~*/ "\000\0", /*narrow sp*/ "\001-", /*hyphen*/ "\001o\b+", /*bullet*/ "\002\[]", /n*/ "\001o\b[\b]", /*Phi*/ "\001\200[]-\302\202'\244`\202\342", /*Psi*/ "\001\200O\302\241-\202-\241\342", /*Omega*/ "\000\0", /*square root*/ "\000\0", /*terminal sigma*/ "\000\0", /*root en*/ "\001>\b_", /*>=*/ "\001<\b_", /*<=*/ "\001=\b_", /*identically equal*/ "\001-", /*equation minus*/ "\001=\b~", /*approx =*/ "\000\0", /*approximates*/ "\001=\b/", /*not equal*/ "\002->", /*right arrow*/ "\002<-", /*left arrow*/ "\001|\b^", /*up arrow*/ "\000\0", /*down arrow*/ "\001=", /*equation equabig curly bracket*/ "\001|", /*right center of big curly bracket*/ "\001|", /*bold vertical*/ "\001|", /*left floor (left bot of big sq bract)*/ "\001|", /*right floor (rb of ")*/ "\001|", /*left ceiling (lt of ")*/ "\001|"}; /*right ceiling (rt of ")*/ #define INCH 240 /* DASI300 nroff driving tables width and code tables */ struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { /*bset*/ 0, /*breset*/ 0177420, /*Hor*/ INCH/60, /*Vert*/ INCH/48, /*Newline*/ INCH/6, /*Char*#define INCH 240 /* TTY M37 nroff driving tables width and code tables */ struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { /*bset*/ 0, /*breset*/ 0, /*Hor*/ INCH/10, /*Vert*/ INCH/12, /*Newline*/ INCH/6, /*Char*/ INCH/*q*/ "\201r", /*r*/ "\201s", /*s*/ "\201t", /*t*/ "\201u", /*u*/ "\201v", /*v*/ "\201w", /*w*/ "\201x", /*x*/ "\201y", /*y*/ "\201z", /*z*/ "\001{", /*{*/ "\001|", /*|*/ "\001}", /*}*/ "\001~", /*~*/ "\000\0", /*narrow sp*/ "\001-", /*hyphen*/ "\001o\b+", /*bullet*/ "\002\[]", /*square*/ "\001-", /*3/4 em*/ "\001_", /*rule*/ "\0031/4", /*1/4*/ "\0031/2", /*1/2*/ "\0033/4", /*3/4*/ "\001-", /*minus*/ "\202fi", /*fi*/ "\202fl", /*fl*/ "\202ff", /*ff*/ "\203ffi", /*ffi*/ "\203ffl", /*ffl*/ "\000\0" A G M S B H N T I O U#define INCH 240 /* DASI450 nroff driving tables width and code tables */ struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { /*bset*/ 0, /*breset*/ 0177420, /*Hor*/ INCH/60, /*Vert*/ INCH/48, /*Newline*/ INCH/6, /*Char*001/", /*/*/ "\2010", /*0*/ "\2011", /*1*/ "\2012", /*2*/ "\2013", /*3*/ "\2014", /*4*/ "\2015", /*5*/ "\2016", /*6*/ "\2017", /*7*/ "\2018", /*8*/ "\2019", /*9*/ "\001:", /*:*/ "\001;", /*;*/ "\001<", /*<*/ "\001=", /*=*/ "\001>", /*>*/ "\001?", /*?*/ "\001@", /*@*/ "\201A", /*A*/ "\201B", /*B*/ "\201C", /*C*/ "\201D", /*D*/ "\201E", /*E*/ "\201F", /*F*/ "\201G", /*G*/ "\201H", /*H*/ "\201I", /*I*/ "\201J", /*J*/ "\201K", /*K*/ "\201L", /*L*/ "\201M", /*M*/ "\201N", /*N*/ "\201O", /*O*/ "\201P", /*P*/ "\20/ INCH/10, /*Em*/ INCH/10, /*Halfline*/ INCH/12, /*Adj*/ INCH/10, /*twinit*/ "\007", /*twrest*/ "\007", /*twnl*/ "\015\n", /*hlr*/ "", /*hlf*/ "", /*flr*/ "\013", /*bdon*/ "", /*bdoff*/ "", /*ploton*/ "\006", /*plotoff*/ "\033\006", /*up*/ "\013", /*down*/ "\n", /*right*/ " ", /*left*/ "\b", /*codetab*/ #include "code.300" /10, /*Em*/ INCH/10, /*Halfline*/ INCH/12, /*Adj*/ INCH/10, /*twinit*/ "", /*twrest*/ "", /*twnl*/ "\n", /*hlr*/ "\0338", /*hlf*/ "\0339", /*flr*/ "\0337", /*bdon*/ "", /*bdoff*/ "", /*ploton*/ "", /*plotoff*/ "", /*up*/ "", /*down*/ "", /*right*/ "", /*left*/ "", /*codetab*/ "\001 ", /*space*/ "\001!", /*!*/ "\001\"", /*"*/ "\001#", /*#*/ "\001$", /*$*/ "\001%", /*%*/ "\001&", /*&*/ "\001'", /*' close*/ "\001(", /*(*/ "\001)", /*)*/ "\001*", /***/ "\001+", /*+*/ "\001,", /*,*/ "\001-", /*- hyphen*/ ", /*degree*/ "\000\0", /*dagger*/ "\000\0", /*section*/ "\001'", /*foot mark*/ "\001'", /*acute accent*/ "\001`", /*grave accent*/ "\001_", /*underrule*/ "\001/", /*slash (longer)*/ "\000\0", /*half narrow space*/ "\001 ", /*unpaddable space*/ "\201\016A\017", /*alpha*/ "\201\016B\017", /*beta*/ "\201\016\\\017", /*gamma*/ "\201\016D\017", /*delta*/ "\201\016S\017", /*epsilon*/ "\201\016Q\017", /*zeta*/ "\201\016N\017", /*eta*/ "\201\016O\017", /*theta*/ "\201i", /*iota*/ "\201k", /*kappa*/ "\201\on equal*/ "\001x", /*multiply*/ "\001/", /*divide*/ "\001+\b_", /*plus-minus*/ "\001U", /*cup (union)*/ "\000\0", /*cap (intersection)*/ "\000\0", /*subset of*/ "\000\0", /*superset of*/ "\000\0", /*improper subset*/ "\000\0", /* improper superset*/ "\002oo", /*infinity*/ "\001\016]\017", /*partial derivative*/ "\001\016[\017", /*gradient*/ "\001\016_\017", /*not*/ "\001\016^\017", /*integral sign*/ "\000\0", /*proportional to*/ "\000\0", /*empty set*/ "\000\0", /*member of*/ "\001+", /*equat/ INCH/10, /*Em*/ INCH/10, /*Halfline*/ INCH/12, /*Adj*/ INCH/10, /*twinit*/ "\0334", /*twrest*/ "\0334", /*twnl*/ "\015\n", /*hlr*/ "\033D", /*hlf*/ "\033U", /*flr*/ "\033\n", /*bdon*/ "", /*bdoff*/ "", /*ploton*/ "\0333", /*plotoff*/ "\0334", /*up*/ "\033\n", /*down*/ "\n", /*right*/ " ", /*left*/ "\b", /*codetab*/ #include "code.300" 1Q", /*Q*/ "\201R", /*R*/ "\201S", /*S*/ "\201T", /*T*/ "\201U", /*U*/ "\201V", /*V*/ "\201W", /*W*/ "\201X", /*X*/ "\201Y", /*Y*/ "\201Z", /*Z*/ "\001[", /*[*/ "\001\\", /*\*/ "\001]", /*]*/ "\001^", /*^*/ "\001_", /*_ dash*/ "\001`", /*` open*/ "\201a", /*a*/ "\201b", /*b*/ "\201c", /*c*/ "\201d", /*d*/ "\201e", /*e*/ "\201f", /*f*/ "\201g", /*g*/ "\201h", /*h*/ "\201i", /*i*/ "\201j", /*j*/ "\201k", /*k*/ "\201l", /*l*/ "\201m", /*m*/ "\201n", /*n*/ "\201o", /*o*/ "\201p", /*p*/ "\201q", /*q*/ "\201r", /#define INCH 240 /* DASI300S nroff driving tables width and code tables */ struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { /*bset*/ 0, /*breset*/ 0177420, /*Hor*/ INCH/60, /*Vert*/ INCH/48, /*Newline*/ INCH/6, /*Char\001.", /*.*/ "\001/", /*/*/ "\2010", /*0*/ "\2011", /*1*/ "\2012", /*2*/ "\2013", /*3*/ "\2014", /*4*/ "\2015", /*5*/ "\2016", /*6*/ "\2017", /*7*/ "\2018", /*8*/ "\2019", /*9*/ "\001:", /*:*/ "\001;", /*;*/ "\001<", /*<*/ "\001=", /*=*/ "\001>", /*>*/ "\001?", /*?*/ "\001@", /*@*/ "\201A", /*A*/ "\201B", /*B*/ "\201C", /*C*/ "\201D", /*D*/ "\201E", /*E*/ "\201F", /*F*/ "\201G", /*G*/ "\201H", /*H*/ "\201I", /*I*/ "\201J", /*J*/ "\201K", /*K*/ "\201L", /*L*/ "\201M", /*M*/ "\201N", /*N*/ "\201O", /*O*/ "\2016L\017", /*lambda*/ "\201\016M\017", /*mu*/ "\201\016@\017", /*nu*/ "\201\016X\017", /*xi*/ "\201o", /*omicron*/ "\201\016J\017", /*pi*/ "\201\016K\017", /*rho*/ "\201\016Y\017", /*sigma*/ "\201\016I\017", /*tau*/ "\201v", /*upsilon*/ "\201\016U\017", /*phi*/ "\201x", /*chi*/ "\201\016V\017", /*psi*/ "\201\016C\017", /*omega*/ "\201\016G\017", /*Gamma*/ "\201\016W\017", /*Delta*/ "\201\016T\017", /*Theta*/ "\201\016E\017", /*Lambda*/ "\000\0", /*Xi*/ "\201\016P\017", /*Pi*/ "\201\016R\017", /*Sigma*/ ion plus*/ "\001\0338r\0339", /*registered*/ "\001\0338c\0339", /*copyright*/ "\001|", /*box rule */ "\001c\b/", /*cent sign*/ "\000\0", /*dbl dagger*/ "\000\0", /*right hand*/ "\001*", /*left hand*/ "\001*", /*math * */ "\000\0", /*bell system sign*/ "\001|", /*or (was star)*/ "\001O", /*circle*/ "\001|", /*left top (of big curly)*/ "\001|", /*left bottom*/ "\001|", /*right top*/ "\001|", /*right bot*/ "\001|", /*left center of big curly bracket*/ "\001|", /*right center of big curly brack#define INCH 240 /* TTY M37 nroff driving tables width and code tables */ struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { /*bset*/ 0, /*breset*/ 0, /*Hor*/ INCH/10, /*Vert*/ INCH/6, /*Newline*/ INCH/6, /*Char*/ INCH/*r*/ "\201s", /*s*/ "\201t", /*t*/ "\201u", /*u*/ "\201v", /*v*/ "\201w", /*w*/ "\201x", /*x*/ "\201y", /*y*/ "\201z", /*z*/ "\001{", /*{*/ "\001|", /*|*/ "\001}", /*}*/ "\001~", /*~*/ "\000\0", /*nar sp*/ "\001-", /*hyphen*/ "\001o\b+", /*bullet*/ "\002\[]", /*square*/ "\001-", /*3/4 em*/ "\001_", /*rule*/ "\000\0", /*1/4*/ "\000\0", /*1/2*/ "\000\0", /*3/4*/ "\001-", /*minus*/ "\202fi", /*fi*/ "\202fl", /*fl*/ "\202ff", /*ff*/ "\203ffi", /*ffi*/ "\203ffl", /*ffl*/ "\000\0", /*degree*/ "\000*/ INCH/10, /*Em*/ INCH/10, /*Halfline*/ INCH/12, /*Adj*/ INCH/10, /*twinit*/ "\033\006", /*twrest*/ "\033\006", /*twnl*/ "\015\n", /*hlr*/ "\033H", /*hlf*/ "\033h", /*flr*/ "\032", /*bdon*/ "", /*bdoff*/ "", /*ploton*/ "\006", /*plotoff*/ "\033\006", /*up*/ "\032", /*down*/ "\n", /*right*/ " ", /*left*/ "\b", /*codetab*/ #include "code.300" 01P", /*P*/ "\201Q", /*Q*/ "\201R", /*R*/ "\201S", /*S*/ "\201T", /*T*/ "\201U", /*U*/ "\201V", /*V*/ "\201W", /*W*/ "\201X", /*X*/ "\201Y", /*Y*/ "\201Z", /*Z*/ "\001[", /*[*/ "\001\\", /*\*/ "\001]", /*]*/ "\001^", /*^*/ "\001_", /*_ dash*/ "\001`", /*` open*/ "\201a", /*a*/ "\201b", /*b*/ "\201c", /*c*/ "\201d", /*d*/ "\201e", /*e*/ "\201f", /*f*/ "\201g", /*g*/ "\201h", /*h*/ "\201i", /*i*/ "\201j", /*j*/ "\201k", /*k*/ "\201l", /*l*/ "\201m", /*m*/ "\201n", /*n*/ "\201o", /*o*/ "\201p", /*p*/ "\201q", "\000\0", /**/ "\201Y", /*Upsilon*/ "\201\016F\017", /*Phi*/ "\201\016H\017", /*Psi*/ "\201\016Z\017", /*Omega*/ "\000\0", /*square root*/ "\000\0", /*terminal sigma*/ "\000\0", /*root en*/ "\001>\b_", /*>=*/ "\001<\b_", /*<=*/ "\001=\b_", /*identically equal*/ "\001-", /*equation minus*/ "\001=\b~", /*approx =*/ "\001\0339~\0338", /*approximates*/ "\001=\b/", /*not equal*/ "\002->", /*right arrow*/ "\002<-", /*left arrow*/ "\001|\b^", /*up arrow*/ "\000\0", /*down arrow*/ "\001=", /*equatiet*/ "\001|", /*bold vertical*/ "\001|", /*left floor (left bot of big sq bract)*/ "\001|", /*right floor (rb of ")*/ "\001|", /*left ceiling (lt of ")*/ "\001|"}; /*right ceiling (rt of ")*/ 10, /*Em*/ INCH/10, /*Halfline*/ INCH/12, /*Adj*/ INCH/10, /*twinit*/ "", /*twrest*/ "", /*twnl*/ "\n", /*hlr*/ "", /*hlf*/ "", /*flr*/ "", /*bdon*/ "", /*bdoff*/ "", /*ploton*/ "", /*plotoff*/ "", /*up*/ "", /*down*/ "", /*right*/ "", /*left*/ "", /*codetab*/ "\001 ", /*space*/ "\001!", /*!*/ "\001\"", /*"*/ "\001#", /*#*/ "\001$", /*$*/ "\001%", /*%*/ "\001&", /*&*/ "\001'", /*' close*/ "\001(", /*(*/ "\001)", /*)*/ "\001*", /***/ "\001+", /*+*/ "\001,", /*,*/ "\001-", /*- hyphen*/ "\001.", /*.*/ "\\0", /*dagger*/ "\000\0", /*section*/ "\001'", /*foot mark*/ "\001'", /*acute accent*/ "\001`", /*grave accent*/ "\001_", /*underrule*/ "\001/", /*slash (longer)*/ "\000\0", /*half narrow space*/ "\001 ", /*unpaddable space*/ "\000", /*alpha*/ "\000", /*beta*/ "\000", /*gamma*/ "\000", /*delta*/ "\000", /*epsilon*/ "\000", /*zeta*/ "\000", /*eta*/ "\000", /*theta*/ "\201i", /*iota*/ "\201k", /*kappa*/ "\000", /*lambda*/ "\000", /*mu*/ "\000", /*nu*/ "\000", /*xi*/ "\201o", /*omicron*/ "\000", /*pi*/ "\000", /*rho*/ "\000", /*sigma*/ "\000", /*tau*/ "\201v", /*upsilon*/ "\000", /*phi*/ "\201x", /*chi*/ "\000", /*psi*/ "\000", /*omega*/ "\000", /*Gamma*/ "\000", /*Delta*/ "\000", /*Theta*/ "\000", /*Lambda*/ "\000\0", /*Xi*/ "\000", /*Pi*/ "\000", /*Sigma*/ "\000\0", /**/ "\201Y", /*Upsilon*/ "\000", /*Phi*/ "\000", /*Psi*/ "\000", /*Omega*/ "\000\0", /*square root*/ "\000\0", /*terminal sigma*/ "\000\0", /*root en*/ "\001>\b_", /*>=*/ "\001<\b_", /*<=*/ "\001=\b_", /*identically equal*/ "\(of big curly)*/ "\001|", /*left bottom*/ "\001|", /*right top*/ "\001|", /*right bot*/ "\001|", /*left center of big curly bracket*/ "\001|", /*right center of big curly bracket*/ "\001|", /*bold vertical*/ "\001|", /*left floor (left bot of big sq bract)*/ "\001|", /*right floor (rb of ")*/ "\001|", /*left ceiling (lt of ")*/ "\001|"}; /*right ceiling (rt of ")*/ For a description of the terminal driving tables, see ../formatters.tw.h The only ones here that are known to work are tab37 TTY 37 - nroff default tables; postprocessors like "col" depend on control codes produced by this table. tabcar Carousel 300 with Electronic Format Control; uses fine increments for half-line motions and to build Greek character set. termrc shows how to build a new table off programs various postprocessors - u & u tbl source for tbl terms terminal driving tables for nroff tests simple test input to see if nroff still works es. Although dedicating certain access lines to each terminal type is the simplest approach, economy dictates that as many terminal types as possible be served by each group of dedicated lines. The greatest economy occurs when all terminals can use the same group of lines. If different terminal types are to use the same access lines, it is necessary for the system to be able to identify the terminal type. This paper addresses the terminal-type identification problem. .br TERMINAL PROPERTIES .pg While it is oftware, must cope with the terminal's speed, character set, line discipline, special features, lack of 9bo -2- 9* Head title 3 features, and other idiosyncrasies.(3) In many cases, the physical association of such an interface __________ (3)See reference (3) for a more complete description of terminal differences. 9bo -3- 9* Head title 4 with a terminal is dynamic; most general-purpose time-sharing s001-", /*equation minus*/ "\001=\b~", /*approx =*/ "\000\0", /*approximates*/ "\001=\b/", /*not equal*/ "\002->", /*right arrow*/ "\002<-", /*left arrow*/ "\001|\b^", /*up arrow*/ "\000\0", /*down arrow*/ "\001=", /*equation equal*/ "\001x", /*multiply*/ "\001/", /*divide*/ "\001+\b_", /*plus-minus*/ "\001U", /*cup (union)*/ "\000\0", /*cap (intersection)*/ "\000\0", /*subset of*/ "\000\0", /*superset of*/ "\000\0", /*improper subset*/ "\000\0", /* improper superset*/ "\002oo", /*infinitycc -c tab$1.c strip tab$1.o mv tab$1.o $1 termrc 37 termrc car .de x .br .sp extra line .br \&\c 'bp another extra line. .. .em x .lg .pl4i .ll2i .de hd \"HEADER .tl '*''' 'sp |0.5i .tl 'Head title %''' .ft 'ps 'sp |1i .nr x 0 1 .nr y 0-0.5i .if \\n(dn .fz .ns .. .de fo \"FOOTER .nr dn 0 .if \\nx .xf .ch fo -0.5i .ftR 'ps10 'bp .. .de bo .tl 'bo'-%-'' .. .de fn \"BEGIN FOOTNOTE .da FN .ev1 .nh .if !\\n+x-1 .fs .. .de ef \"END FOOTNOTE .br .ev .di .if !\\nx-1 .nr dn +\\n(.v .nr y -\\n(dn .ch fo \\nyu .if \\n(nl+\\n(.v-\\n(.p-\\ny .ch fo \\n(nlu+\\n(.vu .. .de fs \"SEPARthe differences between types that brings about the need for identification, it is often these differences that permit identification. The properties and abilities of terminals may be classified and examined for their effect on the necessity for and the possibility of type indentification. The concern here is with typewriter-like terminals employing asynchronous character communications. The first properties to be enumerated are fundamental ones; i. e, properties that cannot be ignored when communicating wiystems are accessed via switched telephone lines. Although dedicating certain access lines to each terminal type is the simplest approach, economy dictates that as many termi- nal types as possi- ble be served by 9bo -4- 9* Head title 5 each group of dedi- cated lines. The greatest economy oc- curs when all termi- nals can use the same group of lines. If different termi- nal types are to use the same access lines, it is neces- sary P V E K Q W X ^ j Y#define INCH 240 /* DASI450 nroff driving tables width and code tables */ struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { /*bset*/ 0, /*breset*/ 0177420, /*Hor*/ INCH/60, /*Vert*/ INCH/48, /*Newline*/ INCH/6, /*Char*cpall 37 car /usr/lib/term rm 37 car ATOR \l'1i' .br .. .de fz .fn .nf .fy .fi .ef .. .de fx .di fy .. .de xf .ev1 .nf .FN .rm FN .di .fi .ev .. .wh 0 hd .wh -0.5i fo .wh -0.25i bo .ch fo 12i .wh -0.5i fx .ch fo -0.5i .ev1 'ps8 'vs10p .ll1.5i .ev .br Today's increasing abundance of different types of computer terminals(1) .fn .sp (1)See attached list. .ef bodes well for the satisfaction of the diverse needs and desires of computer terminal users.(2) .fn .sp (2)Footnote... .ef Before any new terminal can be connected to a computer system, howevth the terminal. Character code and format. In addition to the character - bit-pattern relationship, this includes(end) for the system to be able to iden- tify the terminal type. This paper addresses the 9bo -5- 9* Head title 6 terminal-type iden- tification problem. TERMINAL PROPERTIES While it is the differences between types that brings about the need for identification, it is often these differences that permit identifica- tion. The proper- ties and abilities of terminals may be classified and exam- 9bo -6- */ "\000", /*partial derivative*/ "\000", /*gradient*/ "\000", /*not*/ "\000", /*integral sign*/ "\000\0", /*proportional to*/ "\000\0", /*empty set*/ "\000\0", /*member of*/ "\001+", /*equation plus*/ "\001r\bO", /*registered*/ "\001c\bO", /*copyright*/ "\001|", /*box rule */ "\001c\b/", /*cent sign*/ "\000\0", /*dbl dagger*/ "\000\0", /*right hand*/ "\001*", /*left hand*/ "\001*", /*math * */ "\000\0", /*bell system sign*/ "\001|", /*or (was star)*/ "\001O", /*circle*/ "\001|", /*left top / INCH/12, /*Em*/ INCH/12, /*Halfline*/ INCH/12, /*Adj*/ INCH/12, /*twinit*/ "\0334\033\037\013", /*twrest*/ "\0334\033\037\015", /*twnl*/ "\015\n", /*hlr*/ "\033D", /*hlf*/ "\033U", /*flr*/ "\033\n", /*bdon*/ "", /*bdoff*/ "", /*ploton*/ "\0333", /*plotoff*/ "\0334", /*up*/ "\033\n", /*down*/ "\n", /*right*/ " ", /*left*/ "\b", /*codetab*/ #include "code.300" Here is the source for nroff, troff, and associated stuff. read_me (lowercase) files are original versions; READ_ME (uppercase) files contain comments on the current Interdata version. doc nroff/troff manual as distributed - this is in troff format and will require some work to use it under nroff. eqn goes with troff - unchanged & untested fonts for troff - u & u cmds source for both nroff and troff, and common suffix table macros several nroff/troff macro packages neqn version of eqn to go with nrer, an appropriate interface must exist.\"xxx This interface, inevitably involving both system hardware and software, must cope with the terminal's speed, character set, line discipline, special features, lack of features, and other idiosyncrasies.(3) .fn .sp (3)See reference (3) for a more complete description of terminal differences. .ef In many cases, the physical association of such an interface with a terminal is dynamic; most general-purpose time-sharing systems are accessed via switched telephone lin* Head title 1 Today's increasing abundance of dif- ferent types of com- puter terminals(1) bodes well for the satisfaction of the diverse needs and desires of computer terminal users.(2) __________ (1)See attached list. (2)Footnote... 9bo -1- 9* Head title 2 Before any new ter- minal can be con- nected to a computer system, however, an appropriate inter- face must exist. This interface, inevitably involving both system hardware and s9* Head title 7 ined for their ef- fect on the necessi- ty for and the pos- sibility of type in- dentification. The concern here is with typewriter-like ter- minals employing asynchronous charac- ter communications. The first properties to be enumerated are fundamental ones; i. e, properties that cannot be ignored 9bo -7- 9* Head title 8 when communicating with the terminal. Character code and format. In addition to the character - bit-pattern rela- tionship, this includes(end) extra line 9bo -8- 9* Head title 9 another extra line. 9bo -9- 9E``u0G F E``uHG) g$H !FgEG%  % gH)gG' g H) )gG)   g H  %) gG$.%)gH! g!G$8gH 6$  gG   FgHE FE '`nG ````wH G F E F`zHE``u0G FE``u$H ````````````g G FE `````````````````````````````````````````````````````````````````r@IAAAAAAAA for the system to be able to iden- tify the terminal type. This paper addresses the Dbo -5- D* Head title 6 terminal-type iden- tification problem. TERMINAL PROPERTIES While it is the dif- ferences between types that brings about the need for identification, it is often these dif- ferences that permit identification. The properties and abil- ities of terminals may be classified and examined for Dbo -6- r;mescf br 3f 2: jsr r5,str;mescb 3: jsr r5,numb;esc jsr r5,str;nl tst escd beq 0f neg esc 0: add esc,esct clr esc 1: jsr pc,prn cmpb r0,$100 bne 1f jsr r5,str;minit jmp loop 1: cmpb r0,$101 bne 1f jsr r5,str;mlr jmp loop 1: cmpb r0,$102 bne 1f jsr r5,str;mur jmp loop 1: cmpb r0,$103 bne 1f jsr r5,str;mum jmp loop 1: cmpb r0,$104 bne 1f jsr r5,str;mlm jmp loop 1: cmpb r0,$105 bne 1f jsr r5,str;mlc clr case jmp loop 1: cmpb r0,$106 bne 1f jsr r5,str;muc mov $100,case j,0f 1: tstb (r1)+ bne 1b sub r2,r1 dec r1 mov r1,1f mov $1,r0 sys write; 0:..; 1:.. mov (sp)+,r0 rts r5 numb: mov r0,-(sp) mov r2,-(sp) mov r3,-(sp) mov *(r5)+,r3 jsr pc,numb1 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r0 rts r5 numb1: clr r2 dvd base,r2 mov r3,-(sp) mov r2,r3 beq 1f jsr pc,numb1 1: add $'0,(sp) mov (sp)+,char mov $1,r0 sys write; char; 1 rts pc atoi: clr -(sp) mov r3,-(sp) clr r3 clr -(sp) movb (r1)+,r0 cmpb r0,$'- bne 2f inc (sp) 1: movb (r1)+,r0 2: sub $@`FRgE``u0 F E``uH.G )%  gH )FE gGF E  ! gH    gG   gH!) =F E$gG  gH'!')gG !gG% $6 gH)FE gG'gH ) )gG   )`b FH E  F`zE``u0G F E``uHG)$. gHFE ) gG $gH.G* Head title 1 Today's increasing abundance of dif- ferent types of com- puter terminals(1) bodes well for the satisfaction of the diverse needs and desires of computer terminal users.(2) __________ (1)See attached list. (2)Footnote... Dbo -1- D* Head title 2 Before any new ter- minal can be connec- ted to a computer system, however, an appropriate inter- face must exist. This interface, inevitably involving both system hardware and sD* Head title 7 their effect on the necessity for and the possibility of type indentifica- tion. The concern here is with typewriter-like ter- minals employing asynchronous charac- ter communications. The first properties to be enumerated are fundamental ones; i. e, properties that cannot be ignored Dbo -7- D* Head title 8 when communicating with the terminal. Character code and format. In addition to the character - bit-pattern mp loop 1: cmpb r0,$107 bne 1f jsr r5,str;mef / jsr r5,str;mesct jsr r5,numb;esct jsr r5,str;nl clr escd jmp loop 1: cmpb r0,$110 bne 1f jsr r5,str;meb / jsr r5,str;mesct jsr r5,numb;esct jsr r5,str;nl inc escd jmp loop 1: cmpb r0,$111 bne 1f jsr r5,str;mstop jmp loop 1: cmpb r0,$112 bne 1f jsr r5,str;mlf jsr r5,numb;leadtot jsr r5,str;nl clr leadmode jmp loop 1: cmpb r0,$114 bne 1f jsr r5,str;mlb jsr r5,numb;leadtot jsr r5,str;nl inc leadmode jmp loop 1: cmpb r0,$100 bne 1'0,r0 cmp r0,$7 bhi 1f inc 4(sp) mpy $8.,r3 add r0,r3 br 1b 1: tst (sp)+ beq 1f neg r3 1: mov r3,r0 mov (sp)+,r3 tst (sp)+ rts pc space: < \0> minit: mesct: mesc: mescf: <\> \0> mescb: <\< \0> nl: <\n\0> mlr: mur: mum: mlm: muc: mlc: mef: <\> mode, \0> meb: <\< mode, \0> mstop: <*****Stop*****\n\0> mlf: mlb: mlead: F `vG E$$$R``mH G F E F`zHE``u0G F E``uHG% ) !gH!'!  gG 'gH' 'g G':4261FE374/7:4.6:>gHFE FEg G!) % gH'FE  gG  FE g H.$FE gG   gH    FE )g GFE)gH) ) oftware, must cope with the terminal's speed, character set, line discipline, special features, lack of Dbo -2- D* Head title 3 features, and other idiosyncrasies.(3) In many cases, the physical association of such an interface __________ (3)See reference (3) for a more complete description of terminal differences. Dbo -3- D* Head title 4 with a terminal is dynamic; most general-purpose time-sharing s rela- tionship, this includes(end) extra line Dbo -8- D* Head title 9 another extra line. Dbo -9- Df jsr r5,str;minit jmp loop 1: mov r0,r1 bic $!360,r1 cmp r1,$100 bne 1f jsr r5,str;milgl jmp loop 1: mov r0,r1 bic $!340,r1 cmpb r1,$140 bne 1f com r0 bic $!37,r0 mov r0,n jsr r5,str;mlead jsr r5,numb;n jsr r5,str;nl tst leadmode beq 0f neg n 0: add n,leadtot jmp loop 1: mov r0,r1 bic $!360,r1 cmpb $120,r1 bne 1f bic $!17,r0 mov r0,n jsr r5,str;msize mov $stab+1,r0 2: cmpb n,(r0)+ beq 2f tstb (r0)+ bne 2b br 3f 2: tst -(r0) movb (r0),pts jsr r5,numb;pts 3: jsr r5,stread \0> milgl: msize: .even pts: 12. stab: /type size table .byte 6.,10 .byte 7.,00 .byte 8.,01 .byte 9.,07 .byte 10.,02 .byte 11.,03 .byte 12.,04 .byte 14.,05 .byte 16.,11 .byte 18.,06 .byte 20.,12 .byte 22.,13 .byte 24.,14 .byte 28.,15 .byte 36.,16 .byte 0,0 .bss leadtot: .=.+2 leadmode: .=.+2 argc: .=.+2 base: .=.+2 x: .=.+2 char: .=.+2 n: .=.+2 case: .=.+2 esc: .=.+2 esct: .=.+2 escd: .=.+2 ibuf: .=.+518. .data wtab: /Graphic Systems Font Table /Commercial Layout /Tim ' gH6F E$) gG)') gH!  gG )gH%  %QkG`vH F E >F EkG  kH$FE R``m G F E F`zH  gG FE$.g H !)!`b G F E F`zHE``u0G F E``uHG)%)gH.$FgEG  g'H$   gG % gH%ystems are accessed via switched telephone lines. Although dedicating certain access lines to each terminal type is the simplest approach, economy dictates that as many ter- minal types as pos- sible be served by Dbo -4- D* Head title 5 each group of dedi- cated lines. The greatest economy oc- curs when all ter- minals can use the same group of lines. If different ter- minal types are to use the same access lines, it is neces- sary /Phototypesetter interpreter mov (sp)+,argc dec argc beq loop tst (sp)+ mov (sp),r1 cmpb (r1)+,$'- bne 1f jsr pc,atoi mov r0,0f dec argc beq loop0 tst (sp)+ 1: mov (sp),r0 jsr r5,fopen; ibuf bec loop0 ex: jsr r5,str;mlt jsr r5,numb;leadtot jsr r5,str;nl clr r0 sys exit mlt: .even loop0: mov ibuf,r0 sys seek; 0:..; 0 loop: jsr r5,getc; ibuf bes ex tstb r0 bpl 1f jsr pc,prn com r0 bic $!177,r0 add r0,esc jmp loop 1: tst esc beq 1f tst escd bne 2f jsr r5,st;nl jmp loop 1: bitb $300,r0 bne 1f bic $!77,r0 add case,r0 mov $wtab+1,r1 2: cmpb r0,(r1)+ beq 3f inc r1 cmp r1,$wtab+192. blo 2b br 1f 3: tst -(r1) movb (r1),r3 mpy pts,r3 sxt r2 dvd $6.,r2 mov r2,n sub $wtab,r1 asr r1 add $040,r1 clr x movb r1,x jsr r5,str;x / jsr r5,str;space / jsr r5,numb;n jsr r5,str;nl jmp loop 1: jsr r5,str;nl jmp loop prn: mov $8.,base mov r0,n jsr r5,numb;n mov $10.,base jsr r5,str;space rts pc str: mov r0,-(sp) mov (r5)+,r1 mov r1,r2 mov r1 t z u { es Roman Regular /Extended Code, ASCII order /Width (6 pt.), Code .byte 15.,0 /space .byte 9.,145 /! .byte 0,0 /" .byte 27.,153 /# .byte 18.,155 /$ .byte 27.,53 /% .byte 28.,50 /& .byte 9.,150 /' * .byte 9.,132 /( .byte 9.,133 /) .byte 16.,122 /* .byte 27.,143 /+ .byte 9.,47 /, .byte 27.,123 /- .byte 9.,44 /. .byte 12.,43 // .byte 18.,110 /0 .byte 18.,111 /1 .byte 18.,112 /2 .byte 18.,113 /3 .byte 18.,114 /4 .byte 18.,115 /5 .byte 18.,116 /6 .byte 18.,117 /7 .byte 18.,120 /8 .byte 18.,121 /9 .byte 9.,142 float paper[256]; struct passwd { char *pw_name; char *pw_passwd; int pw_uid; int pw_gid; char *pw_gecos; char *pw_dir; char *pw_shell; }; int ibuf1[259]; int ibuf2[259]; int *ip1 ibuf1; int *ip2 ibuf2; int pu[2]; char acctname[] "/usr/jfo/tr.acct"; int xxx; main(argc,argv) int argc; char **argv; { register int i; int lastu; register struct passwd *p; char date[40]; float total; if(fopen("/etc/passwd",ip2) <0){ printf("Cannot open /etc/passwd\n"); exit(); } if(argc == 2)acctname[9] = (#define SIGINT 2 #define SIGQIT 3 /* C version of tcatsim */ #define OBSZ 512 #define MAXY 3071 #define US 037 #define GS 035 #define ESC 033 #define FF 014 #define DBL 0200 int pl 11*144; int mpy 1; int div 1; char *ap; int ch; int nonumb; int psize 10; int dfact 1; int ibuf[259]; char obuf[OBSZ]; char *obufp obuf; int esc; int escd; int verd; int esct; int osize 02; int size 02; int rx; int xx 0; int yy MAXY+62+48; int leadtot -31; int ohy -1; int ohx -1; int oxb -1; int oly -1; int olx -1; int tflag; i if(!first && !tflag)kwait(); if(first){ first = 0; yy =+ 62; } init(); continue; case 0101: /*lower rail*/ railmag =& ~01; continue; case 0102: /*upper rail*/ railmag =| 01; continue; case 0103: /*upper mag*/ railmag =| 02; continue; case 0104: /*lower mag*/ railmag =& ~02; continue; case 0105: /*lower case*/ mcase = 0; continue; case 0106: /*upper case*/ mcase = 0100; continue; case 0107: /*escape forward*/ if(pgskip)return; *obufp++ = i; if(obufp >= (obuf + OBSZ))flusho(); } flusho(){ write(od,obuf,obufp-obuf); obufp = obuf; } sendpt(){ int hy,xb,ly,hx,lx; oput(GS); hy = ((yy>>7) & 037); xb = ((xx & 03) + ((yy<<2) & 014) & 017); ly = ((yy>>2) & 037); hx = ((xx>>7) & 037); lx = ((xx>>2) & 037); if(hy != ohy)oput(hy | 040); if(xb != oxb)oput(xb | 0140); if((ly != oly) || (hx != ohx) || (xb != oxb)) oput(ly | 0140); if(hx != ohx)oput(hx | 040); oput(lx | 0100); ohy = hy; oxb = xb; oly = ly;/: .byte 9.,23 /; .byte 0,0 /< .byte 27.,140 /= .byte 0,0 /> .byte 16.,147 /? .byte 36.,131 /@ .byte 29.,103 /A .byte 23.,75 /B .byte 26.,70 /C .byte 29.,74 /D .byte 25.,72 /E .byte 24.,101 /F .byte 30.,65 /G .byte 29.,60 /H .byte 13.,66 /I .byte 16.,105 /J .byte 29.,107 /K .byte 24.,63 /L .byte 35.,62 /M .byte 30.,61 /N .byte 27.,57 /O .byte 22.,67 /P .byte 27.,55 /Q .byte 28.,64 /R .byte 18.,76 /S .byte 24.,56 /T .byte 29.,106 /U .byte 28.,71 /V .byte 36.,104 /W .byte 28.,102 /X .byte 28.,77 /Y .byte 24.,++argv)[0][0]; if(fopen(acctname,ip1) < 0){ printf("Cannot open: %s\n",acctname); exit(); } i=0; while(1){ date[i] = getc(ip1); if(date[i++] == '\n')break; } date[i]=0; while(getn(pu,3) == 3){ paper[pu[1]] =+ pu[0]/1728.; total =+ pu[0]/1728.; lastu = pu[1]; } printf("%s",date); printf("UID Feet of paper\n"); i=0; while(i<256){ if(paper[i++] != 0.0){ while(p=getpwent()){ if(p->pw_uid == (i-1)){ if(lastu == p->pw_uid) printf("_\b"); printf("%s\t%8.1f\n", nt railmag; int lead; int skip; int pgskip; int ksize ';'; int mcase; int stab[]{010,0,01,07,02,03,04,05,0211,06,0212,0213,0214,0215,0216,0217}; int rtab[]{6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 26, 18}; int ktab[]{';',';',';',';',';',';',':',':','9','9','9','9','8','8','8','9'}; int od 1; int first 1; int alpha; extern char *asctab[128]; extern char *spectab[128]; int erase 1; int xxx; int sigint; int sigqit; main(argc,argv) int argc; char **argv; { register i, j; register char *k; extern escd = 0; continue; case 0110: /*escape backward*/ escd = 1; continue; case 0111: /*stop*/ continue; case 0112: /*lead forward*/ verd = 0; continue; case 0113: /*undefined*/ continue; case 0114: /*lead backward*/ verd = 1; continue; case 0115: /*undefined*/ case 0116: case 0117: continue; } if((i & 0340) == 0140){ /*leading*/ lead = (~i) & 037; if(verd)lead = -lead; if((leadtot =+ lead) > pl){ leadtot = lead; oput(US); } } continue; } } ex(); } lig(x) char *x; { register i, j; register char *k; j = 0; k = x; oput(US); oput(*k++); i = psize * 8 * mpy / (div * 6); /* 8/36 em */ while(*k){ xx =+ i; j =+ i; sendpt(); oput(US); oput(*k++); } xx =- j; sendpt(); } init(){ register i; flusho(); if(erase){ oput(ESC); oput(FF); }else erase = 1; oput(ESC); oput(ksize); /*delay about a second*/ /* let the system do it... for(i = 960; i > 0; i--)oput(GS); */ skip = 0; sendpt(); } ex(){ y ohx = hx; olx = lx; alpha = 0; return; } prstr(s) char *s; { register i; for(i=0;*s;i++)s++; write(2,s-i,i); } atoi() { register i, j, acc; int field, digits, *dd, *tscale(); field = digits = acc = 0; a1: while(((j = (i = getch()) - '0') >= 0) && (j <= 9)){ field++; digits++; acc = 10*acc + j; } if(i == '.'){ field++; digits = 0; goto a1; } if(!(ch = i))ch = 'x'; dd = tscale(acc); acc = dd[0]; if((field != digits) && (digits > 0)){ j = 1; while(digits--)j =* 10; acc = 73 /Z .byte 9.,134 /[ .byte 0,0 /\ .byte 9.,135 /] .byte 0,0 /^ .byte 0,0 /_ .byte 0,0 /` .byte 17.,25 /a .byte 19.,12 /b .byte 16.,27 /c .byte 20.,11 /d .byte 17.,31 /e .byte 13.,14 /f .byte 17.,45 /g .byte 21.,01 /h .byte 10.,06 /i .byte 10.,15 /j .byte 20.,17 /k .byte 10.,05 /l .byte 32.,04 /m .byte 21.,03 /n .byte 19.,33 /o .byte 20.,21 /p .byte 19.,42 /q .byte 14.,35 /r .byte 15.,10 /s .byte 12.,02 /t .byte 20.,16 /u .byte 20.,37 /v .byte 27.,41 /w .byte 20.,13 /x .byte 19.,51 /y .byte 16.,07 /z .byte p->pw_name,paper[i-1]); break; } } if(p == 0){ printf("%d\t%8.1f\n", i-1,paper[i-1]); seek(*ip2,0,0); ibuf2[1] = ibuf2[2] = 0; } } } printf("Total\t%8.1f\n",total); } getpwent() { register char *p; register c; static struct passwd passwd; static char line[100]; p = line; while((c=getc(ip2)) != '\n') { if(c <= 0) return(0); if(p < line+98) *p++ = c; } *p = 0; p = line; passwd.pw_name = p; p = pwskip(p); passwd.pw_passwd = p; p = pwskip(p); pex(); while((--argc > 0) && ((++argv)[0][0]=='-')){ switch(argv[0][1]){ case 'p': ap = &argv[0][2]; dfact = 72; if(i = atoi())pl = i/3; continue; case 't': tflag++; continue; case 's': ap = &argv[0][2]; dfact = 1; pgskip = atoi(); continue; default: dfact = 1; ap = &argv[0][1]; if(i = atoi())mpy = i; if(i = atoi())div = i; continue; } } if(argc){ if(fopen(argv[0], ibuf) < 0){ prstr("Cannot open: "); prstr(argv[0]); pr flusho(); if(!tflag)kwait(); yy = MAXY; if(pgskip)--pgskip; init(); continue; } if(skip)continue; if((yy =- (lead<<1)) < 0){ skip++; yy = 0; }else sendpt(); continue; } if((i & 0360) == 0120){ /*size change*/ i =& 017; for(j = 0; i != (stab[j] & 017); j++); osize = size; size = stab[j]; psize = rtab[j]; ksize = ktab[j]; oput(ESC); oput(ksize); i = 0; if(!(osize & DBL) && (size & DBL))i = -55; else if((osize & DBL) && !(size & Dy = MAXY; xx = 0; sendpt(); oput(ESC); oput(';'); oput(US); flusho(); exit(0); } kwait(){ char buf[128]; char *bptr; char c; if(pgskip) return; next: bptr=buf; while((c=readch())&&(c!='\n')) *bptr++=c; *bptr=0; if(bptr!=buf){ bptr = buf; if(*bptr == '!'){unix(&buf[1]); prstr("!\n"); goto next;} else switch(*bptr++){ case 'e': erase = 0; goto next; case 's': ap = &buf[1]; dfact = 1; pgskip = atoi() + 1; goto next; default: prstr("?\n"); goto next; ldiv(dd[1],dd[0],j); } nonumb = !field; ch = 0; return(acc); } int *tscale(n) int n; { register i, j; static int aa[2]; switch(i = getch()){ case 'u': j = 1; break; case 'p': /*Points*/ j = 6; break; case 'i': /*Inches*/ j = 432; break; case 'c': /*Centimeters; should be 170.0787*/ j = 170; break; case 'P': /*Picas*/ j = 72; break; default: j = dfact; ch = i; } aa[0] = n * j; aa[1] = hmul(n,j); return(aa); } getch(){ register i; if(ch){ i = ch0,0 /{ .byte 5.,151 /| .byte 0,0 /} /.byte 11.,40 /~ .byte 0,0 /~ .byte 0,0 /del asswd.pw_uid = atoi(p); p = pwskip(p); passwd.pw_gid = atoi(p); p = pwskip(p); passwd.pw_gecos = p; p = pwskip(p); passwd.pw_dir = p; p = pwskip(p); passwd.pw_shell = p; return(&passwd); } pwskip(ap) char *ap; { register char *p; p = ap; while(*p != ':') { if(*p == 0) return(p); p++; } *p++ = 0; return(p); } getn(p,n) char *p; int n; { register i; for(i=0; i= 0){ if(!i)continue; if(i & 0200){ esc =+ (~i) & 0177; continue; } if(esc){ if(escd)esc = -esc; esct =+ esc; xx =+ (esc*mpy + rx)/div; rx = (esc*mpy + rx)%div; sendpt(); esc = 0; } switch(i){ case 0100: /*init*/ escd = verd = mcase = railmag = xx = 0; yy = MAXY + 48; leadtot = -31; ohy = oxb = oly = ohx = olx = -1; oput(US); flusho(); BL))i = 55; if(escd)i = -i; esc =+ i; continue; } if(i & 0300)continue; i = (i & 077) | mcase; if(railmag != 03)k = asctab[i]; else k = spectab[i]; if(alpha)sendpt(); if(k != -1){ oput(US); while(*k & 0377)oput(*k++); alpha++; continue; }else{ if(railmag != 03){ switch(i){ case 0124: lig("fi"); break; case 0125: lig("fl"); break; case 0126: lig("ff"); break; case 0130: lig("ffl"); break; case 0131: lig("ffi"); break; default: continue; } } else if (c==0) ex(); else return; } unix(line) char line[]; { int rc, status, unixpid; if( (unixpid=fork())==0 ) { signal(SIGINT,sigint); signal(SIGQIT,sigqit); close(0); dup(2); execl("/bin/sh", "-sh", "-c", line, 0); exit(255); } else if(unixpid == -1) return; else{ signal(SIGINT,1); signal(SIGQIT,1); while( (rc = wait(&status)) != unixpid && rc != -1 ) ; signal(SIGINT,ex); signal(SIGQIT,sigqit); } } readch(){ char c; if (read(2,&c,1)<1) c=0; return(c); } oput(i) char i; { ; ch = 0; return(i); } return(*ap++); } char *asctab[128] { "\0", /*blank*/ "h", /*h*/ "t", /*t*/ "n", /*n*/ "m", /*m*/ "l", /*l*/ "i", /*i*/ "z", /*z*/ "s", /*s*/ "d", /*d*/ "b", /*b*/ "x", /*x*/ "f", /*f*/ "j", /*j*/ "u", /*u*/ "k", /*k*/ "\0", /*blank*/ "p", /*p*/ "-", /*_ 3/4 em dash*/ ";", /*;*/ "\0", /*blank*/ "a", /*a*/ "_", /*rule*/ "c", /*c*/ "`", /*` open*/ "e", /*e*/ "\'", /*' close*/ "o", /*o*/ "\0", /*1/4*/ "r", /*r*/ "\0", /*1/2*/ "v", /*v*/ "-", /*- hyphen*/ "w", /*w*/ "q", /*q*/ "/", /*/*/ ".", /*.*/ "g", /*g*/ "\0", /*3/4*/ ",", -sign*/ "\033\016U\033\017", /*down arrow*/ "\0", /*blank*/ "\033\016A\033\017", /*alpha*/ "|", /*or*/ "l\b/", /*chi*/ "\"", /*"*/ "\033\016E\033\017", /*epsilon*/ "=", /*=*/ "\033\016O\033\017", /*omicron*/ "\033\016[\033\017", /*left arrow*/ "\033\016R\033\017", /*rho*/ "\033\016Y\033\017", /*up arrow*/ "\033\016N\033\017", /*tau*/ "_", /*underrule*/ "\\", /*\*/ "I\b\033\016(\033\017", /*Psi*/ "\033\016O\bJ\033\017", /*bell system sign*/ "\033\016W\bX\033\017", /*infinity*/ "`\b/", /*gamma*/ "\033\016X\bF lx -1; int tflag; int ksize ';'; int od 1; int first 1; int alpha; int somode; int ry; int xxx; int sigint; int sigqit; main(argc,argv) int argc; char **argv; { register i, j; extern ex(); while(--argc > 0 && (++argv)[0][0]=='-') switch(argv[0][1]){ case 'p': ap = &argv[0][2]; if(i = atoi()) pl = i; yyll = MAXY + 1 - pl; break; case 't': tflag++; break; default: ap = &argv[0][1]; if(i = atoi())mpy = i; ch = 0; if(i = atoi())div = i; break; ; oput(j); oput(ESC); oput(SI); alpha++; xx =+ 31; } continue; } sendpt(alpha); oput(US); oput(i); if(i>040)xx =+ 31; alpha++; continue; } } xx = XOFF; yy = 0; sendpt(0); oput(US); flusho(); kwait(); ex(); } init(){ register i; ohx = oxb = olx = ohy = oly = -1; xx = XOFF; yy = MAXY; oput(ESC); oput(FF); oput(ESC); oput(ksize); /* for(i = 1; i > 0; i--)oput(GS); /*delay about .001 second*/ sendpt(0); } ex(){ yy = MAXY; xx = 0; szz = yy) < 0)zz = 0; hy = ((zz>>7) & 037); xb = ((xx & 03) + ((zz<<2) & 014) & 017); ly = ((zz>>2) & 037); hx = ((xx>>7) & 037); lx = ((xx>>2) & 037); if(!a){ oput(GS); if(hy != ohy)oput(hy | 040); if(xb != oxb)oput(xb | 0140); if((ly != oly) || (hx != ohx) || (xb != oxb)) oput(ly | 0140); if(hx != ohx)oput(hx | 040); oput(lx | 0100); ohy = hy; oxb = xb; oly = ly; ohx = hx; olx = lx; alpha = 0; } return; } prstr(s) char *s; { register i; for(i=0;*s;i++)s++; write(2,s-i,i); } atoi()/*,*/ "&", /*&*/ "y", /*y*/ "\0", /*blank*/ "%", /*%*/ "\0", /*blank*/ "Q", /*Q*/ "T", /*T*/ "O", /*O*/ "H", /*H*/ "N", /*N*/ "M", /*M*/ "L", /*L*/ "R", /*R*/ "G", /*G*/ "I", /*I*/ "P", /*P*/ "C", /*C*/ "V", /*V*/ "E", /*E*/ "Z", /*Z*/ "D", /*D*/ "B", /*B*/ "S", /*S*/ "Y", /*Y*/ "\0", /*blank*/ "F", /*F*/ "X", /*X*/ "A", /*A*/ "W", /*W*/ "J", /*J*/ "U", /*U*/ "K", /*K*/ "0", /*0*/ "1", /*1*/ "2", /*2*/ "3", /*3*/ "4", /*4*/ "5", /*5*/ "6", /*6*/ "7", /*7*/ "8", /*8*/ "9", /*9*/ "*", /***/ "-", /*minus*/ -1,\033\017", /*improper superset*/ "\033\016A\033\017", /*proportional to*/ "\033\016\\\b]\033\017", /*right hand*/ "\033\016W\033\017", /*omega*/ "\0", /*blank*/ "\033\016G\033\017", /*gradient*/ "\0", /*blank*/ "I\033\016\bO\033\017", /*Phi*/ "O\b=", /*Theta*/ "O\b_", /*Omega*/ "\033\016V\033\017", /*cup (union)*/ "\033\016@\033\017", /*root en*/ "s", /*terminal sigma*/ "\033\016)\bK\033\017", /*Lambda*/ "-", /*minus*/ "\033\016S\bK\033\017", /*Gamma*/ "\033\016i\033\017", /*integral sign*/ "\033\016t\b'\0333\016*\033\017", /*not equal*/ "{", /*{*/ "}", /*}*/ "\'", /*' acute accent*/ "`", /*` grave accent*/ "^", /*^*/ "#", /*sharp*/ "\033\016|\b[\033\017", /*left hand*/ "\033\016c\b_\033\017", /*member of*/ "~", /*~*/ "\033\016O\b/\033\017", /*empty set*/ "\0", /*blank*/ "\033\016%\bM\033\017", /*dbl dagger*/ "|", /*box rule*/ "*", /*asterisk*/ "\033\016Z\bF\033\017", /*improper subset*/ "\033\016O\033\017", /*circle*/ "\0", /*blank*/ "+", /*eqn plus*/ "\033\016]\033\017", /*right arrow*/ "g\b\033\016C\033\01} if(argc){ if(fopen(argv[0], ibuf) < 0){ prstr("Cannot open: "); prstr(argv[0]); prstr("\n"); exit(1); } } sigint=signal(2, ex); sigqit=signal(SIGQIT,1); init(); while((i = getc(ibuf)) >= 0){ switch(i){ case '\014': /*form feed*/ goto x0; case '\n': xx = XOFF; yy =- LINE; alpha = 0; if(yy < yyll){ x0: yy = 0; sendpt(0); oput(US); flusho(); kwait(); init(); } continue; case CR: xx = XOFF; alpha = 0; conendpt(0); oput(ESC); oput(';'); oput(US); flusho(); exit(0); } kwait(){ char buf[128]; char *bptr; char c; next: bptr=buf; while((c=readch())&&(c!='\n')) *bptr++=c; *bptr=0; if(bptr!=buf){ bptr = buf; if(*bptr == '!'){unix(&buf[1]); prstr("!\n"); goto next;} else switch(*bptr++){ default: prstr("?\n"); goto next; } } else if (c==0) ex(); else return; } unix(line) char line[]; { int rc, status, unixpid; if( (unixpid=fork())==0 ) { signal(SIGINT,sigint); signal(SIGQIT,sigqi { register i, j, acc; int field, digits, aa[2]; field = digits = acc = 0; a1: while(((j = (i = getch()) - '0') >= 0) && (j <= 9)){ field++; digits++; acc = 10*acc + j; } if(i == '.'){ field++; digits = 0; goto a1; } if(!(ch = i))ch = 'x'; switch(i = getch()){ case 'i': /*inches*/ j = 6 * LINE; break; case 'l': /*lines*/ j = LINE; break; default: j = LINE; ch = i; } aa[0] = acc * j; aa[1] = hmul(acc,j); acc = aa[0]; if((field != digits) && (digits > 0)){ /*fi*/ -1, /*fl*/ -1, /*ff*/ "\033\016Z\bM\033\017", /*cent sign*/ -1, /*ffl*/ -1, /*ffi*/ "(", /*(*/ ")", /*)*/ "[", /*[*/ "]", /*]*/ "\033\016J\033\017", /*degree*/ "\033\016M\b_\033\017", /*dagger*/ "=", /*=*/ "\033\016O\b&\033\017", /*registered*/ ":", /*:*/ "+", /*+*/ "\0", /*blank*/ "!", /*!*/ "\033\016O\b~\033\017", /*bullet*/ "?", /*?*/ "\'", /*foot mark*/ "|", /*|*/ "\0", /*blank*/ "\033\016O\b#\033\017", /*copyright*/ "\033\016L\033\017", /*square*/ "$" }; /*$*/ char *spectab[128] { "\0", /*blan3\017", /*Pi*/ "\033\016Z\033\017", /*subset of*/ "\033\016X\033\017", /*superset of*/ "\033\016T\033\017", /*approximates*/ "o\b`", /*partial derivative*/ "\033\016H\033\017", /*Delta*/ "\033\016I\b'\033\017", /*square root*/ ">\b\033\016F\b@\033\017", /*Sigma*/ "\033\016T\bF\033\017", /*approx =*/ "\0", /*blank*/ ">", /*>*/ "\033\016_\bF\b@\033\017", /*Xi*/ "<", /*<*/ "/", /*slash (longer)*/ "\033\016C\033\017", /*cap (intersection)*/ "\033\016y\033\017", /*Upsilon*/ "\033\016|\033\017", /*not*/ "|", /*ri7" }; /*section mark*/ tinue; case ' ': /*space*/ xx =+ 31; alpha = 0; continue; case '\t': /*tabstops at 8*31=248*/ j = ((xx-XOFF)/248) + 1; xx =+ j*248 - (xx-XOFF); alpha = 0; continue; case '\b': xx =- 31; alpha = 0; continue; case ESC: switch(i = getc(ibuf)){ case '\014': goto x0; case '7': yy =+ LINE; alpha = 0; continue; case '8': yy =+ (LINE + ry)/2; ry = (LINE + ry)%2; alpha = 0; continue; case '9': t); close(0); dup(2); execl("/bin/sh", "-sh", "-c", line, 0); exit(255); } else if(unixpid == -1) return(0); else{ signal(SIGINT,1); signal(SIGQIT,1); while( (rc = wait(&status)) != unixpid && rc != -1 ) ; signal(SIGINT,ex); signal(SIGQIT,sigqit); } } readch(){ char c; if (read(2,&c,1)<1) c=0; return(c); } oput(i) char i; { *obufp++ = i; if(obufp >= (obuf + OBSZ))flusho(); } flusho(){ write(od,obuf,obufp-obuf); obufp = obuf; } sendpt(a)int a;{ register zz; int hy,xb,ly,hx,lx; if((j = 1; while(digits--)j =* 10; acc = ldiv(aa[1],aa[0],j); } nonumb = !field; return(acc); } getch(){ register i; if(ch){ i = ch; ch = 0; return(i); } return(*ap++); } k*/ "\033\016(\bM\033\017", /*psi*/ "\033\016o\b_\033\017", /*theta*/ "v\b)", /*nu*/ "\033\016V\b,\033\017", /*mu*/ "\033\016)\b?\033\017", /*lambda*/ "\033\016I\033\017", /*iota*/ "S\b\033\016Z\033\017", /*zeta*/ "o\b\'", /*sigma*/ "o\b\033\0165\033\017", /*delta*/ "\033\016b\033\017", /*beta*/ "\033\016e\bc\033\017", /*xi*/ "j\b\033\016C\033\017", /*eta*/ "\033\016O\bM\033\017", /*phi*/ "\033\016(\033\017", /*upsilon*/ "\033\016k\033\017", /*kappa*/ "\0", /*blank*/ "T\b\033\016S\033\017", /*pi*/ "@", /*atght ceiling (rt of ")*/ "|", /*left top (of big curly)*/ "|", /*bold vertical*/ "|", /*left center of big curly bracket*/ "|", /*left bottom*/ "|", /*right top*/ "|", /*right center of big curly bracket*/ "|", /*right bot*/ "|", /*right floor (rb of ")*/ "|", /*left floor (left bot of big sq bract)*/ "|", /*left ceiling (lt of ")*/ "\033\016=\033\017", /*multiply*/ "\033\016+\033\017", /*divide*/ "+\b_", /*plus-minus*/ "\033\016$\033\017", /*<=*/ "\033\016^\033\017", /*>=*/ "=\b_", /*identically equal*/ "\0#define SIGINT 2 #define SIGQIT 3 #define EOR '\n' #define X 0 /* tk.c */ #define OBSZ 512 #define MAXY 3071 #define LINE 47 #define XOFF 248 #define US 037 #define GS 035 #define ESC 033 #define CR 015 #define FF 014 #define SO 016 #define SI 017 int pl 66*LINE; int yyll -1; int mpy 1; int div 1; char *ap; int ch; int nonumb; int dfact 1; int ibuf[259]; char obuf[OBSZ]; char *obufp obuf; int esc; int escd; int verd; int esct; int xx XOFF; int yy MAXY; int ohy -1; int ohx -1; int oxb -1; int oly -1; int o yy =- (LINE - ry)/2; ry = -(LINE - ry)%2; alpha = 0; continue; default: continue; } case SO: somode++; continue; case SI: somode = 0; continue; default: j = 0; if(somode){ switch(i){ case 'C': j='W';break;/*omega*/ case 'S': j='E';break;/*epsilon*/ case 'K': j='R';break;/*rho*/ case 'A': j='A';break;/*alpha*/ default: j = ' '; } if(j){ sendpt(alpha); oput(US); oput(ESC); oput(SO) .fp 1 R .ps 6 .ft 1 .de x \ \\$1 \w"\\$1" .. .nf .x h .x t .x n .x m .x l .x i .x z .x s .x d .x b .x x .x f .x j .x u .x k .x p .x \(em .x ; .x a .x \(ru .x c .x ` .x e .x ' .x o .x \(14 .x r .x \(12 .x v .x \(hy .x w .x q .x / .x \&. .x g .x \(34 .x , .x & .x y .x % .x Q .x T .x O .x H .x N .x M .x L .x R .x G .x I .x P .x C .x V .x E .x Z .x D .x B .x S .x Y .x F .x X .x A .x W .x J .x U .x K .x 0 .x 1 .x 2 .x 3 .x 4 .x 5 .x 6 .x 7 .x 8 .x 9 .x * .x \- .x \(fi .x \(fl .x \(ff .x \(ct .x \(Fl .x \(Fi .x ( .x ) .x [ .x ] .x \(de .x \(dg .x = .x \(rg .x : .x + .x ! .x \(bu .x ? .x \(fm .x | .x \(co .x \(sq .x $ 040]); continue; } if(i == ' '){ printf("12,\t %s\n",nametab[i-040]); continue; } if(i == '-'){ printf("%d,\t %s\n",hyw,nametab[i-040]); continue; } for(j=0; j<102; j++){ if(ascii[j] == i)break; } if(j == 102){ printf("0,"); zero++; if(nametab[i-040]){ printf("\t %s\n",nametab[i-040]); zero = 0; }else if(i < 0177){ printf("\t /*%c*/\n",i); zero = 0; } if(zero && !((i+1)%8)){ printf("\n"); zero = 0; } }else{ if(zero){ zer"/*6*/", "/*7*/", "/*8*/", "/*9*/", "/*:*/", "/*;*/", "/*<*/", "/*=*/", "/*>*/", "/*?*/", "/*@*/", "/*A*/", "/*B*/", "/*C*/", "/*D*/", "/*E*/", "/*F*/", "/*G*/", "/*H*/", "/*I*/", "/*J*/", "/*K*/", "/*L*/", "/*M*/", "/*N*/", "/*O*/", "/*P*/", "/*Q*/", "/*R*/", "/*S*/", "/*T*/", "/*U*/", "/*V*/", "/*W*/", "/*X*/", "/*Y*/", "/*Z*/", "/*[*/", "/*\\*/", "/*]*/", "/*^*/", "/*_*/", "/*` open*/", "/*a*/", "/*b*/", "/*c*/", "/*d*/", "/*e*/", "/*f*/", "/*g*/", "/*h*/", "/*i*/", "/*j*/", "/*k*/", "/*l*/", "/*m*/", "/*pi*/ '*r', 0250, /*rho*/ '*s', 0251, /*sigma*/ '*t', 0252, /*tau*/ '*u', 0253, /*upsilon*/ '*f', 0254, /*phi*/ '*x', 0255, /*chi*/ '*q', 0256, /*psi*/ '*w', 0257, /*omega*/ '*A', 0101, /*Alpha*/ '*B', 0102, /*Beta*/ '*G', 0260, /*Gamma*/ '*D', 0261, /*Delta*/ '*E', 0105, /*Epsilon*/ '*Z', 0132, /*Zeta*/ '*Y', 0110, /*Eta*/ '*H', 0262, /*Theta*/ '*I', 0111, /*Iota*/ '*K', 0113, /*Kappa*/ '*L', 0263, /*Lambda*/ '*M', 0115, /*Mu*/ '*N', 0116, /*Nu*/ '*C', 0264, /*Xi*/ '*O', 0117, /*Omicron*/ '*P', 0265, /*Pi*4, /*equation plus*/ 'rg', 0335, /*registered*/ 'co', 0336, /*copyright*/ 'br', 0337, /*box vert rule*/ 'ct', 0340, /*cent sign*/ 'dd', 0341, /*dbl dagger*/ 'rh', 0342, /*right hand*/ 'lh', 0343, /*left hand*/ '**', 0344, /*math * */ 'bs', 0345, /*bell system sign*/ 'or', 0346, /*or*/ 'ci', 0347, /*circle*/ 'lt', 0350, /*left top (of big curly)*/ 'lb', 0351, /*left bottom*/ 'rt', 0352, /*right top*/ 'rb', 0353, /*right bot*/ 'lk', 0354, /*left center of big curly bracket*/ 'rk', 0355, /*right center of big */ 17, /*e*/ 13+0200, /*f*/ 18+0100, /*g*/ 22+0200, /*h*/ 12+0200, /*i*/ 12+0300, /*j*/ 23+0200, /*k*/ 12+0200, /*l*/ 32, /*m*/ 22, /*n*/ 18, /*o*/ 20+0100, /*p*/ 19+0100, /*q*/ 15, /*r*/ 17, /*s*/ 13+0200, /*t*/ 21, /*u*/ 19, /*v*/ 27, /*w*/ 21, /*x*/ 19+0100, /*y*/ 17, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 28, /*1/4*/ 28, /*1/2*/ 28, /*3/4*/ 36, /*minus*/ 22, /*fi*/ 22, /*fl*/ 23, /: top echo making font table $1 cc -c $1.c strip $1.o mv $1.o /usr/lib/font/$1 shift nif $1x != x goto top o = 0; printf("\n"); } printf("%d",width[j]); if(font[j].ctval)printf("+0%d00, ",font[j].ctval); else printf(",\t "); printf("%s\n",nametab[i-040]); } } } *n*/", "/*o*/", "/*p*/", "/*q*/", "/*r*/", "/*s*/", "/*t*/", "/*u*/", "/*v*/", "/*w*/", "/*x*/", "/*y*/", "/*z*/", "/*{*/", "/*|*/", "/*}*/", "/*~*/", "/*narrow space*/", "/*hyphen*/", "/*bullet*/", "/*square*/", "/*3/4 em*/", "/*rule*/", "/*1/4*/", "/*1/2*/", "/*3/4*/", "/*minus*/", "/*fi*/", "/*fl*/", "/*ff*/", "/*ffi*/", "/*ffl*/", "/*degree*/", "/*dagger*/", "/*section*/", "/*foot mark*/", "/*'*/", "/*`*/", "/*_*/", 0, "/*half nar sp*/", 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,/ '*R', 0120, /*Rho*/ '*S', 0266, /*Sigma*/ '*T', 0124, /*Tau*/ '*U', 0270, /*Upsilon*/ '*F', 0271, /*Phi*/ '*X', 0130, /*Chi*/ '*Q', 0272, /*Psi*/ '*W', 0273, /*Omega*/ 'sr', 0274, /*square root*/ 'ts', 0275, /*terminal sigma*/ 'rn', 0276, /*root en*/ '>=', 0277, /*>=*/ '<=', 0300, /*<=*/ '==', 0301, /*identically equal*/ '~=', 0303, /*approx =*/ 'ap', 0304, /*approximates*/ '!=', 0305, /*not equal*/ '->', 0306, /*right arrow*/ '<-', 0307, /*left arrow*/ 'ua', 0310, /*up arrow*/ 'da', 0311, /*down arrow*/ curly bracket*/ 'bv', 0356, /*bold vertical*/ 'lf', 0357, /*left floor (left bot of big sq bract)*/ 'rf', 0360, /*right floor (rb of ")*/ 'lc', 0361, /*left ceiling (lt of ")*/ 'rc', 0362, /*right ceiling (rt of ")*/ 0,0}; *ff*/ 33, /*ffi*/ 33, /*ffl*/ 15, /*degree*/ 20, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copywrite*/ 0, 19, /*cent*/ }; pC.c~tchar Cw[256-32] { /*Comm I News Condensed made to look like II*/ 12, /*space*/ 8, /*!*/ 0, /*"*/ 0, /*#*/ 16, /*$*/ 24,#include "mkfont1.c" char ibuf[512]; int id; int width[102]; int ascii[102]; int zero; int emw, hyw; int xxx; main(argc,argv) int argc; char **argv; { register i, j; register char *p; while((--argc > 0) && ((++argv)[0][0]=='-')){ switch(argv[0][1]){ default: continue; } } if(argc){ if((id=open(argv[0],0)) < 0){ printf("Cannot open: %s.\n",argv[0]); exit(1); } } j = read(id,ibuf,512); p = ibuf; for(i=0; i<102; i++){ width[i] = atoi(p); while(*p++ != '\n'); } for(i=0; i< struct { int name; int ctval; } font[102] { 'h',2, 't',2, 'n',0, 'm',0, 'l',2, 'i',2, 'z',0, 's',0, 'd',2, 'b',2, 'x',0, 'f',2, 'j',3, 'u',0, 'k',2, 'p',1, 'em',0, ';',0, 'a',0, 'ru',0, 'c',0, '`',0, 'e',0, '\'',0, 'o',0, '14',0, 'r',0, '12',0, 'v',0, 'hy',0, 'w',0, 'q',1, '/',0, '.',0, 'g',1, '34',0, ',',0, '&',0, 'y',1, '%',0, 'Q',3, 'T',2, 'O',2, 'H',2, 'N',2, 'M',2, 'L',2, 'R',2, 'G',2, 'I',2, 'P',2, 'C',2, 'V',2, 'E',2, 'Z',2, 'D',2, 'B',2, 'S',2, 'Y',2, 'F',2, 'X',2, 'A',2, 'W',2, 'J',2, 'U',2, 'K0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, "/*registered*/", "/*copywrite*/", 0, "/*cent*/", }; int chtab [] { '--', 0210, /*font minus*/ 'hy', 0200, /*hyphen*/ 'bu', 0201, /*bullet*/ 'sq', 0202, /*square*/ 'em', 0203, /*3/4em*/ 'ru', 0204, /*rule*/ '14', 0205, /*1/4*/ '12', 0206, /*1/2*/ '34', 0207, /*3/4*/ 'mi', 0302, /*equation minus*/ 'fi', 0211, /*fi*/ 'fl', 0212, /*fl*/ 'ff', 0213, /*ff*/ 'Fi', 0214, /*ffi*/ 'Fl', 0215, /*ffl*/ 'de', 0216, /*degree*/ 'dg', 0217 eB.c~G/*modified for Commercial II*/ char Bw[256-32] { /*Times Bold widths*/ 12, /*space*/ 13, /*!*/ 0, /*"*/ 0, /*#*/ 18, /*$*/ 28, /*%*/ 27, /*&*/ 12, /*' close*/ 16, /*(*/ 16, /*)*/ 18, /***/ 36, /*+*/ 12, /*,*/ 14, /*- hyphen*/ 12, /*.*/ 18, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+0200, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+0200, /*7*/ 19+0200, /*8*/ 19+0200, /*9*/ 13, /*:*/ 13, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 22, /*?*/ 0, /*%*/ 23, /*&*/ 8, /*' close*/ 11, /*(*/ 11, /*)*/ 14, /***/ 27, /*+*/ 8, /*,*/ 10, /*- hyphen*/ 8, /*.*/ 18, /*/*/ 16+0200, /*0*/ 16+0200, /*1*/ 16+0200, /*2*/ 16+0200, /*3*/ 16+0200, /*4*/ 16+0200, /*5*/ 16+0200, /*6*/ 16+0200, /*7*/ 16+0200, /*8*/ 16+0200, /*9*/ 8, /*:*/ 8, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 14, /*?*/ 0, /*@*/ 19+0200, /*A*/ 17+0200, /*B*/ 17+0200, /*C*/ 17+0200, /*D*/ 15+0200, /*E*/ 15+0200, /*F*/ 18+0200, /*G*/ 17+0200, /*H*/ 8+0200, /*I*/ 13+0200, /*J*/ 17+0200, /*K*102; i++){ if(font[i].name < 0177){ ascii[i] = font[i].name; }else{ for(j=0; chtab[j] != 0; j =+ 2){ if(font[i].name == chtab[j])break; } ascii[i] = chtab[j+1] & 0377; if(chtab[j] == 'hy')hyw = width[i]; if(chtab[j] == 'em')emw = width[i]; } } printf("char XXw[256-32] {\t/*XX*/\n"); for(i=040; i<256; i++){ if(i == 0377){ printf("0};\n"); break; } if(i == 0177){ printf("6,\t %s\n",nametab[i-040]); continue; } if(i == 0226){ printf("3,\t %s\n",nametab[i-',2, '0',2, '1',2, '2',2, '3',2, '4',2, '5',2, '6',2, '7',2, '8',2, '9',2, '*',0, '--',0, 'fi',0, 'fl',0, 'ff',0, 'ct',0, 'Fl',0, 'Fi',0, '(',0, ')',0, '[',0, ']',0, 'de',0, 'dg',0, '=',0, 'rg',0, ':',0, '+',0, '!',0, 'bu',0, '?',0, 'fm',0, '|',0, 'co',0, 'sq',0, '$',0}; char *nametab[256-32] { "/*space*/", "/*!*/", "/*\"*/", "/*#*/", "/*$*/", "/*%*/", "/*&*/", "/*' close*/", "/*(*/", "/*)*/", "/***/", "/*+*/", "/*,*/", "/*- hyphen*/", "/*.*/", "/*/*/", "/*0*/", "/*1*/", "/*2*/", "/*3*/", "/*4*/", "/*5*/", , /*dagger*/ 'sc', 0220, /*section*/ 'fm', 0221, /*foot mark*/ 'aa', 0222, /*acute accent*/ 'ga', 0223, /*grave accent*/ 'ul', 0224, /*underrule*/ 'sl', 0225, /*slash (longer)*/ '*a', 0230, /*alpha*/ '*b', 0231, /*beta*/ '*g', 0232, /*gamma*/ '*d', 0233, /*delta*/ '*e', 0234, /*epsilon*/ '*z', 0235, /*zeta*/ '*y', 0236, /*eta*/ '*h', 0237, /*theta*/ '*i', 0240, /*iota*/ '*k', 0241, /*kappa*/ '*l', 0242, /*lambda*/ '*m', 0243, /*mu*/ '*n', 0244, /*nu*/ '*c', 0245, /*xi*/ '*o', 0246, /*omicron*/ '*p', 0247, /'eq', 0312, /*equation equal*/ 'mu', 0313, /*multiply*/ 'di', 0314, /*divide*/ '+-', 0315, /*plus-minus*/ 'cu', 0316, /*cup (union)*/ 'ca', 0317, /*cap (intersection)*/ 'sb', 0320, /*subset of*/ 'sp', 0321, /*superset of*/ 'ib', 0322, /*improper subset*/ 'ip', 0323, /* " superset*/ 'if', 0324, /*infinity*/ 'pd', 0325, /*partial derivative*/ 'gr', 0326, /*gradient*/ 'no', 0327, /*not*/ 'is', 0330, /*integral sign*/ 'pt', 0331, /*proportional to*/ 'es', 0332, /*empty set*/ 'mo', 0333, /*member of*/ 'pl', 033/*@*/ 28+0200, /*A*/ 26+0200, /*B*/ 26+0200, /*C*/ 29+0200, /*D*/ 25+0200, /*E*/ 23+0200, /*F*/ 28+0200, /*G*/ 32+0200, /*H*/ 16+0200, /*I*/ 21+0200, /*J*/ 28+0200, /*K*/ 25+0200, /*L*/ 36+0200, /*M*/ 30+0200, /*N*/ 29+0200, /*O*/ 25+0200, /*P*/ 29+0300, /*Q*/ 28+0200, /*R*/ 23+0200, /*S*/ 25+0200, /*T*/ 29+0200, /*U*/ 27+0200, /*V*/ 36+0200, /*W*/ 27+0200, /*X*/ 28+0200, /*Y*/ 27+0200, /*Z*/ 12, /*[*/ 0, /*\*/ 12, /*]*/ 0, /*^*/ 0, /*_*/ 12, /*` open*/ 19, /*a*/ 19+0200, /*b*/ 16, /*c*/ 19+0200, /*d/ 15+0200, /*L*/ 22+0200, /*M*/ 18+0200, /*N*/ 18+0200, /*O*/ 16+0200, /*P*/ 18+0300, /*Q*/ 17+0200, /*R*/ 17+0200, /*S*/ 17+0200, /*T*/ 17+0200, /*U*/ 17+0200, /*V*/ 24+0200, /*W*/ 16+0200, /*X*/ 17+0200, /*Y*/ 15+0200, /*Z*/ 10, /*[*/ 0, /*\*/ 10, /*]*/ 0, /*^*/ 0, /*_*/ 8, /*` open*/ 14, /*a*/ 15+0200, /*b*/ 14, /*c*/ 15+0200, /*d*/ 14, /*e*/ 11+0200, /*f*/ 14+0100, /*g*/ 14+0200, /*h*/ 8+0200, /*i*/ 8+0300, /*j*/ 14+0200, /*k*/ 8+0200, /*l*/ 22, /*m*/ 14, /*n*/ 15, /*o*/ 15+0100, /*p*/ 15+0100, /*q*/ 10, /*r*/ 14, /*s*/ 12+0200, /*t*/ 14, /*u*/ 14, /*v*/ 20, /*w*/ 13, /*x*/ 14+0100, /*y*/ 12, /*z*/ 0, /*{*/ 5, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 10, /*hyphen*/ 27, /*bullet*/ 36, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 24, /*1/4*/ 24, /*1/2*/ 24, /*3/4*/ 27, /*minus*/ 18, /*fi*/ 18, /*fl*/ 20, /*ff*/ 18, /*ffi*/ 19, /*ffl*/ 15, /*degree*/ 19, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0,3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,6+0200, /*R*/ 22+0200, /*S*/ 24+0200, /*T*/ 28+0200, /*U*/ 28+0200, /*V*/ 36+0200, /*W*/ 27+0200, /*X*/ 27+0200, /*Y*/ 24+0200, /*Z*/ 12, /*[*/ 0, /*\*/ 12, /*]*/ 0, /*^*/ 0, /*_*/ 9, /*` open*/ 18, /*a*/ 19+0200, /*b*/ 16, /*c*/ 19+0200, /*d*/ 17, /*e*/ 13+0200, /*f*/ 20+0100, /*g*/ 19+0200, /*h*/ 10+0200, /*i*/ 12+0300, /*j*/ 20+0200, /*k*/ 10+0200, /*l*/ 29, /*m*/ 19, /*n*/ 17, /*o*/ 19+0100, /*p*/ 19+0100, /*q*/ 16, /*r*/ 15, /*s*/ 14+0200, /*t*/ 19, /*u*/ 19, /*v*/ 27, /*w*/ 19, /*x*/ / 0, /*\*/ 14, /*]*/ 0, /*^*/ 0, /*_*/ 10, /*` open*/ 21, /*a*/ 19+0200, /*b*/ 18, /*c*/ 20+0200, /*d*/ 18, /*e*/ 14+0200, /*f*/ 19+0100, /*g*/ 21+0200, /*h*/ 12+0200, /*i*/ 13+0300, /*j*/ 21+0200, /*k*/ 13+0200, /*l*/ 30, /*m*/ 21, /*n*/ 19, /*o*/ 20+0100, /*p*/ 20+0100, /*q*/ 15, /*r*/ 16, /*s*/ 14+0200, /*t*/ 21, /*u*/ 19, /*v*/ 27, /*w*/ 22, /*x*/ 20+0100, /*y*/ 17, /*z*/ 0, /*{*/ 5, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*22+0200, /*h*/ 10+0200, /*i*/ 10+0300, /*j*/ 21+0200, /*k*/ 10+0200, /*l*/ 31, /*m*/ 22, /*n*/ 21, /*o*/ 22+0100, /*p*/ 22+0100, /*q*/ 14, /*r*/ 20, /*s*/ 12+0200, /*t*/ 22, /*u*/ 19, /*v*/ 28, /*w*/ 20, /*x*/ 20+0100, /*y*/ 18, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 15, /*hyphen*/ 27, /*bullet*/ 36, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 30, /*1/4*/ 30, /*1/2*/ 30, /*3/4*/ 36, /*minus*/ 22, /*fi*/ 22, /*fl*/ 24, /*ff*/ 34, /*ffi*/ 34, /*ffl*/ 14, /*degre0200, /*t*/ 22, /*u*/ 19, /*v*/ 28, /*w*/ 20, /*x*/ 19+0100, /*y*/ 18, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 36, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 30, /*1/4*/ 30, /*1/2*/ 30, /*3/4*/ 36, /*minus*/ 22, /*fi*/ 22, /*fl*/ 24, /*ff*/ 34, /*ffi*/ 34, /*ffl*/ 14, /*degree*/ 20, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0ace*/ 17, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 32, /*1/4*/ 32, /*1/2*/ 32, /*3/4*/ 27, /*minus*/ 24, /*fi*/ 24, /*fl*/ 28, /*ff*/ 38, /*ffi*/ 38, /*ffl*/ 14, /*degree*/ 23, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 21, /*registered*/ 21, /*copywrite*/ 0, 250,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 0, /*registered*/ 0, /*copywrite*/ 0, 0, /*cent*/ 0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; CE.c~L/*modified for Commercial II*/ char CEw[256-32] { /*Century Expanded widths*/ 12, /*space*/ 13, /*!*/ 0, /*"*/ 20, /*#*/ 18, /*$*/ 24, /*%*/ 27, /*&*/ 9, /*' close*/ 15, /*(*/ 15, /*)*/ 16, /***/ 27, /*+*/ 9, /*,*/ 14, /*-20+0100, /*y*/ 17, /*z*/ 0, /*{*/ 5, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 24, /*1/4*/ 24, /*1/2*/ 24, /*3/4*/ 27, /*minus*/ 20, /*fi*/ 20, /*fl*/ 22, /*ff*/ 30, /*ffi*/ 30, /*ffl*/ 13, /*degree*/ 18, /*dagger*/ 0, /*section*/ 8, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,3/4 em*/ 18, /*rule*/ 31, /*1/4*/ 31, /*1/2*/ 31, /*3/4*/ 27, /*minus*/ 23, /*fi*/ 23, /*fl*/ 22, /*ff*/ 19, /*en*/ 33, /*paragraph*/ 15, /*degree*/ 19, /*dagger*/ 0, /*section*/ 8, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 23, /*registered*/ 23, /*copywrite*/ 0, 19, /*cent*/ }; /G.c~G/*modified fe*/ 20, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 21, /*registered*/ 21, /*copywrite*/ 0, 23, /*cent*/ }; pGI.c~@char W10[256-32] { /*Genevia Regular Italic (GI) widths #803-033B*/ 13, /*space*/ 13, /*!*/ 0, /*"*/ 0, /*#*/ 23, /*$*/ 30, /*%*/ 26, /*&*/ 9, /*' close*/ 13, ,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 21, /*registered*/ 21, /*copywrite*/ 0, 23, /*cent*/ }; GM.c~[/*Geneva Medium (similar to Helvetica Medium)*/ char W11[256-32] { /*Geneva Medium widths*/ 14, /*space*/ 14, /*!*/ 0, /*"*/ 0, /*#*/ 25, /*$*/ 29, /*%*/ 27, /*&*/ 10, /*' close*/ 15, /*(*/ 15, /*)*/ 17, /***/ 27, /*+*/ 10, /*,*/ 17, /*- hyphen*/ 10, /*.*/ 17, /*/*/ 25+0200, /*0*/ 25+0200, /*1*/ 25+0200, /*2*/ 25+02, /*cent*/ }; pI.c~E/*modified for Commercial II*/ char Iw[256-32] { /*Times Italic widths*/ 12, /*space*/ 13, /*!*/ 0, /*"*/ 0, /*#*/ 19, /*$*/ 27, /*%*/ 26, /*&*/ 11, /*' close*/ 15, /*(*/ 15, /*)*/ 16, /***/ 36, /*+*/ 11, /*,*/ 13, /*- hyphen*/ 11, /*.*/ 9, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+0200, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+0200, /*7*/ 19+0200, /*8*/ 19+0200, /*9*/ 11, /*:*/ 11, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 20                0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copywrite*/ 0, 18, /*cent*/ }; CK.c~[/*modified for Commercial II*/ char CKw[256-32] { /*Century Bold Italic widths (CK)*/ 12, /*space*/ 14, /*!*/ 0, /*"*/ 0, /*#*/ 19, /*$*/ 31, /*%*/ 30, /*&*/ 10, /*' close*/ 18, /*(*/ 18, /*)*/ 18, /***/ 27, /*+*/ 10, /*,*/ 14, /*- hyphen*/ 10, /*.*/ 11, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+0200, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+020or Commercial II*/ char Gw[256-32] { /*Geneva Regular widths*/ 12, /*space*/ 12, /*!*/ 0, /*"*/ 0, /*#*/ 23, /*$*/ 28, /*%*/ 25, /*&*/ 9, /*' close*/ 13, /*(*/ 13, /*)*/ 16, /***/ 36, /*+*/ 8, /*,*/ 15, /*- hyphen*/ 8, /*.*/ 15, /*/*/ 23+0200, /*0*/ 23+0200, /*1*/ 23+0200, /*2*/ 23+0200, /*3*/ 23+0200, /*4*/ 23+0200, /*5*/ 23+0200, /*6*/ 23+0200, /*7*/ 23+0200, /*8*/ 23+0200, /*9*/ 12, /*:*/ 12, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 25, /*?*/ 0, /*@*/ 25+0200, /*A*/ 26+0200, /*B*/ 27+0200/*(*/ 13, /*)*/ 15, /***/ 36, /*+*/ 8, /*,*/ 14, /*- hyphen*/ 8, /*.*/ 11, /*/*/ 23+0200, /*0*/ 23+0200, /*1*/ 23+0200, /*2*/ 23+0200, /*3*/ 23+0200, /*4*/ 23+0200, /*5*/ 23+0200, /*6*/ 23+0200, /*7*/ 23+0200, /*8*/ 23+0200, /*9*/ 12, /*:*/ 12, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 24, /*?*/ 0, /*@*/ 25+0200, /*A*/ 25+0200, /*B*/ 28+0200, /*C*/ 26+0200, /*D*/ 23+0200, /*E*/ 21+0200, /*F*/ 29+0200, /*G*/ 26+0200, /*H*/ 11+0200, /*I*/ 20+0200, /*J*/ 25+0200, /*K*/ 22+0200, /*L*/ 31+0200, /*M*/ 27+0200, /*3*/ 25+0200, /*4*/ 25+0200, /*5*/ 25+0200, /*6*/ 25+0200, /*7*/ 25+0200, /*8*/ 25+0200, /*9*/ 14, /*:*/ 14, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 27, /*?*/ 0, /*@*/ 27+0200, /*A*/ 27+0200, /*B*/ 29+0200, /*C*/ 28+0200, /*D*/ 24+0200, /*E*/ 23+0200, /*F*/ 29+0200, /*G*/ 27+0200, /*H*/ 12+0200, /*I*/ 22+0200, /*J*/ 27+0200, /*K*/ 23+0200, /*L*/ 32+0200, /*M*/ 28+0200, /*N*/ 30+0200, /*O*/ 25+0200, /*P*/ 30+0300, /*Q*/ 26+0200, /*R*/ 26+0200, /*S*/ 24+0200, /*T*/ 27+0200, /*U*/ 26+0200, /*V*/ 35+0200,, /*?*/ 0, /*@*/ 25+0200, /*A*/ 24+0200, /*B*/ 26+0200, /*C*/ 27+0200, /*D*/ 23+0200, /*E*/ 21+0200, /*F*/ 27+0200, /*G*/ 29+0200, /*H*/ 14+0200, /*I*/ 16+0200, /*J*/ 28+0200, /*K*/ 24+0200, /*L*/ 34+0200, /*M*/ 27+0200, /*N*/ 27+0200, /*O*/ 22+0200, /*P*/ 27+0300, /*Q*/ 27+0200, /*R*/ 20+0200, /*S*/ 23+0200, /*T*/ 28+0200, /*U*/ 25+0200, /*V*/ 36+0200, /*W*/ 24+0200, /*X*/ 24+0200, /*Y*/ 25+0200, /*Z*/ 13, /*[*/ 0, /*\*/ 13, /*]*/ 0, /*^*/ 0, /*_*/ 11, /*` open*/ 19, /*a*/ 18+0200, /*b*/ 15, /*c*/ hyphen*/ 9, /*.*/ 12, /*/*/ 18+0200, /*0*/ 18+0200, /*1*/ 18+0200, /*2*/ 18+0200, /*3*/ 18+0200, /*4*/ 18+0200, /*5*/ 18+0200, /*6*/ 18+0200, /*7*/ 18+0200, /*8*/ 18+0200, /*9*/ 13, /*:*/ 13, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 19, /*?*/ 30, /*@*/ 28+0200, /*A*/ 25+0200, /*B*/ 25+0200, /*C*/ 27+0200, /*D*/ 26+0200, /*E*/ 25+0200, /*F*/ 26+0200, /*G*/ 29+0200, /*H*/ 15+0200, /*I*/ 20+0200, /*J*/ 28+0200, /*K*/ 25+0200, /*L*/ 32+0200, /*M*/ 29+0200, /*N*/ 25+0200, /*O*/ 24+0200, /*P*/ 26+0300, /*Q*/ 20, /*7*/ 19+0200, /*8*/ 19+0200, /*9*/ 13, /*:*/ 13, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 21, /*?*/ 0, /*@*/ 27+0200, /*A*/ 27+0200, /*B*/ 25+0200, /*C*/ 28+0200, /*D*/ 26+0200, /*E*/ 24+0200, /*F*/ 27+0200, /*G*/ 29+0200, /*H*/ 15+0200, /*I*/ 20+0200, /*J*/ 29+0200, /*K*/ 25+0200, /*L*/ 31+0200, /*M*/ 27+0200, /*N*/ 27+0200, /*O*/ 26+0200, /*P*/ 28+0300, /*Q*/ 29+0200, /*R*/ 22+0200, /*S*/ 25+0200, /*T*/ 28+0200, /*U*/ 25+0200, /*V*/ 35+0200, /*W*/ 26+0200, /*X*/ 27+0200, /*Y*/ 24+0200, /*Z*/ 14, /*[*, /*C*/ 26+0200, /*D*/ 24+0200, /*E*/ 22+0200, /*F*/ 29+0200, /*G*/ 27+0200, /*H*/ 11+0200, /*I*/ 20+0200, /*J*/ 26+0200, /*K*/ 22+0200, /*L*/ 32+0200, /*M*/ 27+0200, /*N*/ 29+0200, /*O*/ 24+0200, /*P*/ 29+0300, /*Q*/ 26+0200, /*R*/ 25+0200, /*S*/ 23+0200, /*T*/ 27+0200, /*U*/ 24+0200, /*V*/ 35+0200, /*W*/ 25+0200, /*X*/ 26+0200, /*Y*/ 23+0200, /*Z*/ 12, /*[*/ 0, /*\*/ 12, /*]*/ 0, /*^*/ 0, /*_*/ 9, /*` open*/ 21, /*a*/ 22+0200, /*b*/ 21, /*c*/ 22+0200, /*d*/ 21, /*e*/ 12+0200, /*f*/ 21+0100, /*g*/ 00, /*N*/ 29+0200, /*O*/ 23+0200, /*P*/ 29+0300, /*Q*/ 26+0200, /*R*/ 25+0200, /*S*/ 22+0200, /*T*/ 26+0200, /*U*/ 24+0200, /*V*/ 33+0200, /*W*/ 25+0200, /*X*/ 24+0200, /*Y*/ 23+0200, /*Z*/ 12, /*[*/ 0, /*\*/ 12, /*]*/ 0, /*^*/ 0, /*_*/ 9, /*` open*/ 21, /*a*/ 22+0200, /*b*/ 21, /*c*/ 22+0200, /*d*/ 21, /*e*/ 12+0200, /*f*/ 22+0100, /*g*/ 22+0200, /*h*/ 10+0200, /*i*/ 10+0300, /*j*/ 20+0200, /*k*/ 10+0200, /*l*/ 32, /*m*/ 22, /*n*/ 22, /*o*/ 22+0100, /*p*/ 22+0100, /*q*/ 13, /*r*/ 20, /*s*/ 12+ /*W*/ 26+0200, /*X*/ 25+0200, /*Y*/ 25+0200, /*Z*/ 16, /*[*/ 0, /*\*/ 16, /*]*/ 0, /*^*/ 0, /*_*/ 10, /*` open*/ 22, /*a*/ 23+0200, /*b*/ 22, /*c*/ 23+0200, /*d*/ 22, /*e*/ 14+0200, /*f*/ 23+0100, /*g*/ 22+0200, /*h*/ 11+0200, /*i*/ 11+0300, /*j*/ 22+0200, /*k*/ 11+0200, /*l*/ 32, /*m*/ 22, /*n*/ 23, /*o*/ 23+0100, /*p*/ 23+0100, /*q*/ 15, /*r*/ 21, /*s*/ 14+0200, /*t*/ 22, /*u*/ 20, /*v*/ 30, /*w*/ 21, /*x*/ 21+0100, /*y*/ 20, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 7, /*narrow sp 18+0200, /*d*/ 16, /*e*/ 11+0200, /*f*/ 17+0100, /*g*/ 19+0200, /*h*/ 9+0200, /*i*/ 9+0300, /*j*/ 19+0200, /*k*/ 9+0200, /*l*/ 28, /*m*/ 19, /*n*/ 18, /*o*/ 17+0100, /*p*/ 18+0100, /*q*/ 13, /*r*/ 14, /*s*/ 10+0200, /*t*/ 19, /*u*/ 16, /*v*/ 24, /*w*/ 18, /*x*/ 16+0100, /*y*/ 14, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 13, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 27, /*1/4*/ 27, /*1/2*/ 27, /*3/4*/ 36, /*minus*/ 21, /*fi*/ 21, /*fl*/ 21, /*ff*/ 31, /*ffi*/ 31, /*ffl*/ 15, /*degree*/ 19, /*dagger*/ 0, /*section*/ 7, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copywrite*/ 0, 19, /*cent*/ }; pL.c~^char Lw[256-32] { /*L Geneva Light*/ 12, /*space*/ 11, /*!*/ 0, /*"*/ 0, /*#*/ 21, /*$*/ 27, /*%*/ 25, /*&*0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 21, /*registered*/ 21, /*copywrite*/ 0, 21, /*cent*/ 0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; LI.c~fchar LIw[256-32] { /*LI Geneva Light Italic*/ 12, /*space*/ 12, /*!*/ 0, /*"*/ 0, /*#*/ 21, /*$*/ 27, /*%*/ 26, /*&*/ 7, /*' close*/ 13, /*(*/ 13, /*)*/ 15, /***/ 36, /*+*/ 7, /*,*/ 13, /*- hyphen*/ 7, /*.*/ 7, /*/*/ 21+0200, /*0*/ ered*/ 21, /*copywrite*/ 0, 21, /*cent*/ 0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; PA.c~p/*Commercial II*/ char PAw[256-32] { /*character withs for Palatino 814-007A*/ 12, /*space*/ 12, /*!*/ 0, /*"*/ 0, /*sharp*/ 19, /*$*/ 27, /*%*/ 29, /*&*/ 10, /*' close*/ 14, /*(*/ 14, /*)*/ 16, /***/ 27, /*+*/ 9, /*,*/ 14, /*- hyphen*/ 9, /*.*/ 12, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+020 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copywrite*/ 0, 19, /*cent*/ }; PB.c~/*Commercial II*/ char W14[256-32] { /*character withs for Palatino Bold 814-009A*/ 12, /*space*/ 14, /*!*/ 00, /*"*/ 00, /*sharp*/ 18, /*$*/ 27, /*%*/ 30, /*&*/ 12, /*' close*/ 14, /*(*/ 34, /*ffi*/ 34, /*ffl*/ 15, /*degree*/ 21, /*dagger*/ 00, /*section*/ 9, /*foot mark*/ 00, /*'*/ 00, /*`*/ 00, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copywrite*/ 00, 18, /*cent*/ }; PI.c~/*Commercial II*/ char PIw[256-32] { /*character withs for Palatquare*/ 36, /*3/4 em*/ 18, /*rule*/ 28, /*1/4*/ 28, /*1/2*/ 28, /*3/4*/ 27, /*minus*/ 20, /*fi*/ 20, /*fl*/ 20, /*ff*/ 29, /*ffi*/ 29, /*ffl*/ 14, /*degree*/ 20, /*dagger*/ 00, /*section*/ 10, /*foot mark*/ 00, /*'*/ 00, /*`*/ 00, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, / 7, /*' close*/ 13, /*(*/ 13, /*)*/ 16, /***/ 27, /*+*/ 7, /*,*/ 13, /*- hyphen*/ 7, /*.*/ 10, /*/*/ 21+0200, /*0*/ 21+0200, /*1*/ 21+0200, /*2*/ 21+0200, /*3*/ 21+0200, /*4*/ 21+0200, /*5*/ 21+0200, /*6*/ 21+0200, /*7*/ 21+0200, /*8*/ 21+0200, /*9*/ 11, /*:*/ 11, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 22, /*?*/ 0, /*@*/ 23+0200, /*A*/ 24+0200, /*B*/ 26+0200, /*C*/ 26+0200, /*D*/ 22+0200, /*E*/ 20+0200, /*F*/ 27+0200, /*G*/ 26+0200, /*H*/ 10+0200, /*I*/ 18+0200, /*J*/ 24+0200, /*K*/ 20+0200, /*L21+0200, /*1*/ 21+0200, /*2*/ 21+0200, /*3*/ 21+0200, /*4*/ 21+0200, /*5*/ 21+0200, /*6*/ 21+0200, /*7*/ 21+0200, /*8*/ 21+0200, /*9*/ 11, /*:*/ 11, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 24, /*?*/ 0, /*@*/ 24+0200, /*A*/ 25+0200, /*B*/ 27+0200, /*C*/ 26+0200, /*D*/ 22+0200, /*E*/ 20+0200, /*F*/ 28+0200, /*G*/ 26+0200, /*H*/ 10+0200, /*I*/ 19+0200, /*J*/ 25+0200, /*K*/ 21+0200, /*L*/ 30+0200, /*M*/ 26+0200, /*N*/ 28+0200, /*O*/ 23+0200, /*P*/ 28+0300, /*Q*/ 24+0200, /*R*/ 23+0200, /*S*/ 21+0200, /*T*/ 25+0, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+0200, /*7*/ 19+0200, /*8*/ 19+0200, /*9*/ 12, /*:*/ 12, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 20, /*?*/ 0, /*@*/ 28+0200, /*A*/ 21+0200, /*B*/ 25+0200, /*C*/ 28+0200, /*D*/ 21+0200, /*E*/ 20+0200, /*F*/ 27+0200, /*G*/ 30+0200, /*H*/ 12+0200, /*I*/ 12+0200, /*J*/ 27+0200, /*K*/ 22+0200, /*L*/ 34+0200, /*M*/ 30+0200, /*N*/ 29+0200, /*O*/ 22+0200, /*P*/ 29+0300, /*Q*/ 25+0200, /*R*/ 19+0200, /*S*/ 22+0200, /* 14, /*)*/ 15, /***/ 27, /*+*/ 12, /*,*/ 15, /*- hyphen*/ 10, /*.*/ 13, /*/*/ 18+0200, /*0*/ 18+0200, /*1*/ 18+0200, /*2*/ 18+0200, /*3*/ 18+0200, /*4*/ 18+0200, /*5*/ 18+0200, /*6*/ 18+0200, /*7*/ 18+0200, /*8*/ 18+0200, /*9*/ 14, /*:*/ 15, /*;*/ 00, /*<*/ 27, /*=*/ 00, /*>*/ 21, /*?*/ 00, /*@*/ 28+0200, /*A*/ 22+0200, /*B*/ 25+0200, /*C*/ 29+0200, /*D*/ 21+0200, /*E*/ 20+0200, /*F*/ 28+0200, /*G*/ 30+0200, /*H*/ 14+0200, /*I*/ 14+0200, ino Italic 814-008A*/ 12, /*space*/ 9, /*!*/ 00, /*"*/ 00, /*sharp*/ 18, /*$*/ 28, /*%*/ 27, /*&*/ 9, /*' close*/ 13, /*(*/ 13, /*)*/ 19, /***/ 27, /*+*/ 9, /*,*/ 14, /*- hyphen*/ 9, /*.*/ 12, /*/*/ 18+0200, /*0*/ 18+0200, /*1*/ 18+0200, /*2*/ 18+0200, /*3*/ 18+0200, /*4*/ 18+0200, /*5*/ 18+0200, /*6*/ 18+0200, /*7*/ 18+0200, /*8*/ 18+0200, /*9*/ 9, /*:*/ 9, /*;*/ 00, /*<*/ 27, /*=*/ 00, /*>*/ 14, / /*registered*/ 20, /*copywrite*/ 0, 18, /*cent*/ }; 2R.c~G/*modified for Commercial II*/ char Rw[256-32] { /*Times Roman widths*/ 12, /*space*/ 12, /*!*/ 0, /*"*/ 0, /*#*/ 19, /*$*/ 29, /*%*/ 28, /*&*/ 12, /*' close*/ 16, /*(*/ 16, /*)*/ 16, /***/ 36, /*+*/ 12, /*,*/ 13, /*- hyphen*/ 10, /*.*/ 17, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+0200, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+0200, /*7*/ 19+0200, /*8*/ 19+0200, /*9*/ 10, /**/ 30+0200, /*M*/ 26+0200, /*N*/ 28+0200, /*O*/ 22+0200, /*P*/ 28+0300, /*Q*/ 24+0200, /*R*/ 22+0200, /*S*/ 20+0200, /*T*/ 25+0200, /*U*/ 23+0200, /*V*/ 35+0200, /*W*/ 23+0200, /*X*/ 22+0200, /*Y*/ 22+0200, /*Z*/ 11, /*[*/ 0, /*\*/ 11, /*]*/ 0, /*^*/ 0, /*_*/ 7, /*` open*/ 20, /*a*/ 21+0200, /*b*/ 20, /*c*/ 21+0200, /*d*/ 20, /*e*/ 11+0200, /*f*/ 21+0100, /*g*/ 20+0200, /*h*/ 9+0200, /*i*/ 9+0300, /*j*/ 19+0200, /*k*/ 9+0200, /*l*/ 31, /*m*/ 20, /*n*/ 20, /*o*/ 21+0100, /*p*/ 21+0100, /*q*/ 12, 0200, /*U*/ 22+0200, /*V*/ 32+0200, /*W*/ 22+0200, /*X*/ 22+0200, /*Y*/ 22+0200, /*Z*/ 11, /*[*/ 0, /*\*/ 11, /*]*/ 0, /*^*/ 0, /*_*/ 7, /*` open*/ 21, /*a*/ 22+0200, /*b*/ 20, /*c*/ 22+0200, /*d*/ 20, /*e*/ 12+0200, /*f*/ 22+0100, /*g*/ 21+0200, /*h*/ 9+0200, /*i*/ 9+0300, /*j*/ 20+0200, /*k*/ 9+0200, /*l*/ 31, /*m*/ 21, /*n*/ 21, /*o*/ 22+0100, /*p*/ 22+0100, /*q*/ 13, /*r*/ 19, /*s*/ 12+0200, /*t*/ 21, /*u*/ 18, /*v*/ 27, /*w*/ 19, /*x*/ 18+0100, /*y*/ 18, /*z*/ 0, /*{*/ 2, /*|*/ 0, T*/ 28+0200, /*U*/ 27+0200, /*V*/ 36+0200, /*W*/ 24+0200, /*X*/ 24+0200, /*Y*/ 24+0200, /*Z*/ 13, /*[*/ 0, /*\*/ 13, /*]*/ 0, /*^*/ 0, /*_*/ 10, /*` open*/ 18, /*a*/ 20+0200, /*b*/ 16, /*c*/ 21+0200, /*d*/ 17, /*e*/ 12+0200, /*f*/ 19+0100, /*g*/ 22+0200, /*h*/ 11+0200, /*i*/ 11+0300, /*j*/ 20+0200, /*k*/ 11+0200, /*l*/ 32, /*m*/ 22, /*n*/ 20, /*o*/ 21+0100, /*p*/ 19+0100, /*q*/ 15, /*r*/ 15, /*s*/ 12+0200, /*t*/ 22, /*u*/ 20, /*v*/ 3/*J*/ 28+0200, /*K*/ 22+0200, /*L*/ 36+0200, /*M*/ 30+0200, /*N*/ 29+0200, /*O*/ 22+0200, /*P*/ 29+0300, /*Q*/ 26+0200, /*R*/ 20+0200, /*S*/ 25+0200, /*T*/ 28+0200, /*U*/ 28+0200, /*V*/ 36+0200, /*W*/ 25+0200, /*X*/ 25+0200, /*Y*/ 23+0200, /*Z*/ 13, /*[*/ 00, /*\*/ 13, /*]*/ 00, /*^*/ 0, /*_*/ 12, /*` open*/ 18, /*a*/ 20+0200, /*b*/ 16, /*c*/ 22+0200, /*d*/ 18, /*e*/ 14+0200, /*f*/ 20+0100, /*g*/ 22+0200, /*h*/ 12+0200, /*i*/ 12+0300, /*j*/ 22+0200, /*k*/ 12+0200, /*l*?*/ 00, /*@*/ 27+0200, /*A*/ 21+0200, /*B*/ 24+0200, /*C*/ 27+0200, /*D*/ 20+0200, /*E*/ 18+0200, /*F*/ 26+0200, /*G*/ 27+0200, /*H*/ 12+0200, /*I*/ 12+0200, /*J*/ 25+0200, /*K*/ 20+0200, /*L*/ 36+0200, /*M*/ 28+0200, /*N*/ 27+0200, /*O*/ 20+0200, /*P*/ 27+0300, /*Q*/ 25+0200, /*R*/ 17+0200, /*S*/ 22+0200, /*T*/ 28+0200, /*U*/ 27+0200, /*V*/ 35+0200, /*W*/ 26+0200, /*X*/ 25+0200, /*Y*/ 22+0200, /*Z*/ 14, /*[*/ 00, /*\*/ 14, /*]*/ 00, /*^*/ 0, /*_*/ 9, /*` open*/ 17, /*a*/:*/ 12, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 20, /*?*/ 0, /*@*/ 29+0200, /*A*/ 23+0200, /*B*/ 26+0200, /*C*/ 30+0200, /*D*/ 24+0200, /*E*/ 23+0200, /*F*/ 30+0200, /*G*/ 29+0200, /*H*/ 13+0200, /*I*/ 16+0200, /*J*/ 28+0200, /*K*/ 24+0200, /*L*/ 35+0200, /*M*/ 29+0200, /*N*/ 27+0200, /*O*/ 22+0200, /*P*/ 27+0300, /*Q*/ 27+0200, /*R*/ 20+0200, /*S*/ 24+0200, /*T*/ 29+0200, /*U*/ 27+0200, /*V*/ 36+0200, /*W*/ 28+0200, /*X*/ 27+0200, /*Y*/ 23+0200, /*Z*/ 14, /*[*/ 0, /*\*/ 14, /*]*/ 0, /*^*/ 0, /*_*/ 12, /*r*/ 18, /*s*/ 11+0200, /*t*/ 20, /*u*/ 18, /*v*/ 27, /*w*/ 18, /*x*/ 18+0100, /*y*/ 17, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 13, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 30, /*1/4*/ 30, /*1/2*/ 30, /*3/4*/ 27, /*minus*/ 20, /*fi*/ 20, /*fl*/ 22, /*ff*/ 31, /*ffi*/ 31, /*ffl*/ 14, /*degree*/ 18, /*dagger*/ 0, /*section*/ 8, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 13, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 27, /*1/4*/ 27, /*1/2*/ 27, /*3/4*/ 36, /*minus*/ 21, /*fi*/ 21, /*fl*/ 24, /*ff*/ 33, /*ffi*/ 33, /*ffl*/ 14, /*degree*/ 20, /*dagger*/ 0, /*section*/ 8, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 21, /*regist0, /*w*/ 19, /*x*/ 20+0100, /*y*/ 18, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 27, /*1/4*/ 27, /*1/2*/ 27, /*3/4*/ 27, /*minus*/ 22, /*fi*/ 22, /*fl*/ 23, /*ff*/ 33, /*ffi*/ 33, /*ffl*/ 13, /*degree*/ 22, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0,*/ 32, /*m*/ 22, /*n*/ 20, /*o*/ 22+0100, /*p*/ 20+0100, /*q*/ 15, /*r*/ 16, /*s*/ 13+0200, /*t*/ 22, /*u*/ 21, /*v*/ 31, /*w*/ 19, /*x*/ 21+0100, /*y*/ 18, /*z*/ 00, /*{*/ 2, /*|*/ 00, /*}*/ 00, /*~*/ 6, /*narrow space*/ 15, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 32, /*1/4*/ 32, /*1/2*/ 32, /*3/4*/ 27, /*minus*/ 23, /*fi*/ 23, /*fl*/ 25, /*ff*/ 16+0200, /*b*/ 15, /*c*/ 18+0200, /*d*/ 15, /*e*/ 12+0200, /*f*/ 16+0100, /*g*/ 18+0200, /*h*/ 12+0200, /*i*/ 12+0300, /*j*/ 16+0200, /*k*/ 11+0200, /*l*/ 28, /*m*/ 20, /*n*/ 16, /*o*/ 18+0100, /*p*/ 16+0100, /*q*/ 14, /*r*/ 14, /*s*/ 11+0200, /*t*/ 19, /*u*/ 18, /*v*/ 26, /*w*/ 18, /*x*/ 19+0100, /*y*/ 16, /*z*/ 00, /*{*/ 2, /*|*/ 00, /*}*/ 00, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 27, /*s /*` open*/ 17, /*a*/ 20+0200, /*b*/ 16, /*c*/ 20+0200, /*d*/ 18, /*e*/ 13+0200, /*f*/ 18+0100, /*g*/ 21+0200, /*h*/ 10+0200, /*i*/ 9+0300, /*j*/ 20+0200, /*k*/ 10+0200, /*l*/ 32, /*m*/ 21, /*n*/ 20, /*o*/ 19+0100, /*p*/ 19+0100, /*q*/ 14, /*r*/ 15, /*s*/ 12+0200, /*t*/ 21, /*u*/ 20, /*v*/ 26, /*w*/ 20, /*x*/ 18+0100, /*y*/ 17, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 13, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 29, /*1/4*/ 29, /*1/2*/ 29, /*3/4*/ 36, /*minus*/ 21, /*fi*/ 21, /*fl*/ 24, /*ff*/ 32, /*ffi*/ 32, /*ffl*/ 15, /*degree*/ 20, /*dagger*/ 0, /*section*/ 8, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copywrite*/ 0, 19, /*cent*/ }; pS.c~ /* Modified for Commercial II and with +, -, and = for equations 18, /*down arrow*/ 27, /*equal*/ 27, /*multiply*/ 27, /*divide*/ 36, /*plus-minus*/ 36, /*cup (union)*/ 36, /*cap (intersection)*/ 36, /*subset of*/ 36, /*superset of*/ 36, /*improper subset*/ 36, /*improper superset*/ 34, /*infinity*/ 21, /*partial derivative*/ 36+0200, /*gradient*/ 22, /*not*/ 24, /*integral sign*/ 27, /*proportional to*/ 28, /*empty set*/ 27, /*member of*/ 27, /*plus*/ 0, 0, 0, /*box vert rule (was 2.)*/ 0, 17, /*dbl dagger*/ 42, /*right hand*/ 42, /*left hand*/ 1 21+0100, /*p*/ 21+0100, /*q*/ 14, /*r*/ 16, /*s*/ 12+0200, /*t*/ 22, /*u*/ 22, /*v*/ 29, /*w*/ 22, /*x*/ 22+0100, /*y*/ 19, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 13, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 32, /*1/4*/ 32, /*1/2*/ 32, /*3/4*/ 27, /*minus*/ 24, /*fi*/ 24, /*fl*/ 26, /*ff*/ 37, /*ffi*/ 37, /*ffl*/ 14, /*degree*/ 20, /*dagger*/ 0, /*section*/ 10, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ /*y*/ 16, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 11, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 29, /*1/4*/ 29, /*1/2*/ 29, /*3/4*/ 27, /*minus*/ 19, /*fi*/ 19, /*fl*/ 20, /*ff*/ 28, /*ffi*/ 28, /*ffl*/ 17, /*degree*/ 19, /*dagger*/ 0, /*section*/ 8, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,6, /*3/4 em*/ 18, /*rule*/ 31, /*1/4*/ 31, /*1/2*/ 31, /*3/4*/ 27, /*minus*/ 21, /*fi*/ 21, /*fl*/ 22, /*ff*/ 32, /*ffi*/ 32, /*ffl*/ 15, /*degree*/ 19, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 22, /*registered*/ 22, /*copywrite*/ 0, 24, /*cent*/ 0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0*minus*/ 18, /*fi*/ 18, /*fl*/ 19, /*ff*/ 27, /*ffi*/ 27, /*ffl*/ 14, /*degree*/ 29, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 16, /*registered*/ 16, /*copywrite*/ 0, 21, /*cent*/ }; */ char Sw[256-32] { /*Special font widths*/ 0,0, /*.=Sw+042-40*/ 13, /*"*/ 29, /*#*/ 0,0,0,0, /*.=Sw+074-40*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0, 36, /*<*/ 0, /*.=Sw+076-40*/ 36, /*>*/ 0, /*.=Sw+100-40*/ 36, /*@*/ 0,0,0,0,0,0,0, /*.=Sw+134-40*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0, 15, /*\\*/ 0, /*.=Sw+136-40*/ 15, /*^*/ 18, /*_ underrule*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0, 14, /*{*/ 0, /*.=Sw+175-40*/ 14, /*}*/ 15, /*~*/ 0, /*.=Sw+220-40*/ 0,0,6, /*math * */ 41, /*bell system sign*/ 9, /*or*/ 27, /*circle*/ 9, /*left top (of big curly)*/ 9, /*left bottom*/ 9, /*right top*/ 9, /*right bot*/ 9, /*left center of big curly bracket*/ 9, /*right center of big curly bracket*/ 9, /*bold vertical*/ 9, /*left floor (left bot of big sq bract)*/ 9, /*right floor (rb of ")*/ 9, /*left ceiling (lt of ")*/ 9 }; /*right ceiling (rt of ")*/ SB.c~cchar SBw[256-32] { /*SB Stymie Bold*/ 12, /*space*/ 13, /*!*/ 0, /*"*/ 0, /*#*0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copywrite*/ 0, 25, /*cent*/ 0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; eSI.c~jchar SIw[256-32] { /*SI Stymie Medium Italic*/ 12, /*space*/ 11, /*!*/ 0, /*"*/ 0, /*#*/ 18, /*$*/ 30, /*%*/ 26, /*&*/ 8, /*' close*/ 12, /*(*/ 12, /*)*/ 17, /***/ 27, /*+*/ 8, /*,*/ 11, /*- hyphe 0,0,0,0,0,0,0,0, 0,0,0,0,0, 19, /*registered*/ 19, /*copywrite*/ 0, 18, /*cent*/ 0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0}; SM.c~dchar SMw[256-32] { /*SM Stymie Medium*/ 12, /*space*/ 11, /*!*/ 0, /*"*/ 0, /*#*/ 24, /*$*/ 22, /*%*/ 26, /*&*/ 9, /*' close*/ 13, /*(*/ 13, /*)*/ 13, /***/ 27, /*+*/ 9, /*,*/ 11, /*- hyphen*/ 9, /*.*/ 15, /*/*/ 24+0200, /*0*/ 24+0200, /*1*/ 24+0200, /*2*/ 24+0200, /*3*/ 24+0200, /*4*/ 24+0200, /*5*/ 24+0200, /*6*/,0,0, 0,0,0,0,0,0,0,0}; UD.c~Z/*modified for Commercial II*/ char UDw[256-32] { /*Utica Demibold widths (Utica == Futura)*/ 12, /*space*/ 11, /*!*/ 0, /*"*/ 16, /*0*/ 21, /*$*/ 28, /*%*/ 25, /*&*/ 10, /*' close*/ 14, /*(*/ 14, /*)*/ 13, /***/ 27, /*+*/ 9, /*,*/ 14, /*- hyphen*/ 9, /*.*/ 15, /*/*/ 21+0200, /*0*/ 21+0200, /*1*/ 21+0200, /*2*/ 21+0200, /*3*/ 21+0200, /*4*/ 21+0200, /*5*/ 21+0200, /*6*/ 21+0200, /*7*/ 21+0200, /*8*/ 21+0200, /*9*/ 11, /*:*/ 11, /*;*/ 0, The grammar for eqn is in e.g; don't change it until you're reasonably cocky. Semantic actions for most kinds of things are in e[1256].c; input processing is in e3.c, general control in e4.c (including the main routine), and lexical stuff in elex.c. elex.c includes y.tab.c (from yaccing e.g), so if you change the grammar you have to recompile elex.c. Make a new eqn with yacc e.g cc e*.c -ly -lS The file test1 is a miniature test, small enough that you can understand what it does by eyeballing the output0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 17, /*section*/ 0, /*.=Sw+222-40*/ 10, /*acute accent*/ 10, /*grave accent*/ 18, /*underrule*/ 15, /*slash (longer)*/ 0, /**/ 0, /**/ 24, /*alpha*/ 23+0300, /*beta*/ 23+0100, /*gamma*/ 19+0200, /*delta*/ 18, /*epsilon*/ 18+0300, /*zeta*/ 23+0100, /*eta*/ 19+0200, /*theta*/ 13, /*iota*/ 21, /*kappa*/ 22+0200, /*lambda*/ 25+0100, /*mu*/ 20, /*nu*/ 20+0300, /*xi*/ 20, /*omicron*/ 27, /*pi*/ 21+0100, /*rho*/ 27, /*sigma*/ 20, /*tau*/ 21, /*upsilon*/ 25+0300, /*phi/ 25, /*$*/ 32, /*%*/ 29, /*&*/ 9, /*' close*/ 15, /*(*/ 15, /*)*/ 13, /***/ 27, /*+*/ 9, /*,*/ 13, /*- hyphen*/ 9, /*.*/ 17, /*/*/ 25+0200, /*0*/ 25+0200, /*1*/ 25+0200, /*2*/ 25+0200, /*3*/ 25+0200, /*4*/ 25+0200, /*5*/ 25+0200, /*6*/ 25+0200, /*7*/ 25+0200, /*8*/ 25+0200, /*9*/ 13, /*:*/ 13, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 25, /*?*/ 0, /*@*/ 30+0200, /*A*/ 26+0200, /*B*/ 27+0200, /*C*/ 28+0200, /*D*/ 25+0200, /*E*/ 24+0200, /*F*/ 28+0200, /*G*/ 30+0200, /*H*/ 14+0200, /*I*/ 17+0200, n*/ 7, /*.*/ 7, /*/*/ 18+0200, /*0*/ 18+0200, /*1*/ 18+0200, /*2*/ 18+0200, /*3*/ 18+0200, /*4*/ 18+0200, /*5*/ 18+0200, /*6*/ 18+0200, /*7*/ 18+0200, /*8*/ 18+0200, /*9*/ 11, /*:*/ 11, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 22, /*?*/ 0, /*@*/ 25+0200, /*A*/ 23+0200, /*B*/ 24+0200, /*C*/ 25+0200, /*D*/ 24+0200, /*E*/ 23+0200, /*F*/ 26+0200, /*G*/ 27+0200, /*H*/ 11+0200, /*I*/ 11+0200, /*J*/ 25+0200, /*K*/ 21+0200, /*L*/ 30+0200, /*M*/ 27+0200, /*N*/ 26+0200, /*O*/ 21+0200, /*P*/ 26+0300, /*Q*/ 24+0200, 24+0200, /*7*/ 24+0200, /*8*/ 24+0200, /*9*/ 11, /*:*/ 11, /*;*/ 0, /*<*/ 27, /*=*/ 0, /*>*/ 22, /*?*/ 0, /*@*/ 27+0200, /*A*/ 22+0200, /*B*/ 25+0200, /*C*/ 25+0200, /*D*/ 20+0200, /*E*/ 20+0200, /*F*/ 27+0200, /*G*/ 27+0200, /*H*/ 12+0200, /*I*/ 14+0200, /*J*/ 25+0200, /*K*/ 20+0200, /*L*/ 30+0200, /*M*/ 26+0200, /*N*/ 27+0200, /*O*/ 20+0200, /*P*/ 27+0300, /*Q*/ 23+0200, /*R*/ 18+0200, /*S*/ 21+0200, /*T*/ 26+0200, /*U*/ 25+0200, /*V*/ 32+0200, /*W*/ 26+0200, /*X*/ 25+0200, /*Y*/ 21+0200, /*Z*/ 14/*<*/ 27, /*=*/ 0, /*>*/ 20, /*?*/ 0, /*@*/ 24+0200, /*A*/ 19+0200, /*B*/ 22+0200, /*C*/ 21+0200, /*D*/ 19+0200, /*E*/ 16+0200, /*F*/ 26+0200, /*G*/ 24+0200, /*H*/ 12+0200, /*I*/ 17+0200, /*J*/ 21+0200, /*K*/ 14+0200, /*L*/ 29+0200, /*M*/ 26+0200, /*N*/ 26+0200, /*O*/ 19+0200, /*P*/ 27+0300, /*Q*/ 19+0200, /*R*/ 18+0200, /*S*/ 16+0200, /*T*/ 24+0200, /*U*/ 22+0200, /*V*/ 33+0200, /*W*/ 22+0200, /*X*/ 20+0200, /*Y*/ 22+0200, /*Z*/ 12, /*[*/ 0, /*\*/ 12, /*]*/ 0, /*^*/ 0, /*_*/ 10, /*` open*/ 20, /*. When that works, use the file aip/browman for bigger and more serious testing. Both eqn and neqn have an undocumented option "-" which turns on a fair amount of debugging information related mainly to the heights of various objects. Regrettably, neqn is somewhat different from eqn internally, because it has not yet been converted to use the new standard io. */ 22+0100, /*chi*/ 24+0300, /*psi*/ 25, /*omega*/ 24+0200, /*Gamma*/ 26+0200, /*Delta*/ 28+0200, /*Theta*/ 28+0200, /*Lambda*/ 27+0200, /*Xi*/ 29+0200, /*Pi*/ 25+0200, /*Sigma*/ 0, /**/ 28+0200, /*Upsilon*/ 29+0200, /*Phi*/ 32+0200, /*Psi*/ 36+0200, /*Omega*/ 30, /*square root*/ 18+0100, /*terminal sigma*/ 18, /*root en*/ 36, /*>=*/ 36, /*<=*/ 36, /*identically equal*/ 27, /*minus*/ 36, /*approx =*/ 36, /*approximates*/ 36, /*not equal*/ 36, /*right arrow*/ 36, /*left arrow*/ 18, /*up arrow*//*J*/ 29+0200, /*K*/ 23+0200, /*L*/ 35+0200, /*M*/ 30+0200, /*N*/ 29+0200, /*O*/ 24+0200, /*P*/ 29+0300, /*Q*/ 27+0200, /*R*/ 24+0200, /*S*/ 26+0200, /*T*/ 30+0200, /*U*/ 29+0200, /*V*/ 40+0200, /*W*/ 30+0200, /*X*/ 29+0200, /*Y*/ 25+0200, /*Z*/ 13, /*[*/ 0, /*\*/ 13, /*]*/ 0, /*^*/ 0, /*_*/ 9, /*` open*/ 18, /*a*/ 21+0200, /*b*/ 18, /*c*/ 21+0200, /*d*/ 19, /*e*/ 13+0200, /*f*/ 21+0100, /*g*/ 22+0200, /*h*/ 11+0200, /*i*/ 10+0300, /*j*/ 21+0200, /*k*/ 11+0200, /*l*/ 30, /*m*/ 22, /*n*/ 19, /*o*//*R*/ 21+0200, /*S*/ 22+0200, /*T*/ 25+0200, /*U*/ 25+0200, /*V*/ 33+0200, /*W*/ 25+0200, /*X*/ 25+0200, /*Y*/ 24+0200, /*Z*/ 12, /*[*/ 0, /*\*/ 12, /*]*/ 0, /*^*/ 0, /*_*/ 8, /*` open*/ 16, /*a*/ 19+0200, /*b*/ 17, /*c*/ 18+0200, /*d*/ 18, /*e*/ 11+0200, /*f*/ 19+0100, /*g*/ 19+0200, /*h*/ 10+0200, /*i*/ 10+0300, /*j*/ 18+0200, /*k*/ 10+0200, /*l*/ 28, /*m*/ 19, /*n*/ 18, /*o*/ 19+0100, /*p*/ 19+0100, /*q*/ 12, /*r*/ 14, /*s*/ 10+0200, /*t*/ 19, /*u*/ 18, /*v*/ 27, /*w*/ 18, /*x*/ 18+0100,, /*[*/ 0, /*\*/ 14, /*]*/ 0, /*^*/ 0, /*_*/ 9, /*` open*/ 18, /*a*/ 21+0200, /*b*/ 18, /*c*/ 21+0200, /*d*/ 19, /*e*/ 11+0200, /*f*/ 21+0100, /*g*/ 21+0200, /*h*/ 10+0200, /*i*/ 10+0300, /*j*/ 20+0200, /*k*/ 10+0200, /*l*/ 30, /*m*/ 21, /*n*/ 19, /*o*/ 21+0100, /*p*/ 21+0100, /*q*/ 14, /*r*/ 15, /*s*/ 11+0200, /*t*/ 21, /*u*/ 20, /*v*/ 27, /*w*/ 21, /*x*/ 20+0100, /*y*/ 18, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 11, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 3a*/ 20+0200, /*b*/ 14, /*c*/ 20+0200, /*d*/ 18, /*e*/ 11+0200, /*f*/ 20+0100, /*g*/ 19+0200, /*h*/ 9+0200, /*i*/ 9+0300, /*j*/ 18+0200, /*k*/ 9+0200, /*l*/ 29, /*m*/ 19, /*n*/ 18, /*o*/ 20+0100, /*p*/ 20+0100, /*q*/ 12, /*r*/ 15, /*s*/ 10+0200, /*t*/ 19, /*u*/ 18, /*v*/ 28, /*w*/ 18, /*x*/ 18+0100, /*y*/ 16, /*z*/ 0, /*{*/ 5, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 28, /*1/4*/ 28, /*1/2*/ 28, /*3/4*/ 27, /echo making eqn nyacc e.g ncc -n -s -O -o eqn e*.c -lyy -lS echo Done with eqn; install in /bin or /usr/bin .nf .EQ x .EN .sp .EQ alpha ~ beta ~ sum ~ int ~ pi ~ partial .EN .sp .EQ x sub i .EN .sp .EQ x sub i sup k .EN .sp .EQ a over bc .EN .sp .EQ a over b+c .EN .sp .EQ x sup 2 over a sup 2 ~=~ y sup 2 over b sup 2 .EN .sp .EQ sum from i=0 to n x .EN .sp .EQ pile {a above b above c} .EN .sp .EQ left [ cpile {abcdef above b above cd} right ] .EN .sp .EQ sqrt x ~~~ sqrt {ax sup 2 + bx+c} .EN | rpile MQ list MQ1 ={ lpile('R', $1, ct); ct = $1; } | pile MQ list MQ1 ={ lpile('-', $1, ct); ct = $1; } | box sub box sbox %prec SUB ={ shift2($1, $3, $4); } | box sub box %prec SUB ={ bshiftb($1, $2, $3); } | box sup box %prec SUP ={ bshiftb($1, $2, $3); } | int sub box sbox %prec SUB ={ integral($1, $3, $4); } | int sub box %prec SUB ={ integral($1, $3, 0); } | int sup box %prec SUP ={ integral($1, 0, $3); } | int ={ integral($1, 0, 0); } | left eqn right ={ paren($1, $2, $3); } | pbo | ITALIC ={ setfont(ITAL); } | BOLD ={ setfont(BLD); } | FONT text ={ setfont($2->c1); } ; sub : SUB ={ shift(1); } ; sup : SUP ={ shift(-1); } ; pbox : MQ eqn MQ1 ={ $$ = $2; } | QTEXT ={ text('q',$1); } | CONTIG ={ text('c',$1); } | SPACE ={ text('~', $1); } | THIN ={ text('^', $1); } | TAB ={ text('\t', $1); } | SUM ={ funny('S'); } | PROD ={ funny('P'); } /* | INT ={ funny('I'); } */ | UNION ={ funny('U'); } | INTER ={ funny('A'); } /* intersection */ ; text : CONTIG | QTEXT | SPAC*/ re0.c~#include "e.h" int dbg; /* debugging print if non-zero */ int lp[80]; /* stack for things like piles and matrices */ int ct; /* pointer to lp */ int used[100]; /* available registers */ int ps; /* default init point size */ int deltaps 3; /* default change in ps */ int gsize 10; int gfont '2'; /* italic */ int ft; /* default font */ FILE *curfile; /* current input file */ int ifile; int linect; /* line number in file */ int eqline; /* line where eqn started */ int svargc; cha of main box */ d1 = VERT( (effps2*6)/2 ); shval = - d1 + h2 - b2; if( d1+b1 > h2 ) /* move little sub down */ shval = b1-b2; ebase[yyval] = b1 + max(0, h2-b1-d1); eht[yyval] = h1 + max(0, h2-b1-d1); if (rfont[p1] == ITAL && lfont[p2] == ROM) sh1 = "\\|"; if (rfont[p2] == ITAL) sh2 = "\\|"; } else { /* superscript */ /* 4/10 up main box */ d1 = VERT( (effps*6*2)/10 ); ebase[yyval] = b1; shval = -VERT( (4 * (h1-b1)) / 10 ) - b2; if( VERT(4*(h1-b1)/10) + h2 < h1-b1 ) /* raisefor roman, italic, bold */ yyval = ft; ft = ch1; printf(".ft %c\n", ch1); if(dbg)printf(".\tsetfont %c\n", ch1); } font(p1, p2) int p1, p2; { /* old font in p1, new in ft */ yyval = p2; lfont[yyval] = rfont[yyval] = ft==ITAL ? ITAL : ROM; if(dbg)printf(".\tb:fb: S%d <- \\f%c S%d \\f%c b=%d,h=%d,lf=%c,rf=%c\n", yyval, ft, p2, p1, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]); printf(".ds %d \\f%c\\*(%d\\f%c\n", yyval, ft, p2, p1); ft = p1; printf(".ft %c\n", ft); } fatbox(p) int pee.g~\{# #include "e.h" # int fromflg 0; \} %term CONTIG QTEXT SPACE THIN TAB %term MATRIX LCOL CCOL RCOL COL %term MARK LINEUP %term SUM INT PROD UNION INTER %term LPILE PILE CPILE RPILE ABOVE %term DEFINE TDEFINE NDEFINE DELIM GSIZE GFONT INCLUDE %right FROM TO %left OVER SQRT %right SUP SUB %right SIZE FONT ROMAN ITALIC BOLD FAT %right UP DOWN BACK FWD %left MQ MQ1 %left LEFT RIGHT %right DOT DOTDOT HAT TILDE BAR UNDER VEC DYAD %% stuff : eqn ={ putout($1); } | error ={ ex | box from box tbox %prec FROM ={ fromto($1,$3,$4); fromflg=0; } | box to box %prec TO ={ fromto($1, 0, $3); } | box diacrit ={ diacrit($1,$2); } | fwd box %prec UP ={ move(0,$1,$2); } | up box %prec UP ={ move(1,$1,$2); } | back box %prec UP ={ move(2,$1,$2); } | down box %prec UP ={ move(3,$1,$2); } | matrix MQ collist MQ1 ={ matrix($1,$3); } ; int : INT ={ setintegral(); } ; fwd : FWD text ={ $$ = numb($1); } ; up : UP text ={ $$ = numb($1); } ; back : BACK text ={ $$ = numb($1); } ; down  $ *   % +  & ,  ! ' -  " ( .  # ) / 0 6 < B 1 7 = C 2 8 > D 3 9 ? E 4 : @ F 5 ; A G H N T Z I O U [ J P V \ K Q W ] L R X ^ M S Y _ ` f l rr **svargv; int eht[100]; int ebase[100]; int lfont[100]; int rfont[100]; int tht[30]; int tbase[30]; int eqnreg, eqnht; int lefteq '\0'; /* left in-line delimiter */ int righteq '\0'; /* right in-line delimiter */ int lastchar; /* last character read by lex */ e1.c~-# include "e.h" boverb(p1, p2) int p1, p2; { int h, b, treg, d; treg = oalloc(); yyval = p1; d = (ps*6*3) / 10; /* 0.3m */ h = eht[p1] + eht[p2] + VERT(d); b = eht[p2] - d; if(dbg)printf(".\tb:bob: S%d <- S%d over little super */ shval = -(h1-b1) + h2-b2 - d1; eht[yyval] = h1 + max(0, h2-VERT((6*(h1-b1))/10)); if (rfont[p1] == ITAL) sh1 = "\\|"; } if(dbg)printf(".\tb:b shift b: S%d <- S%d vert %d S%d vert %d; b=%d, h=%d\n", yyval, p1, shval, p2, -shval, ebase[yyval], eht[yyval]); printf(".as %d \\v'%du'\\s-%d%s\\*(%d%s\\s+%d\\v'%du'\n", yyval, shval, diffps, sh1, p2, sh2, diffps, -shval); ps =+ deltaps; if (rfont[p2] == ITAL) rfont[p1] = 0; else rfont[p1] = rfont[p2]; ofree(p2); } eqnbox(; { int sh; yyval = p; sh = ps / 4; nrwid(p, ps, p); printf(".ds %d \\*(%d\\h'-\\n(%du+%du'\\*(%d\n", p, p, p, sh, p); if(dbg)printf(".\tfat %d, sh=%d\n", p, sh); } shift(p1) int p1; { ps =- deltaps; yyval = p1; if(dbg)printf(".\tshift: %d;ps=%d\n", yyval, ps); } sqrt(p2) int p2; { int nps; nps = ((eht[p2]*9)/10+5)/6; yyval = p2; eht[yyval] = VERT( (nps*6*12)/10 ); if(dbg)printf(".\tsqrt: S%d <- S%d;b=%d, h=%d\n", yyval, p2, ebase[yyval], eht[yyval]); if (rfont[yyval] == ITAL) printf("rror(!FATAL, "syntax error"); } | ={ eqnreg = 0; } ; eqn : box | eqn box ={ eqnbox($1, $2, 0); } | eqn lineupbox ={ eqnbox($1, $2, 1); } | LINEUP ={ lineup(0, 0); } ; lineupbox : LINEUP box ={ $$ = $2; } ; matrix : MATRIX ={ $$ = ct; } ; collist : column | collist column ; column : lcol MQ list MQ1 ={ column('L',$1,$3); } | ccol MQ list MQ1 ={ column('C',$1,$3); } | rcol MQ list MQ1 ={ column('R',$1,$3); } | col MQ list MQ1 ={ column('-',$1,$3); } ; lcol : LCOL ={ $$ = ct++; } ; ccol : C : DOWN text ={ $$ = numb($1); } ; diacrit : HAT ={ $$ = 'H'; } | VEC ={ $$ = 'V'; } | DYAD ={ $$ = 'Y'; } | BAR ={ $$ = 'B'; } | UNDER ={ $$ = 'N'; } /* under bar */ | DOT ={ $$ = 'D'; } | TILDE ={ $$ = 'T'; } | DOTDOT ={ $$ = 'U'; } /* umlaut = double dot */ ; from : FROM ={ $$=ps; ps =- 3; fromflg = 1; if(dbg)printf(".\tfrom: old ps %d, new ps %d, fflg %d\n", $$,ps,fromflg); } ; to : TO ={ $$=ps; if(fromflg==0)ps =- 3; if(dbg)printf(".\tto: old ps %d, new ps %d\n",$$,ps); } ; E ={ $$ = & "\\|\\|"; } | THIN ={ $$ = & "\\|"; } ; %% e.h~#include #define FATAL 1 #define ROM '1' #define ITAL '2' #define BLD '3' #define VERT(n) ((((n)+1)/3)*3) extern int dbg; extern int ct; extern int lp[]; extern int used[]; /* available registers */ extern int ps; /* dflt init pt size */ extern int deltaps; /* default change in ps */ extern int gsize; /* global size */ extern int gfont; /* global font */ extern int ft; /* dflt font */ extern FILE *curfile; /* S%d; b=%d, h=%d\n", yyval, p1, p2, b, h); nrwid(p1, ps, p1); nrwid(p2, ps, p2); printf(".nr %d \\n(%d\n", treg, p1); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, treg, treg, p2); printf(".nr %d \\n(%d+\\s%d.5m\\s0\n", treg, treg, ps); printf(".ds %d \\v'%du'\\h'\\n(%du-\\n(%du/2u'\\*(%d\\\n", yyval, eht[p2]-ebase[p2]-d, treg, p2, p2); printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\*(%d\\\n", p2, p1, -(eht[p2]-ebase[p2]+d+ebase[p1]), p1); printf("\\h'-\\n(%du-\\n(%du/2u+.1m'\\v'%du'\\l'\\n(%dup1, p2, lu) { int b, h, sh; yyval = p1; b = max(ebase[p1], ebase[p2]); eht[yyval] = h = b + max(eht[p1]-ebase[p1], eht[p2]-ebase[p2]); ebase[yyval] = b; if(dbg)printf(".\te:eb: S%d <- S%d S%d; b=%d, h=%d\n", yyval, p1, p2, b, h); if (rfont[p1] == ITAL && lfont[p2] == ROM) sh = "\\|"; else sh = ""; if (lu) { printf(".nr %d \\w'\\s%d\\*(%d%s'\n", p1, ps, p1, sh); printf(".ds %d \\h'|\\n(97u-\\n(%du'\\*(%d\n", p1, p1, p1); } printf(".as %d \"%s\\*(%d\n", yyval, sh, p2); rfont[p1] = rf.as %d \\|\n", yyval); nrwid(p2, ps, p2); printf(".ds %d \\v'%du'\\s%d\\v'-.2m'\\(sr\\l'\\n(%du\\(rn'\\v'.2m'\\s%d", yyval, ebase[p2], nps, p2, ps); printf("\\v'%du'\\h'-\\n(%du'\\*(%d\n", -ebase[p2], p2, p2); } lpile(type, p1, p2) int type, p1, p2; { int bi, hi, i, gap, h, b, j, nlist, nlist2, mid; yyval = oalloc(); gap = VERT( (ps*6*4)/10 ); /* 4/10 m between blocks */ if( type=='-' ) gap = 0; nlist = p2 - p1; nlist2 = (nlist+1)/2; mid = p1 + nlist2 -1; h = 0; for( i=p1; ic1; } | LEFT MQ ={ $$ = '{'; } ; right : RIGHT text ={ $$ = $2->c1; } | RIGHT MQ1 ={ $$ = '}'; } | ={ $$ = 0; } ; list : eqn ={ lp[ct++] = $1; } | list ABOVE eqn ={ lp[ct++] = $3; } ; lpile : LPILE ={ $$=ct; } ; cpile : CPILE ={ $$=ct; } ; pile : PILE ={ $$=ct; } ; rpile : RPILE ={ $$=ct; } ; size : SIZE text ={ $$=ps; if ($2->c1 == '+') ps =+ numb($2); else if ($2->c1 == '-') ps =- numb($2); else ps = numb($2); } ; font : ROMAN ={ setfont(ROM); } current input file */ extern int ifile; /* input file number */ extern int linect; /* line number in current file */ extern int eqline; /* line where eqn started */ extern int svargc; extern char **svargv; extern int eht[]; extern int ebase[]; extern int lfont[]; extern int rfont[]; struct { char c1; char c2; }; extern int yyval; extern int *yypv; extern int yylval; extern int tht[]; extern int tbase[]; extern int eqnreg, eqnht; extern int lefteq, righteq; extern int lastchar; /* last character read by lex -.2m'\\h'.1m'\\v'%du'\n", treg, p1, ebase[p1]+d, treg, d); ebase[yyval] = b; eht[yyval] = h; lfont[yyval] = rfont[yyval] = 0; ofree(p2); ofree(treg); } bshiftb(p1, dir, p2) int p1, dir, p2; { int shval, sh1, sh2, effps, effps2, d1, h1, b1, h2, b2, h; int diffps; yyval = p1; h1 = eht[p1]; b1 = ebase[p1]; h2 = eht[p2]; b2 = ebase[p2]; effps = ps>6 ? ps : 6; effps2 = (ps+deltaps)>6 ? ps+deltaps : 6; diffps = deltaps; sh1 = sh2 = ""; if( dir > 0 ) { /* subscript */ /* top 1/2m above bottomont[p2]; ofree(p2); } size(p1, p2) int p1, p2; { /* old size in p1, new in ps */ yyval = p2; if(dbg)printf(".\tb:sb: S%d <- \\s%d S%d \\s%d; b=%d, h=%d\n", yyval, ps, p2, p1, ebase[yyval], eht[yyval]); printf(".ds %d \\s%d\\*(%d\\s%d\n", yyval, ps, p2, p1); ps = p1; } numb(p1) char *p1; { int i, n, c; for(i=n=0; (c=p1[i++])!='\0'; ) if( c>='0' && c<='9' ) n = n*10 + c-'0'; if(dbg)printf(".\tnumb: %s %d\n", p1, n); return( n ); } setfont(ch1) char ch1; { /* use number '1', '2', '3' eht[lp[i]]; eht[yyval] = h + (nlist-1)*gap; b = 0; for( i=p2-1; i>mid; i-- ) b =+ eht[lp[i]] + gap; ebase[yyval] = (nlist%2) ? b + ebase[lp[mid]] : b - VERT( (ps*6*5)/10 ) - gap; if(dbg) { printf(".\tS%d <- %c pile of:", yyval, type); for( i=p1; i\\n(%d .nr %d \\n(%d\n", lp[i], yyval, yyval, lp[i]); } printf(".ds %d \\v'%du'\\h'%du*\\n(%du'\\\n", yyval, ebase[yyval], type==ROM ? 1 : 0, yyval); for(i = p2-1; i >=p1; i--) { hi = eht[lp[i]]; bi = ebase[lp[i]]; switch(type) { case 'L': printf("\\v'%du'\\*(%d\\h'-\\n(%du'\\v'0-%du'\\\n", -bi, lp[i], lp[i], hi-bi+gap); continue; case ROM: printf("\\v'%du'\\h'-\\n(%du'\\*(%d\\v'0-%du'\\\n", -bi, lp[i], lp[i], hi-bi+gap); continue; case 'C': case '-': printf("\\v'%du'\\h'\\n(%du2, treg, treg, p2); printf(".as %d \\v'%du'\\s%d\\*(%d\\h'-\\n(%du'\\v'%du'\\\n", p1, subsh, effps, p2, p2, -subsh+supsh); printf("\\s%d\\*(%d\\h'-\\n(%du+\\n(%du'\\s%d\\v'%du'\n", effps, p3, p3, treg, effps2, -supsh); ps =+ deltaps; if (rfont[p2] == ITAL) rfont[yyval] = 0; /* lie */ ofree(p2); ofree(p3); ofree(treg); } |e2.c~# include "e.h" fromto(p1, p2, p3) int p1, p2, p3; { int h, b, h1, b1, pss; yyval = oalloc(); lfont[yyval] = rfont[yyval] = 0; h1 = eht[yyval] 2; v = b1 - h1/2 + VERT( (ps*6*4)/10 ); printf(".ds %d \\|\\v'%du'", yyval, v); switch( leftc ) { case 'n': /* nothing */ case '\0': break; case 'f': /* floor */ if (n <= 1) printf("\\(lf"); else brack(m, "\\(bv", "\\(bv", "\\(lf"); break; case 'c': /* ceiling */ if (n <= 1) printf("\\(lc"); else brack(m, "\\(lc", "\\(bv", "\\(bv"); break; case '{': printf("\\b'\\(lt"); for(j = 0; j < m; j =+ 2) printf("\\(bv"); printf("\\(lk"); for(j = 0; j < m;x(eht[p1]-ebase[p1]-6*ps,0))); /* vertical shift if high */ printf(".if \\n(ct>1 .nr 10 \\n(10+\\s%d.25m\\s0\n", effps); printf(".nr %d \\s%d.1m\\s0\n", t, effps); /* horiz shift if high */ printf(".if \\n(ct>1 .nr %d \\s%d.15m\\s0\n", t, effps); switch(type) { case 'V': /* vec */ printf(".ds %d \\v'-.4m'\\s%d\\(->\\s0\\v'.4m'\n", c, max(effps-3, 6)); break; case 'Y': /* dyad */ printf(".ds %d \\v'-.4m'\\s%d\\z\\(<-\\(->\\s0\\v'.4m'\n", c, max(effps-3, 6)); break; case 'H': /* hat */ == 3) eht[yyval] =+ a; if( dir==1 ) ebase[yyval] =- a; else if( dir==3 ) ebase[yyval] =+ a; */ if(dbg)printf(".\tmove %d dir %d amt %d; h=%d b=%d\n", p, dir, amt, eht[yyval], ebase[yyval]); } funny(n) int n; { int f, t; yyval = oalloc(); t = 'S'; switch(n) { case 'S': f = "\\(*S"; break; case 'U': f = "\\(cu"; break; case 'A': /* intersection */ f = "\\(ca"; break; case 'P': f = "\\(*P"; break; case 'I': f = "\\(is"; t = 'I'; printf(".ds %d \\s%d\\v'.1m'\\s+4%s\\s-4\\v'-"nothing", "", "cdot", "\\v'-.3m'.\\v'.3m'", "times", "\\(mu", "del", "\\(gr", "grad", "\\(gr", "...", "\\v'-.3m'\\ .\\ .\\ .\\ \\v'.3m'", ",...,", ",\\ .\\ .\\ .\\ ,\\|", "alpha", "\\(*a", "beta", "\\(*b", "gamma", "\\(*g", "GAMMA", "\\(*G", "delta", "\\(*d", "DELTA", "\\(*D", "epsilon", "\\(*e", "omega", "\\(*w", "OMEGA", "\\(*W", "lambda", "\\(*l", "LAMBDA", "\\(*L", "mu", "\\(*m", "nu", "\\(*n", "theta", "\\(*h", "THETA", "\\(*H", "phi", "\\(*f", "PHI", "\\(*F", "pi", "\\(*p", -\\n(%du/2u'\\*(%d", -bi, yyval, lp[i], lp[i]); printf("\\h'-\\n(%du-\\n(%du/2u'\\v'0-%du'\\\n", yyval, lp[i], hi-bi+gap); continue; } } printf("\\v'%du'\\h'%du*\\n(%du'\n", eht[yyval]-ebase[yyval]+gap, type!=ROM ? 1 : 0, yyval); for( i=p1; i0 ) { nrwid(p2, pss, p2); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p2, yyval, yyval, p2); eht[yyval] =+ eht[p2]; b = eht[p2]; } if( p3>0 ) { nrwid(p3, pss, p3); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p3, yyval, yyval, p3); eht[yyval] =+ eht[p3]; } printf(".ds %d ", yyval); /* bottom of middle box */ if( p2>0 ) { printf("\\v'%du'\\h'\\n(%du-\\n(%du/2u'\\s%d\ j =+ 2) printf("\\(bv"); printf("\\(lb'"); break; case '(': brack(m, "\\(lt", "\\(bv", "\\(lb"); break; case '[': brack(m, "\\(lc", "\\(bv", "\\(lf"); break; case '|': brack(m, "|", "|", "|"); break; default: brack(m, &leftc, &leftc, &leftc); break; } printf("\\v'%du'\\*(%d", -v, p1); if( rightc ) { printf("\\|\\v'%du'", v); switch( rightc ) { case 'f': /* floor */ if (n <= 1) printf("\\(rf"); else brack(m, "\\(bv", "\\(bv", "\\(rf"); b printf(".ds %d ^\n", c); break; case 'T': /* tilde */ printf(".ds %d ~\n", c); break; case 'D': /* dot */ printf(".ds %d \\s%d\\v'-.67m'.\\v'.67m'\\s0\n", c, effps); break; case 'U': /* umlaut = dotdot */ printf(".ds %d \\s%d\\v'-.67m'..\\v'.67m\\s0'\n", c, effps); break; case 'B': /* bar */ printf(".ds %d \\s%d\\v'.18m'\\h'.05m'\\l'\\n(%du-.1m\\(rn'\\h'.05m'\\v'-.18m'\\s0\n", c, effps, p1); break; case 'N': /* under */ printf(".ds %d \\l'\\n(%du\\(ul'\n", c, p1.1m'\\s%d\n", yyval, ps, f, ps); eht[yyval] = VERT( (((ps+4)*12)/10)*6 ); ebase[yyval] = VERT( (ps*6*3)/10 ); break; default: t = 0; } if( t == 'S' ) { printf(".ds %d \\s%d\\v'.3m'\\s+5%s\\s-5\\v'-.3m'\\s%d\n", yyval, ps, f, ps); eht[yyval] = VERT( (ps+5)*6 -(ps*6*2)/10 ); ebase[yyval] = VERT( (ps*6*3)/10 ); } if(dbg)printf(".\tfunny: S%d <- %s; h=%d b=%d\n", yyval, f, eht[yyval], ebase[yyval]); lfont[yyval] = rfont[yyval] = ROM; } integral(p, p1, p2) { if (p1 != 0) print"PI", "\\(*P", "sigma", "\\(*s", "SIGMA", "\\(*S", "xi", "\\(*c", "XI", "\\(*C", "zeta", "\\(*z", "iota", "\\(*i", "eta", "\\(*y", "kappa", "\\(*k", "rho", "\\(*r", "tau", "\\(*t", "omicron", "\\(*o", "upsilon", "\\(*u", "UPSILON", "\\(*U", "psi", "\\(*q", "PSI", "\\(*Q", "chi", "\\(*x", "and", "\\fRand\\fP", "for", "\\fRfor\\fP", "if", "\\fRif\\fP", "Re", "\\fRRe\\fP", "Im", "\\fRIm\\fP", "sin", "\\fRsin\\fP", "cos", "\\fRcos\\fP", "tan", "\\fRtan\\fP", "arc", "\\fRarc\\fP", "sinh\n", yyval, p1, p2, p3); effps = (ps+deltaps)>6 ? ps+deltaps:6; eht[p3] = h3 = VERT( (eht[p3] * effps) / (ps>6 ? ps : 6) ); ps =+ deltaps; effps2 = (ps+deltaps)>6 ? ps+deltaps:6; h1 = eht[p1]; b1 = ebase[p1]; h2 = eht[p2]; b2 = ebase[p2]; b3 = ebase[p3]; d1 = VERT( (effps2*6)/2 ); subsh = -d1+h2-b2; if( d1+b1 > h2 ) /* move little sub down */ subsh = b1-b2; supsh = -VERT( (4*(h1-b1))/10 ) - b3; d2 = VERT( (effps*6*2)/10 ); if( VERT(4*(h1-b1)/10)+h3 < h1-b1 ) supsh = -(h1-b1) + (h3-b3) - d2;\*(%d\\s%d", eht[p2]-ebase[p2]+b1, yyval, p2, pss, p2, ps); printf("\\h'-\\n(%du-\\n(%du/2u'\\v'%du'\\\n", yyval, p2, -(eht[p2]-ebase[p2]+b1)); } printf("\\h'\\n(%du-\\n(%du/2u'\\*(%d\\h'\\n(%du-\\n(%du/2u'\\\n", yyval, p1, p1, yyval, p1); if( p3>0 ) { printf("\\v'%du'\\h'-\\n(%du-\\n(%du/2u'\\s%d\\*(%d\\s%d\\h'\\n(%du-\\n(%du/2u'\\v'%du'\\\n", -(h1-b1+ebase[p3]), yyval, p3, pss, p3, ps, yyval, p3, (h1-b1+ebase[p3])); } printf("\n"); ebase[yyval] = b + b1; if(dbg)printf(".\tfrom toreak; case 'c': /* ceiling */ if (n <= 1) printf("\\(rc"); else brack(m, "\\(rc", "\\(bv", "\\(bv"); break; case '}': printf("\\b'\\(rt"); for(j = 0; j< m; j =+ 2)printf("\\(bv"); printf("\\(rk"); for(j = 0; j< m; j =+ 2) printf("\\(bv"); printf("\\(rb'"); break; case ']': brack(m, "\\(rc", "\\(bv", "\\(rf"); break; case ')': brack(m, "\\(rt", "\\(bv", "\\(rb"); break; case '|': brack(m, "|", "|", "|"); break; default: ); printf(".nr %d 0\n", t); printf(".nr 10 0-%d\n", -ebase[p1]); break; } nrwid(c, ps, c); if (lfont[p1] != ITAL) printf(".nr %d 0\n", t); printf(".as %d \\h'-\\n(%du-\\n(%du/2u+\\n(%du'\\v'0-\\n(10u'\\*(%d", p1, p1, c, t, c); printf("\\v'\\n(10u'\\h'-\\n(%du+\\n(%du/2u-\\n(%du'\n", c, p1, t); if (type != 'N') eht[p1] =+ VERT( (6*ps*15) / 100); /* 0.15m */ if(dbg)printf(".\tdiacrit: %c over S%d, lf=%c, rf=%c, h=%d,b=%d\n", type, p1, lfont[p1], rfont[p1], eht[p1], ebase[p1]); ofreef(".ds %d \\h'-0.4m'\\v'0.4m'\\*(%d\\v'-0.4m'\n", p1, p1); if (p2 != 0) printf(".ds %d \\v'-0.3m'\\*(%d\\v'0.3m'\n", p2, p2); if (p1 != 0 & p2 != 0) shift2(p, p1, p2); else if (p1 != 0) bshiftb(p, 1, p1); else if (p2 != 0) bshiftb(p, -1, p2); if(dbg)printf(".\tintegral: S%d; h=%d b=%d\n", p, eht[p], ebase[p]); lfont[p] = ROM; } setintegral() { int f; yyval = oalloc(); f = "\\(is"; printf(".ds %d \\s%d\\v'.1m'\\s+4%s\\s-4\\v'-.1m'\\s%d\n", yyval, ps, f, ps); eht[yyval] = VERT( (((ps", "\\fRsinh\\fP", "coth", "\\fRcoth\\fP", "tanh", "\\fRtanh\\fP", "cosh", "\\fRcosh\\fP", "lim", "\\fRlim\\fP", "log", "\\fRlog\\fP", "max", "\\fRmax\\fP", "min", "\\fRmin\\fP", "ln", "\\fRln\\fP", "exp", "\\fRexp\\fP", "det", "\\fRdet\\fP", 0, 0 }; int csp; int psp; #define CSSIZE 400 char cs[420]; int lf, rf; /* temporary spots for left and right fonts */ text(t,p1) int t; char *p1; { int i,j,c; yyval = oalloc(); ebase[yyval] = 0; eht[yyval] = VERT(6 * ((ps>6)?ps:6)); /* ht in machine u eht[yyval] = h1 + max(0, h3-VERT( (6*(h1-b1))/10 )) + max(0, h2-b1-d1); ebase[yyval] = b1+max(0, h2-b1-d1); if (rfont[p1] == ITAL && lfont[p2] == ROM) printf(".ds %d \\|\\*(%d\n", p2, p2); if (rfont[p2] == ITAL) printf(".as %d \\|\n", p2); nrwid(p2, effps, p2); if (rfont[p1] == ITAL && lfont[p3] == ROM) printf(".ds %d \\|\\|\\*(%d\n", p3, p3); else printf(".ds %d \\|\\*(%d\n", p3, p3); nrwid(p3, effps, p3); printf(".nr %d \\n(%d\n", treg, p3); printf(".if \\n(%d>\\n(%d .nr %d \\n(%d\n", p: S%d <- %d f %d t %d; h=%d b=%d\n", yyval, p1, p2, p3, eht[yyval], ebase[yyval]); ofree(p1); if( p2>0 ) ofree(p2); if( p3>0 ) ofree(p3); } paren(leftc, p1, rightc) int p1, leftc, rightc; { int n, m, h1, j, b1, v; h1 = eht[p1]; b1 = ebase[p1]; yyval = p1; lfont[yyval] = rfont[yyval] = 0; n = (h1+(6*ps-1))/(6*ps); if( n<2 ) n = 1; m = n-2; if( leftc=='{' || rightc == '}' ){ n = n%2 ? n : ++n; if( n<3 ) n=3; m = n-3; } eht[yyval] = VERT(6 * ps * n); ebase[yyval] = b1 + (eht[yyval]-h1)/ brack(m, &rightc, &rightc, &rightc); break; } printf("\\v'%du'", -v); } printf("\n"); if(dbg)printf(".\tcurly: h=%d b=%d n=%d v=%d l=%c, r=%c\n", eht[yyval], ebase[yyval], n, v, leftc, rightc); } brack(m, t, c, b) int m; char *t, *c, *b; { int j; printf("\\b'%s", t); for( j=0; j=", "\\(>=", "<=", "\\(<=", "==", "\\(==", "!=", "\\(!=", "+-", "\\(+-", "->", "\\(->", "<-", "\\(<-", "<<", "<\\h'-.3m'<", ">>", ">\\h'-.3m'>", "inf", "\\(if", "infinity", "\\(if", "partial", "\\(pd", "half", "\\fR\\(12\\fP", "prime", "\\fR\\(fm\\fP", "approx", "\\v'-.2m'\\z\\(ap\\v'.25m'\\(ap\\v'-.05m'", nits */ lfont[yyval] = rfont[yyval] = ROM; if( t=='q' ) j = p1; else if ( t == '~' ) j = &"\\|\\|"; else if ( t == '^' ) j = &"\\|"; else if ( t == '\t' ) j = &"\\t"; else if( (i=lookup(p1,restab))>=0 ) { j = restab[i].resval; } else { lf = rf = 0; for( csp=psp=0; (c=p1[psp++])!='\0'; ){ rf = trans(c, p1); if (lf == 0) lf = rf; /* save first */ if( csp>CSSIZE ) error(FATAL,"converted token %.25s... too long",p1); } cs[csp] = '\0'; j = cs; lfont[yyval] = lf; rfont[yyval] = rf; } if(dbg)printf(".\t%ctext: S%d <- %s; b=%d,h=%d,lf=%c,rf=%c\n", t, yyval, j, ebase[yyval], eht[yyval], lfont[yyval], rfont[yyval]); printf(".ds %d \"%s\n", yyval, j); } trans(c,p1) int c; char *p1; { int f; f = ROM; switch( c){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ':': case ';': case '!': case '%': case '(': case '[': case ')': case ']': if (rf == ITAL) shim(); roman(c); break; case '.': if (rf == R+] = c; f = ft==ITAL ? ITAL : ROM; break; } return(f); } shim() { cs[csp++] = '\\'; cs[csp++] = '|'; } roman(c) int c; { cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = ROM; cs[csp++] = c; cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P'; } name4(c1,c2) int c1,c2; { cs[csp++] = '\\'; cs[csp++] = '('; cs[csp++] = c1; cs[csp++] = c2; } e4.c~# include "e.h" # define SIGPIPE 13 /* troff has stopped reading */ #define MAXLINE 600 /* maximum input line */ char in[MAXLINE]f(".rm %d \n", ds); do{ if (*in) printf(".as %d \"%s\n", ds, in); init(); yyparse(); if (eqnreg > 0) { printf(".as %d \\*(%d\n", ds, eqnreg); ofree(eqnreg); } printf(".ps \\n(99\n.ft \\n(98\n"); } while ((t=getline(in)) == lefteq); if (*in) printf(".as %d \"%s", ds, in); printf(".ps \\n(99\n.ft \\n(98\n"); printf("\\*(%d\n", ds); ofree(ds); } putout(p1) int p1; { extern int gsize, gfont; int before, after; if(dbg)printf(".\tanswer <- S%d, h=%d,b=%d\n",p1, eht[p1], ebase[p1])rintf("\nfile %s, between lines %d and %d\n", svargv[ifile], eqline, linect); fprintf(stderr, "eqn: "); if (fatal>0) fprintf(stderr, "fatal error: "); fprintf(stderr, s1, s2); fprintf(stderr, "\nfile %s, between lines %d and %d\n", svargv[ifile], eqline, linect); if (fatal > 0) eqnexit(1); } e5.c~#include "e.h" mark(p1) int p1; { printf(".ds %d \\k(97\\*(%d\n", p1, p1); yyval = p1; if(dbg)printf(".\tmark %d\n", p1); } lineup(p1, p2) { yyval = oalloc(); printf(".dmber of definitions */ struct { char *nptr; /* name pointer */ char *sptr; /* defining string */ } deftab[MAXDEFS]; int defptr 0; /* next free slot in deftab */ struct { char *key; int keyval; } keytab[] { "sub", SUB, "sup", SUP, ".EN", 0, "from", FROM, "to", TO, "sum", SUM, "hat", HAT, "vec", VEC, "dyad", DYAD, "dot", DOT, "dotdot", DOTDOT, "bar", BAR, "tilde", TILDE, "under", UNDER, "prod", PROD, "int", INT, "integral", INT, "union", UNION, "inter", INTER, "pile", PILE, "lpile", case '}': return(MQ1); case '"': for (sp=0; (c=gtc())!='"'; ) { if(c !='\\')token[sp++]=c; else { if((c=gtc())!= '"')token[sp++]='\\'; token[sp++] = c; } if (sp>=SSIZE) error(FATAL,"quoted string %.20s... too long", token); } token[sp]='\0'; yylval= &token[0]; return(QTEXT); } if (c==righteq) return('\0'); getstr(token, c); if(dbg)printf(".\tlex token = |%s|\n", token); if((type = lookup(token,deftab)) >= 0) { putbak(' '); pbstr(deftab[type].sptr); putbak(' '); OM) roman(c); else cs[csp++] = c; f = rf; break; case '|': if (rf == ITAL) shim(); shim(); roman(c); shim(); break; case '=': if (rf == ITAL) shim(); name4('e','q'); break; case '+': if (rf == ITAL) shim(); name4('p', 'l'); break; case '>': case '<': if (rf == ITAL) shim(); if( p1[psp]=='=' ){ /* look ahead for == <= >= */ name4(c,'='); psp++; } else { cs[csp++] = c; } break; case '-': if (rf == ITAL) shim(); if( p1[psp]=='>' ){ nam; /* input buffer */ int eqnexit(); int noeqn; main(argc,argv) int argc; char *argv[];{ eqnexit(eqn(argc, argv)); } eqnexit(n) { #ifdef gcos if (n) fprintf(stderr, "run terminated due to eqn error\n"); exit(0); #endif exit(n); } eqn(argc,argv) int argc; char *argv[];{ int i, type; #ifdef unix signal(SIGPIPE, &eqnexit); #endif setfile(argc,argv); while ((type=getline(in)) != EOF) { eqline = linect; if (in[0]=='.' && in[1]=='E' && in[2]=='Q') { for (i=11; i<100; used[i++]=0); printf(; eqnht = eht[p1]; printf(".ds %d \\x'0'", p1); /* suppposed to leave room for a subscript or superscript */ before = eht[p1] - ebase[p1] - VERT((ps*6*12)/10); if (before > 0) printf("\\x'0-%du'", before); printf("\\f%c\\s%d\\*(%d\\s\\n(99\\f\\n(98",gfont,gsize,p1); after = ebase[p1] - VERT((ps*6*2)/10); if (after > 0) printf("\\x'%du'", after); putchar('\n'); eqnreg = p1; } max(i,j) int i,j; { return (i>j ? i : j); } oalloc() { int i; for (i=11; i<100; i++) if (used[i]++ == 0) return(is %d \\h'|\\n(97u'\n", yyval); if(dbg)printf(".\tlineup %d and %d\n", p1, p2); } e6.c~6#include "e.h" column(type, p1, p2) int type, p1, p2; { int i, n; lp[p1] = ct - p1 - 1; if( dbg ){ printf(".\t%c column of", type); for( i=p1+1; i'); psp++; } else { name4('m','i'); } break; case '/': if (rf == ITAL) shim(); name4('s','l'); break; case '~': case ' ': shim(); shim(); break; case '^': shim(); break; case '\\': /* troff - pass 2 or 3 more chars */ if (rf == ITAL) shim(); cs[csp++] = c; cs[csp++] = c = p1[psp++]; cs[csp++] = p1[psp++]; if( c=='(' ) cs[csp++] = p1[psp++]; if( c=='*' && cs[csp-1] == '(' ){ cs[csp++] = p1[psp++]; cs[csp++] = p1[psp++]; } break; case '\'': cs[csp++] "%s",in); printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n"); init(); yyparse(); if (eqnreg>0) { printf(".nr %d \\w'\\*(%d'\n", eqnreg, eqnreg); printf(".if \\n(%d>\\n(.l .tm too-long eqn, file %s, between lines %d-%d\n", eqnreg, svargv[ifile], eqline, linect); printf(".if %d>\\n(.v .ne %du\n", eqnht, eqnht); printf(".rn %d 10\n", eqnreg); if(!noeqn)printf("\\*(10\n"); } printf(".ps \\n(99\n.ft \\n(98\n"); printf(".EN"); if (lastchar == EOF) { putchar('\n'); br); error( FATAL, "no eqn strings left", i); } ofree(n) int n; { used[n] = 0; } setps(p) int p; { printf(".ps %d\n", p); } nrwid(n1, p, n2) int n1, p, n2; { printf(".nr %d \\w'\\s%d\\*(%d'\n", n1, p, n2); } setfile(argc, argv) int argc; char *argv[]; { svargc = --argc; svargv = argv; while (svargc > 0 && svargv[1][0] == '-') { switch (svargv[1][1]) { case 'd': lefteq=svargv[1][2]; righteq=svargv[1][3]; break; case 's': gsize = numb(&svargv[1][2]); break; case 'p': deltaps = numb(&svargv[1t */ ncol = 0; for( i=p1; i ibuf) return(*--ip); /* already present */ lastchar = getc(curfile); if (lastchar=='\n') linect++; if (lastchar != EOF) return(lastchar); if (++ifile > svargc) { return(EOF); } fclose(curfile); linect = 1; if ((curfile=fopen(sva& c!='\n' && c!='{' && c!='}' && c!='"' && c!='~' && c!='^' && c!=righteq; ) { if(c == '\\') if((c = gtc()) != '"')s[sp++] = '\\'; s[sp++] = c; if (sp>=SSIZE) error(FATAL,"token %.20s... too long",s); c = gtc(); } if (c=='{' || c=='}' || c=='"' || c=='~' || c=='^' || c=='\t' || c==righteq) putbak(c); s[sp]='\0'; yylval = s; } lookup(str,tbl) char *str; struct { char *name; char *val; } tbl[]; { register i,j, r; for (i=0; tbl[i].name!=0; i++) { /* table of tbl wds */ for ( j=0; (r=tb= '\\'; cs[csp++] = 'f'; cs[csp++] = rf==ITAL ? ITAL : ROM; name4('f','m'); cs[csp++] = '\\'; cs[csp++] = 'f'; cs[csp++] = 'P'; f = rf==ITAL ? ITAL : ROM; break; case 'f': if (ft == ITAL) { cs[csp++] = '\\'; cs[csp++] = '^'; cs[csp++] = 'f'; cs[csp++] = '\\'; cs[csp++] = '^'; f = ITAL; } else cs[csp++] = 'f'; break; case 'j': if (ft == ITAL) { cs[csp++] = '\\'; cs[csp++] = '^'; cs[csp++] = 'j'; f = ITAL; } else cs[csp++] = 'j'; break; default: cs[csp+eak; } if (putchar(lastchar) != '\n') while (putchar(gtc()) != '\n'); } else if (type == lefteq) inline(); else printf("%s",in); } return(0); } getline(s) char *s; { char c; while((*s++=c=gtc())!='\n' && c!=EOF && c!=lefteq) if (s >= in+MAXLINE) { error( !FATAL, "input line too long: %.20s\n", in); in[MAXLINE] = '\0'; break; } if (c==lefteq) s--; *s++ = '\0'; return(c); } inline() { int i,j,ds,t; printf(".nr 99 \\n(.s\n.nr 98 \\n(.f\n"); ds = oalloc(); print][2]); break; case 'f': gfont = svargv[1][2]; break; case 'e': noeqn++; break; default: dbg = 1; } svargc--; svargv++; } ifile = 1; linect = 1; if (svargc <= 0) curfile = stdin; else if ((curfile = fopen(svargv[1], "r")) == NULL) error( FATAL,"can't open file %s", svargv[1]); } yyerror() {;} init() { ct = 0; ps = gsize; ft = gfont; setps(ps); printf(".ft %c\n", ft); } error(fatal, s1, s2) int fatal; char *s1, *s2; { if (fatal>0) printf("eqn fatal error: "); printf(s1,s2); p+lp[j]+1); val[i] = yyval; j =+ nrow + 2; } yyval = oalloc(); eht[yyval] = eht[val[0]]; ebase[yyval] = ebase[val[0]]; lfont[yyval] = rfont[yyval] = 0; if(dbg)printf(".\tmatrix S%d: r=%d, c=%d, h=%d, b=%d\n", yyval,nrow,ncol,eht[yyval],ebase[yyval]); printf(".ds %d \"", yyval); for( i=0; i= &ibuf[PUSHBACK]) error( FATAL, "eqn pushback overflow\n"); while (p > str) putbak(*--p); } yylex() { int c, type; beg: while ((c=gtc())==' ' || c=='\n'); yylval=c; switch(c) { case EOF: return('\0'); case '~': return(SPACE); case '^': return(THIN); case '\t': return(TAB); case '{': return(MQ);l[i].name[j])==str[j] && r!='\0'; j++); if (r == str[j]) return(i); } return( -1 ); } cstr(s,quote) char *s; int quote; { int del,c,i; while((del=gtc()) == ' ' || del == '\t' || del == '\n'); if(quote) for (i=0; (c=gtc()) != del;) s[i++] = c; else { s[0] = del; for (i=1; (c=gtc())!=' ' && c!= '\t' && c!='\n';) s[i++]=c; } s[i] = '\0'; return(s); } define(type) int type; { /* char *calloc (); */ int i, c, index; while ((c=gtc())==' ' || c=='\n'); getstr(token,c); if (type == DEFINE) { if((index = lookup(token,deftab)) >= 0) { cfree(deftab[index].sptr); } else { index = defptr++; if (index >= MAXDEFS) error(FATAL, "Too many definitions at %s\n", token); for (i=0; token[i] != '\0'; i++); deftab[index].nptr = calloc(i+1,1); for (i=0; deftab[index].nptr[i]=token[i]; i++); } if(dbg)printf(".\tdefine %s\n",deftab[index].nptr); } cstr(token,1); if (type != DEFINE) return; for (i=0; token[i] != '\0'; i++); deftab[index].sptr = calloc(i+1,1); for (ichdir cmds make chdir ../neqn make chdir ../tbl make chdir ../terms make -6 FO .wh -3 BT .nr EP \n(.pu-6v .. .de TM .pi /usr/bin/col .nr ST 1 .ds MN \\$1 .nr MM \\n(.$ .nr tm 1 .if \\n(.$-1 .ds CA \\$2 .if \\n(.$-2 .ds CC \\$3 .rm RP .rm S0 .rm S2 .rm AX .. .de RP .nr ST 2 .rm SG .rm CS .rm TM .. .de TL\" TL - title and initialization .nr TV 1 .di WT .na .fi .ll 50 .if \\n(tm .ll 30 .ft B .if !\\n(tm .ps 12 .. .de TX .rs .sp 3 .ce 1000 .ul 1000 .ps 12 .ft B .vs 15p .ne 4 .WT .. .de AU\" AU - author(s) .nr AV 1 .ad .br .di .br .nf .nr NA +1 .ds R\\n(NA \\$1 .ds E\\n(NA \\$2 .di A2 .CB 3 .if \\n(NA-3 .CB 4 .if \\n(NA-4 .CB 5 .ft R .sp 2 .WB .br .sp 5 .FF .rm FF .nr x 50-\\n(nl .sp \\nx .nf .ta 15 30 45 Pages Text \\$1 Other \\$2 Total \\$3 .sp No. Figures \\$4 No. Tables \\$5 No. Refs. \\$6 .ps 7 .sp .tl 'E-1932-C (6-73)'SEE REVERSE SIDE FOR DISTRIBUTION LIST'' .ll \\n(LLu .fi .ps 10 .bp 1 .. .de CB\" CB - help with cover sheet .br .mk .A\\$1 .rt .if \\$1-1 .if !\\$1-2 \& \\*(R2 \\*(E2 .if \\$1-2 .if !\\$1-3 \& \\*(R3 \\*(E3 .if \\$1-3 .if !\\$1-4 \& \\*(R4 \\*(E4 .if \\$1ce 0 .nf .WB .fi .ad .. .de SG\" SG - signature .nf .in +(2u*\\n(.lu/3u) .sp 2 .A1 .if \\n(NA-1 .sp 2 .A2 .if \\n(NA-2 .sp 2 .A3 .if \\n(NA-3 .sp 2 .A4 .if \\n(NA-4 .sp 2 .A5 .in \\$1 .br .. .de Ta\" Tables. TS - table start, TE - table end .br .RT .ul 0 .sp .nf .. .de TE .fi .sp 1 .. .de DS\" DS - display. If .DS C, center; L, left-adjust; I, indent. .KS .\\$1D .. .de CD .ce 1000 .nf .nr oi \\n(.i .sp 1 .. .de D .ID .. .de ID .nf .nr oi \\n(.i .sp 1 .in +8 .. .de LD .nf .nr oi \\n(.i .sp 1 .. .de DE\" DE -(1T .sp 4 .RT .mk .nr NC 1 .nr NX 1 .nr L1 \\n(.l .nr L2 \\n(.l*7/15 .ll \\n(L2u .FL \\n(L2*11/12 .nr RO \\n(L2*8/7 .ns .. .de RC .if \\n(NC-1 .C2 .if !\\n(NC-1 .C1 .nr NC \\n(ND .. .de C1 .rt .po +\\n(ROu .nr ND 2 .nr x 0 1 .ns .. .de C2 .po \\n(DOu 'bp .nr ND 1 .. .de 1C\" 1C - return to single column format .nr NX 0 .br .po \\n(DOu .nr ND 1 .ll \\n(L1u .bp .. .de R3 .ll 120 .pl 102 .nr LT \\n(.l .. .de BT .ft R .lt \\n(LTu .tl '\\*(LF'\\*(CF'\\*(RF' .ft P .. .de PP\" PP - paragraph .RT .ne 2 .if \\n(1T .=0; deftab[index].sptr[i] = token[i]; i++); if(dbg)printf(".\tname %s defined as %s\n", deftab[index].nptr, deftab[index].sptr); } include() { error(!FATAL, "Include not yet implemented\n"); } delim() { char *s; yyval = eqnreg = 0; cstr(token,0); lefteq = token[0]; righteq = token[1]; if (lefteq == 'o' && righteq == 'f') lefteq = righteq = '\0'; } globsize() { extern int gsize; int c; while ((c=gtc())==' ' || c=='\n'); getstr(token,c); if (token[0] == '+') gsize =+ numb(token); else i.pl 66 .nr in 5 .de i0 .in \n(in .. .de lp .i0 .ta \\$2 .in \\$1 .ti -\\$2 .. .de s1 .sp 1 .ne 4 .. .de s2 .sp 1 .. .de s3 .sp 1 .. .de fo 'sp 2 'tl ''- % -'' 'bp .. .de th .de x1 'sp 2 'tl '\\$1(\\$2)'\\$3'\\$1(\\$2)' 'sp 2 \\.. .wh -5 fo .wh 0 x1 .in \n(in .. .de sh .s1 .ne 5 .ti 0 \\$1 .br .. .de bd .tr __ .ul \\$1 .. .de bn .tr __ .ul \\$1\\t .. .de it .tr __ .ul .li \\$1 .. .de dt .ta 8 16 24 32 40 48 56 64 .. .de un .mc | .. .de uf .mc .. .ds b B .ds G G .ds a ' .ds - - .ds _ _ .ds v | .ds p J\\n(NA .ll \\n(LLu .if !\\n(tm .ft I .if \\n(tm .ft B .if \\n(tm .ll 16 .ps 10 .. .de AX .ft R .rs .ce 1000 .ul 0 .ps 10 .vs 12p .sp 2 .A1 .sp .I1 .if \\n(NA-1 .sp 2 .A2 .if \\n(NA-1 .sp .I2 .if \\n(NA-2 .sp 2 .A3 .if \\n(NA-2 .sp .I3 .if \\n(NA-3 .sp 2 .A4 .if \\n(NA-3 .sp .I4 .if \\n(NA-4 .sp 2 .A5 .if \\n(NA-4 .sp .I5 .. .de AI\" AI - authors institution .br .ft R .di .di I\\n(NA .nf .. .de AB\" AB - begin an abstract .br .di .ll \\n(LTu .nr 1T 1 .nr IK 1 .di WB .rs .ce 1 .ul .ll \\n(LTu ABSTRACT .sp .fi-4 .if !\\$1-5 \& \\*(R5 \\*(E5 .br .. .de CT \\$1 \\$2 \\$3 \\$4 .. .de S1\" S1 - tm style .sp 6 .ta 47 .ll 80 .ps 36 .br .vs .25i .ps 12 .br .ft B .nf \tBell Laboratories .ft R .fi .na .ps 8 .vs 12p .sp 3 .mk .fi .ll .ll 40 Subject: .ft B .ps .WT .ft R .br .if \\n(MM-1 \\s8Case- \\*(CA\\s10 .if \\n(MM-2 --\s8 File- \\*(CC\\s10 .br .rt .ll 70 .in 52 .ps 8 .mk .ti -6n date: .ps \\n(PS .ft B .br .rt \\*(DY .sp .ft R .ps 8 .mk .ti -6n from: .ps .br .rt .ft B .A1 .br .A2 .br .A3 .br .A4 .br .A5 .ft R .sp .mk . display end .ce 0 .in \\n(oiu .KE .sp 1 .fi .. .de KS\" KS keep - for keep release features. As in IBM .if !\\n(IK .KQ .nr IK +1 .. .de KQ\" KQ - real keep processor .br .di KK .nr TB 0 .. .de KF\" KF - floating keep .if !\\n(IK .FQ .nr IK +1 .. .de FQ\" FQ real floating keep processor .br .di KK .nr TB 1 .. .de KE\" KE release - everything between keep and release is together .if \\n(IK .if !\\n(IK-1 .RQ .if \\n(IK .nr IK -1 .. .de RQ\" RQ real release .br .di .if \\n(dn+\\n(nl-\\n(EP .if !\\n(TB .sp 200 sp .ti +5 .. .de SH\" SH - (unnumbered) section heading .RT .if \\n(1T .sp 1 .if !\\n(1T .BG .RT .ne 7 .ft B .ul 1000 .. .de NH\" NH - numbered heading .RT .if \\n(1T .sp 1 .if !\\n(1T .BG .RT .ne 7 .ft B .ul 1000 .nr a \\$1 .if !\\n(.$ .nr a 1 .if !\\na .nr a 1 .nr H\\na +1 .if !\\na-4 .nr H5 0 .if !\\na-3 .nr H4 0 .if !\\na-2 .nr H3 0 .if !\\na-1 .nr H2 0 .if !\\$1 .if \\n(.$ .nr H1 1 .ds SN \\n(H1. .if \\na-1 .as SN \\n(H2. .if \\na-2 .as SN \\n(H3. .if \\na-3 .as SN \\n(H4. .if \\na-4 .as SN \\n(H5. \\*f (token[0] == '-') gsize =- numb(token); else gsize = numb(token); yyval = eqnreg = 0; setps(gsize); ps = gsize; if (gsize >= 12) /* sub and sup size change */ deltaps = gsize / 4; else deltaps = gsize / 3; } globfont() { extern int gfont; while ((gfont=gtc())==' ' || gfont=='\n'); getstr(token, gfont); yyval = eqnreg = 0; switch (gfont) { case 'r': case 'R': gfont = '1'; break; case 'i': case 'I': gfont = '2'; break; case 'b': case 'B': gfont = '3'; break; } printf(".f .ds r .ds g ` .ds X X .ds u u .ds > -> .ds | .nr oi \\n(.i .in +(\\n(.lu/12u) .ll -(\\n(.lu/12u) .br .ps \\n(PS .ti +5 .. .de AE\" AE - end of an abstract .br .di .ll \\n(LLu .nr 1T 0 .nr IK 0 .in \\n(oiu .di .ce 0 .if \\n(ST-1 .SY .rm SY .. .de OK\" OK - "other keywords" for cover sheet. .br .di .di OD .nf .ft B .. .de CS\" CS - spew out cover sheet .br .di .tr ~ .sp 6 .nf \s24\(bs\s12\fB Bell Laboratories \s16\fRCover Sheet for Technical Memorandum .sp .fi .ps 9 .ft I The information contained herein is for the use of employees of Belps 8 .ti -6n .ft R .if \\n(MM TM: .br .rt .ps .ft B .hy 0 .ll 10n .if \\n(MM \\*(MN .hy .ll .ft R .ll \\n(LLu .in .sp .ad .ce .ft I MEMORANDUM FOR FILE .ft R .sp .ad .. .de SY\" SY - cover sheet of released paper .ll \\n(LLu .sp 6 .ns .if \\n(TV .TX .if \\n(AV .AX .ce 0 .nf .sp 3 .WB .fi .. .de S2\" S2 - first text page, released paper format .SY .rm SY .bp 1 .if \\n(TV .TX .if \\n(AV .AX .ce 0 .ft R .ad .. .de S0\" S0- mike lesk conserve paper style .ll \\n(LLu .rs .sp 6 .ns .if \\n(TV .TX .if \\n(AV .AX ..if !\\n(dn+\\n(nl-\\n(EP .if \\n(TB .nr TB 0 .nf .in 0 .if !\\n(TB .KK .in .fi .. .de EQ\" EQ default equation breakout .sp .ce .ne 2 .ds EL \\$1 .if \\n(.$-1 .ds EL \\$2 .nr LE \\n(.$ .@\\$1 .. .de @L\" This nonsense permits recognition of .EQ L, .EQ I, .EQ C .ce0\" by invoking macros @L, @I, and so forth .nr LE -1 .. .de @C .nr LE -1 .. .de @I .ce 0 .ti 10n .nr LE -1 .. .de EN .ce 0 .lt \\n(.lu .if \\n(LE .sp -1 .if \\n(LE .tl '''\\*(EL' .sp 1 .ns .. .de EM\" EM end up macro - process left over keep-rel(SN .. .de BG\" BG - begin, execute at first PP .br .di .ce 0 .nr 1T 1 .S\\n(ST .rm S0 .rm S1 .rm S2 .rm OK .rm OD .rm TX .rm AX .rm WT .rm I1 .rm I2 .rm I3 .rm I4 .rm I5 .rm CB .rm E1 .rm R1 .rm R2 .rm E2 .de TL .ft B .sp .ul 100 .ce 100 .LG \\.. .de AU .ft I .ul 0 .ce 100 .sp .NL \\.. .de AI .ft R .ce 100 .ul 0 .sp .NL \\.. .ds Ch \\*(CH .sp 2 .fi .ll \\n(LLu .. .de IP\" IP - indented paragraph .RT .if !\\n(IP .nr IP +1m .sp .ne 3 .if \\n(.$-1 .nr IQ \\$2m .LB "\\$1" .. .de LP\" LP - left aligned (block) t %c\n", gfont); ft = gfont; } .nr DO \n(.o .nr tm 0 .de RT\" RT - reset everything to normal state .if !\\n(1T .BG .if !\\n(IK .di .ce 0 .ul 0 .if \\n(IP .in -\\n(IQu .if !\\n(IP .nr IQ 5m .if \\n(IP .nr IP -1m .ft R .ta 6 11 16 21 26 31 36 41 46 61 56 61 66 71 76 81 .ps \\n(PS .vs \\n(VSp .fi .. .de IZ\" IZ - initialization .br .nr y 0-6 .nr x 0 1 .nr IP 0 .nr IQ 5m .nr PS 10 .nr VS 12 .ps \\n(PS .vs \\n(VSp .nr TB 0 .nr LL \n(.lu .ll \\n(LLu .nr LT \\n(.l .lt \\n(LTu .tc ~ .tr ~ .ds CH "- % - .ds Ch \\*(CH .ds CF "\\*(DY .wh 0 NP .wh l Laboratories and is not for publication. (See GEI 13.9-3)\p .ft R .nf .sp .ll 30 .ps 9 .ta 10 40 47 .mk Title- \fB\s10 .rt .in 10 .WT .rt .ll \\n(LLu .in 40 \s9\fRDate-\s10\fB .rt .in 47 \\*(DY .sp .ti 40 .mk \s9\fRTM-\fB\s10 .br .rt .CT \\*(MN .rt .in 0 .sp .mk \s9\fROther Keywords-\fB .rt .in 20 .OD .rm OK .rm OD .in 0 .sp 3 .ps 9 .ta 20 35 45 .ft R Author Location Extension Charging Case- \s10\fB\\*(CA .ps 10 .nf .mk .A1 .rt \\*(R1 \\*(E1 \fR\s9Filing Case- \s10\fB\\*(CC .if \\n(NA-1 .CB 2 .if \\n(NA- s b h n t c i o d j p v e k q w x ~ ease .if \\n(TB .br .if \\n(TB  .if \\n(TB .NP .. .de NP\" NP new page 'sp 3 .ft R .lt \\n(LTu .ps \\n(PS .PT .ps .ft P 'sp 3 .nr x 0 1 .nr y 0-6 .if \\n(MF .fz .nr MF 0 .ns .os .ev 1 .if \\n(TB .nf .if \\n(TB .KK .if \\n(TB .fi .ev .nr TB 0 .mk .. .de PT .if \\n%-1 .tl '\\*(LH'\\*(Ch'\\*(RH' .. .de FO\" FO - footer of page .nr FC +1 .nr dn 0 .if \\nx .xf .nr MF 0 .if \\n(dn .nr MF 1 .ch FO -6 .if !\\n(FC-1 .if \\n(NX .RC .if !\\n(FC-1 .if !\\n(NX 'bp .nr FC -1 .. .de 2C\" 2C - begin double column .if !\\nparagraph .RT .sp .ne 3 .if \\n(.$ .LB \\$1 .. .de IE\" IE - synonym for .LP .LP .. .de LB\" LB - label paragraph .in +\\n(IQu .ta \\n(IQu+1m .ti -\\n(IQu \\$1\t\c .. .de RS\" RS - prepare for double indenting .in +\\n(IQu .nr IP +1m .. .de RE\" RE - retreat to the left .br .in -\\n(IQu .. .de CM\" CM - cut mark .po 0 .tl '-''' .po .. .de B\" B - bold font .ft B .ul 1000 .. .de R\" R - Roman font .ft R .ul 0 .. .de I\" I - italic font .ft I .ul 1000 .. .de TA\" TA - tabs set in ens or chars .ta \\$1n \\$2n \\$3n \\$4n \\$5n \\$6n \\$7n \\$8n \\$9n .. .de SM\" SM - make smaller size .ps -2 .. .de LG\" LG - make larger size .ps +2 .. .de NL\" NL - return to normal size .ps \\n(PS .. .de DA\" DA - force date; ND - no date or new date. .if \\n(.$ .ds DY \\$1 \\$2 \\$3 \\$4 .ds CF \\*(DY .. .de ND .ds DY \\$1 \\$2 \\$3 \\$4 .rm CF .. .if \n(mo-0 .ds mo January .if \n(mo-1 .ds mo February .if \n(mo-2 .ds mo March .if \n(mo-3 .ds mo April .if \n(mo-4 .ds mo May .if \n(mo-5 .ds mo June .if \n(mo-6 .ds mo July .if \n(.HE "NROFF" "MACRO" "SUMMARY" .FO "Peter Ivanov OUG and bar" .NS 1. GENERAL .PA NO SUPPORT IS OFFERED OR GUARANTEED FOR THIS PACKAGE IN ANY SHAPE OR FORM. .PA These macros are by NO means the "be all and end all" of macro packages for nroffing documents. Any body with half a brain and masochistic tendancies could write a package equally as good, maybe even better. If you take your life in your hands and alter them, then it would be a VERY GOOD IDEA to UPDATE the DOCUMENTATION. .NS 2. MACROS .PA For the sakehighest level. One must be supplied to match every "BP". It has no arguments. .NP \&.IN This turns off filling and moves the indent in by any argument given eg. .IN \&.IN 10 .OT would indent 10 units. If no argument is given, the default indent is 7 units. .NP \&.OT This command removes the effect of the "IN" command restoring the original indent. No arguments are accepted. .NP \&.PA Takes a paragraph. .NP \&.NS Starts a new section, underlining the heading. .NP \&.UL Underlines the next line. .NP \&.FO Thi.nh .pl 66 .ll 64 .lt \n(.lu .nr xi 0\" in-out value .nr n 0 1\" level of section .nr l 0 1\" level of indent .nr s\nn 0\" level zero inc indent for section .nr i\nl 0\" level zero indent .nr o\nl 0\" level zero outdent .nr w 0\" .sp indicator for levels .de BP\" $1 - .in +$1, $2 - .ti -$2 .br .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ne 6 .nr zi \\n(i\\nl .nr l \\n+l .nr t\\nl \\$2 .nr i\\nl \\n(zi+\\$1 .nr o\\nl \\n(zi+\\$1-\\$2 .ta \\n(t\\nl .in \\n(i\\nl .ti \\n(o\\nl .. .de NP\" reset indent, tab, andchdir cmds install chdir ../neqn install chdir ../tbl install chdir ../terms install chdir ../macros install fine NHEX 128 /*byte size of exception word list*/ #define NTAB 35 /*tab stops*/ #define NSO 5 /*"so" depth*/ #define WDSIZE 170 /*word buffer size*/ #define LNSIZE 480 /*line buffer size*/ #define NDI 5 /*number of diversions*/ #define DBL 0100000 /*double size indicator*/ #define MOT 0100000 /*motion character indicator*/ #define MOTV 0160000 /*clear for motion part*/ #define VMOT 0040000 /*vert motion bit*/ #define NMOT 0020000 /* negative motion indicator*/ #define MMASK 0100000 /*macro mask indicator*/mo-7 .ds mo August .if \n(mo-8 .ds mo September .if \n(mo-9 .ds mo October .if \n(mo-10 .ds mo November .if \n(mo-11 .ds mo December .if \n(dw-0 .ds dw Sunday .if \n(dw-1 .ds dw Monday .if \n(dw-2 .ds dw Tuesday .if \n(dw-3 .ds dw Wednesday .if \n(dw-4 .ds dw Thursday .if \n(dw-5 .ds dw Friday .if \n(dw-6 .ds dw Saturday .ds DY \*(mo \n(dy, 19\n(yr .IZ .rm IZ .rm mo .de FN .FS .. .de FS\" FS - begin footnote 'ce 0 .di .da FF .ev 1 .if !\\n+x-1 .fs .. .de FE\" FE - footnote end .br .in 0 .ev .di .nr y -\\n(d of simplicity, all macro calls are in upper case. The macros are as follows: .BP 8 6 \&.BP This macro begins a block of indented points such as .BP 6 4 a) Point a) on a certain topic such as the price of cheese at John Beale's local deli. .NP b) Another point called b) about any topic you care to name but nothing dirty naturally. These points can go on 'til Doomsday but even I get sick of raving. .EP Up to nine (9) levels of pointing may be nested for example .BP 11 9 PLUNGER This argument may be assigned s specifies a foot title. The argument given will appear at the bottom-left of all pages. The page number will appear at bottom-center and the date appears at the bottom-right. an example .IN \&.FO "Dr. J.P. Beale Esq." .OT .NP \&.HE This specifies a head title. The three arguments given appear at the top-left, -center and -right of all pages. Extra long arguments may cause problems. An example .IN \&.HE "CSU" "PLOTTING" "FACILITIES" .OT .NP \&.AR This resets the page number to 1 and causes future printing temp indent .br .ne 6 .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ta \\n(t\\nl .in \\n(i\\nl .ti \\n(o\\nl .. .de EP\" pop indent level .br .if \\nw .sp 1 .nr w 0 .if \\n(.n\" .sp 1 .if \\nl .in \\n(i\\n-l .if !\\nl .ta 8 16 24 32 40 48 56 64 72 80 88 96 .. .de IN\" $1 - the increment if given .br .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ne 6 .nr xi 7m .if \\$1 .nr xi \\$1m .in \\n(.iu+\\n(xiu .ta 8 16 24 32 40 48 56 64 72 80 88 96 .nf .. .de OT\" restore to previous indent .br .if \\nw .sp 1 .nr w 0 .if #ifdef NROFF /*NROFF*/ #define EM t.Em #define HOR t.Hor #define VERT t.Vert #define INCH 240 /*increments per inch*/ #define SPS INCH/10 /*space size*/ #define SS INCH/10 /* " */ #define TRAILER 0 #define UNPAD 0227 #define PO 0 /*page offset*/ #define ASCII 1 #define PTID 1 #define LG 0 #define DTAB (8*INCH/10) #define ICS 2*SPS #endif #ifndef NROFF /*TROFF*/ #define INCH 432 /*troff resolution*/ #define SPS 20 /*space size at 10pt; 1/3 Em*/ #define SS 12 /*space size in 36ths of an em*/ #define TRAILER 6 #define CMASK 0100377 #define ZBIT 0400 /*zero width char*/ #define BMASK 0377 #define BYTE 8 #define IMP 004 /*impossible char*/ #define FILLER 037 #define PRESC 026 #define HX 0376 /*High-order part of xlss*/ #define LX 0375 /*low-order part of xlss*/ #define CONT 025 #define COLON 013 #define XPAR 030 #define ESC 033 #define FLSS 031 #define RPT 014 #define JREG 0374 #define NTRAP 20 /*number of traps*/ #define NPN 20 /*numbers in "-o"*/ #define T_PAD 0101 /*cat padding*/ #define T_INIT 0100 #define T_In .ch FO \\nyu .if \\n(nl-\\n(.p-\\ny .ch FO \\n(nlu+1 .. .de fs\" SEPARATOR __________________________________________________________ .br .. .de fz .FS .nf .fy .fi .FE .. .de fx .di fy .. .de xf .ev 1 .nf .FF .rm FF .di .fi .ev .. .de FL .ev 1 .ll \\$1 .ev .. .ch FO 100 .wh -6 fx .ch FO -6 .ev 1 .ll \n(LLu .ll -(\n(.lu/12u) 'ps8 'vs10p .ev .br .em EM two values, with effects which vary widely. These are .BP 5 3 0 This means to raise the plunger to its cocked position. This should be done when nobody is looking. .NP 1 This causes the plunger to be pressed, exploding the TNT placed under the CSU operators console. This usually wakes the operator. .EP This call is restricted to Super Users. .EP The "BP" command should be given with two (2) arguments as below .IN \&.BP arg1 arg2 .OT The arguments have the following meaning .BP 8 6 arg1 specifies the incremeof page numbers to be in arabic numerals. .NP \&.BR This resets the page number to 1 and causes future printing of page numbers to be in big roman numerals. .NP \&.LR This resets the page number to 1 and causes future printing of page numbers to be in little roman numerals. \\n(.n\" .sp 1 .in \\n(.iu-\\n(xiu .fi .. .de PA\" paragraph .br .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ne 6 .. .de NS\"new section. $1=inc indent $2=section no if given .br .if \\nw .sp 1 .nr w 1 .if \\n(.n\" .sp 1 .ne 6 .nr n \\n+n .nr s\\nn \\$1 .in +\\n(s\\nn .nr zi \\n(i\\nl .nr i\\nl \\n(zi+\\n(s\\nn \\$2 'cu 1 .. .de ES\" end section and pop back things .br .if \\nw .sp 1 .nr w 0 .if \\n(.n\" .sp 1 .nr zi \\n(i\\nl .nr i\\nl \\n(zi-\\n(s\\nn .in -\\n(s\\nn .nr n \\n-n .. .de UL\" lynnies choice .048 /*144*14*3 = 14 inches*/ #define UNPAD 027 #define PO 416 /*page offset 26/27ths inch*/ #define HOR 1 #define VERT 3 #define EM (6*(pts&077)) #define ASCII 0 #define PTID 0 #define LG 1 #define DTAB (INCH/2) #define ICS 3*SPS #endif #define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 #define SIGFPE 8 #define SIGKILL 15 #define SIGPIPE 13 #define ECHO 010 /*tty echo mode*/ #define NARSP 0177 /*narrow space*/ #define HNSP 0226 /*half narrow space*/ #define PS 10 /*default point size*/ #define FT 0 /*defaESC 16 /*initial offset*/ #define T_STOP 0111 #define NPP 10 /*pads per field*/ #define FBUFSZ 256 /*field buf size words*/ #define OBUFSZ 512 /*bytes*/ #define IBUFSZ 512 /*bytes*/ #define NC 256 /*cbuf size words*/ #define NOV 10 /*number of overstrike chars*/ #define LONG0 int /*long flag for atoi0,1*/ #define ZONE 5 /*5hrs for EST*/ #define TDELIM 032 #define LEFT 035 #define RIGHT 036 #define LEADER 001 #define TAB 011 #define TMASK 037777 #define RTAB 0100000 #define CTAB 0040000 #define OHC 024 cpall tmac.[ms] /usr/lib ntal indent for all points following until the next "EP" command, .NP arg2 specifies the position to the left of the NEW indent where the first line of this point is to begin. .EP That portion of the first line of a point which is to appear to the left of the NEW indent should be followed by a "tab" character eg. .IN a)The rest of the first line. .OT .NP \&.NP This command starts a new point within a "BP" - "EP" pair. It has no arguments. .NP \&.EP This command pops the pointing level back to the next tmac.[ms] have been revised for the new nroff by Piers Lauder, Sydney University tmac.n is a new package by Peter Ivanov, UNSW ul 1 .. .de FO\" foot title macro .de x1 'sp 2 'ie '\\$2'date' 'tl '\\$1'- % -'\\n(dy/\\n(mo/\\n(yr' 'el 'tl '\\$1'- % -'\\$2' 'bp \\.. .wh -5 x1 .. .de HE\" header title macro .de x2 'sp 2 'tl '\\$1'\\$2'\\$3' 'sp 2 \\.. .wh 0 x2 .. .de AR\" make page nos arabic - no leading zeros .nr % 1 .af % 1 .. .de BR\" make page nos big roman eg I, IV, XLM .nr % 1 .af % I .. .de LR\" make page nos little roman eg i, iv, xlm .nr % 1 .af % i .. ult font position*/ #define LL 65*INCH/10 /*line length; 39picas=6.5in*/ #define VS INCH/6 /*vert space; 12points*/ #define NN 132 /*number registers*/ #define NIF 5 /*if-else nesting*/ #define NS 64 /*name buffer*/ #define NTM 256 /*tm buffer*/ #define NEV 3 /*environments*/ #define EVLSZ 10 /*size of ev stack*/ #define EVS 3*256 /*environment size in words*/ #define NM 220 /*requests + macros*/ #define DELTA 512 /*delta core bytes*/ #define STKSIZE 10 /*words*/ #define NHYP 10 /*max hyphens per word*/ #deextern struct {int op,dnl,dimac,ditrap,ditf,alss,blss,nls,mkline, maxl,hnl,curd;} d[NDI]; extern struct {int pn,nl,yr,hp,ct,dn,mo,dy,dw,ln,dl,st,sb; int vxx[NN-13];} v ; /* typewriter driving table structure*/ #ifdef NROFF extern struct { /*** *** Initial stty() to set up terminal ***/ int bset; /*** bits to set ***/ int breset; /*** bits to reset ***/ /*** *** Terminal resolution - measured in 1/240 inch units ***/ int Hor; /*** horizontal resolution ***/ int Vert; /*** vertical resolution ***/ int Newline; /*** vertical motion produced by newline ***/ int Char; /*** horizontal motion produced by one character ***/ int Em; /*** width of em ***/ int Halfline;; #endif /*Upsilon*/ '*F', 0271, /*Phi*/ '*X', 0130, /*Chi*/ '*Q', 0272, /*Psi*/ '*W', 0273, /*Omega*/ 'sr', 0274, /*square root*/ 'ts', 0275, /*terminal sigma*/ 'rn', 0276, /*root en*/ '>=', 0277, /*>=*/ '<=', 0300, /*<=*/ '==', 0301, /*identically equal*/ '~=', 0303, /*approx =*/ 'ap', 0304, /*approximates*/ '!=', 0305, /*not equal*/ '->', 0306, /*right arrow*/ '<-', 0307, /*left arrow*/ 'ua', 0310, /*up arrow*/ 'da', 0311, /*down arrow*/ 'eq', 0312, /*equation equal*/ 'mu', 0313, /*multiply*/ 'di', 0314, /*divide#include "tdef.h" char obuf[OBUFSZ]; char *obufp obuf; int r[NN] {'%','nl','yr','hp','ct','dn','mo','dy','dw','ln','dl','st','sb'}; int pto 10000; int pfrom 1; int print 1; char nextf[NS] "/usr/lib/tmac.xxxxx"; int nfi 14; #ifdef NROFF char termtab[NS] "/usr/lib/term/37"; int tti 14; #endif char suftab[] "/usr/lib/nsuftab"; int init 1; int fc IMP; int eschar '\\'; int pl 11*INCH; int po PO; int dfact 1; int dfactd 1; int res 1; int smnt 4; int ascii ASCII; int ptid PTID; char ptname[] "/dev/cat"; int lg LG;'wh',casewh, 'dt',casedt, 'it',caseit, 'rm',caserm, 'rr',caserr, 'rn',casern, 'ad',casead, 'rs',casers, 'na',casena, 'pl',casepl, 'ta',caseta, 'tr',casetr, 'ul',caseul, 'cu',casecu, 'lt',caselt, 'nx',casenx, 'so',caseso, 'ig',caseig, 'tc',casetc, 'fc',casefc, 'ec',caseec, 'eo',caseeo, 'lc',caselc, 'ev',caseev, 'rd',caserd, 'ab',casest, 'fl',casefl, 'ex',done, 'ss',casess, 'fp',casefp, 'cs',casecs, 'bd',casebd, 'lg',caselg, 'hc',casehc, 'hy',casehy, 'nh',casenh, 'nm',casenecho == making formatters echo = suffix tables as suftab.s ld -s -o nsuftab a.out rm a.out echo = nroff cc -o nroff -DNROFF -n n[123456789].c n10.c ni.c nii.c ntab.c hytab.c : echo = troff : cc -o troff -n n[12345789].c t6.c t10.c ni.c nii.c tab3.c hytab.c /*** vertical motion produced by halfline ***/ int Adj; /*** resolution for space adjusting ***/ /*** *** Special character sequences ***/ char *twinit; /*** initialize terminal ***/ char *twrest; /*** restore terminal to pre-nroff state ***/ char *twnl; /*** new line ***/ char *hlr; /*** half line upwards ***/ char *hlf; /*** half line downwards ***/ char *flr; /*** full line upwards ***/ char *bdon; /*** escape to "bold" character mode (I think?) ***/ char *bdoff; /*** return from "bold" chara/* character name tables modified for BTL special font version 4 and Commercial II */ int chtab [] { 'hy', 0200, /*hyphen*/ 'bu', 0201, /*bullet*/ 'sq', 0202, /*square*/ 'em', 0203, /*3/4em*/ 'ru', 0204, /*rule*/ '14', 0205, /*1/4*/ '12', 0206, /*1/2*/ '34', 0207, /*3/4*/ 'mi', 0302, /*equation minus*/ 'fi', 0211, /*fi*/ 'fl', 0212, /*fl*/ 'ff', 0213, /*ff*/ 'Fi', 0214, /*ffi*/ 'Fl', 0215, /*ffl*/ 'de', 0216, /*degree*/ 'dg', 0217, /*dagger*/ 'sc', 0220, /*section*/ 'fm', 0221, /*foot mark*/ 'aa', 0222, /*/ '+-', 0315, /*plus-minus*/ 'cu', 0316, /*cup (union)*/ 'ca', 0317, /*cap (intersection)*/ 'sb', 0320, /*subset of*/ 'sp', 0321, /*superset of*/ 'ib', 0322, /*improper subset*/ 'ip', 0323, /* " superset*/ 'if', 0324, /*infinity*/ 'pd', 0325, /*partial derivative*/ 'gr', 0326, /*gradient*/ 'no', 0327, /*not*/ 'is', 0330, /*integral sign*/ 'pt', 0331, /*proportional to*/ 'es', 0332, /*empty set*/ 'mo', 0333, /*member of*/ 'pl', 0334, /*equation plus*/ 'rg', 0335, /*registered*/ 'co', 0336, /*copyright*/ 'b int pnlist[NPN] {-1}; int *pnp pnlist; int npn 1; int npnflg 1; int oldbits -1; int xflg 1; int dpn -1; int totout 1; int ulfont 1; int ulbit 1<<9; int tabch TAB; int ldrch LEADER; int xxx; extern caseds(), caseas(), casesp(), caseft(), caseps(), casevs(), casenr(), caseif(), casepo(), casetl(), casetm(), casebp(), casech(), casepn(), tbreak(), caseti(), casene(), casenf(), casece(), casefi(), casein(), caseli(), casell(), casens(), casemk(), casert(), caseam(), casede(), casedi(), caseda(), casewh(), casem, 'nn',casenn, 'sv',casesv, 'os',caseos, 'ls',casels, 'cc',casecc, 'c2',casec2, 'em',caseem, 'af',caseaf, 'hw',casehw, 'mc',casemc, 'pm',casepm, #ifdef NROFF 'pi',casepi, #endif 'uf',caseuf, 'pc',casepc, 'ht',caseht, }; /* troff environment block */ int block 0; int ics ICS; int ic 0; int icf 0; int chbits 0; int nmbits 0; int apts PS; int apts1 PS; int pts PS; int pts1 PS; int font FT; int font1 FT; int sps SPS; int spacesz SS; int lss VS; int lss1 VS; int ls 1; int ls1 1; int ll LL; int #include "tdef.h" #include "t.h" #include "tw.h" #ifdef NROFF #define GETCH gettch #endif #ifndef NROFF #define GETCH getch #endif /* troff7.c text */ extern int *dip; extern int pl; extern int trap; extern int flss; extern int npnflg; extern int npn; extern int stop; extern int nflush; extern int *ejl; extern int ejf; extern int ascii; extern int donef; extern int nc; extern int wch; extern int dpn; extern int ndone; extern int lss; extern int pto; extern int pfrom; extern int print; extern int nlist[NTcter mode ***/ /*** *** "Plot" mode: *** used to build composite characters and for high-resolution motions. *** It is assumed that printing a character while in plot mode does *** not move the cursor. ***/ char *ploton; /*** start plot mode ***/ char *plotoff; /*** end plot mode ***/ char *up; /*** move up one plot increment ***/ char *down; /*** " down " " " ***/ char *right; /*** " right " " " ***/ char *left; /*** " left " " " ***/ /*** *** Character*acute accent*/ 'ga', 0223, /*grave accent*/ 'ul', 0224, /*underrule*/ 'sl', 0225, /*slash (longer)*/ '*a', 0230, /*alpha*/ '*b', 0231, /*beta*/ '*g', 0232, /*gamma*/ '*d', 0233, /*delta*/ '*e', 0234, /*epsilon*/ '*z', 0235, /*zeta*/ '*y', 0236, /*eta*/ '*h', 0237, /*theta*/ '*i', 0240, /*iota*/ '*k', 0241, /*kappa*/ '*l', 0242, /*lambda*/ '*m', 0243, /*mu*/ '*n', 0244, /*nu*/ '*c', 0245, /*xi*/ '*o', 0246, /*omicron*/ '*p', 0247, /*pi*/ '*r', 0250, /*rho*/ '*s', 0251, /*sigma*/ '*t', 0252, /*tau*/ '*u', 02r', 0337, /*box vert rule*/ 'ct', 0340, /*cent sign*/ 'dd', 0341, /*dbl dagger*/ 'rh', 0342, /*right hand*/ 'lh', 0343, /*left hand*/ '**', 0344, /*math * */ 'bs', 0345, /*bell system sign*/ 'or', 0346, /*or*/ 'ci', 0347, /*circle*/ 'lt', 0350, /*left top (of big curly)*/ 'lb', 0351, /*left bottom*/ 'rt', 0352, /*right top*/ 'rb', 0353, /*right bot*/ 'lk', 0354, /*left center of big curly bracket*/ 'rk', 0355, /*right center of big curly bracket*/ 'bv', 0356, /*bold vertical*/ 'lf', 0357, /*left floor (leftdt(), caseit(), caserm(), casern(), casead(), casers(), casena(), casepl(), caseta(), casetr(), caseul(), caselt(), casenx(), caseso(), caseig(), casetc(), casefc(), caseec(), caseeo(), caselc(), caseev(), caserd(), casest(), casefl(), done(), casess(), casefp(), casecs(), casebd(), caselg(), casehc(), casehy(), casenh(), casenm(), casenn(), casesv(), caseos(), casels(), casecc(), casec2(), caseem(), caseaf(), casehw(), casemc(), casepm(), casecu(), casepi(), caserr(), caseuf(), caseie(), caseel(), casepc()ll1 LL; int lt LL; int lt1 LL; int ad 1; int nms 1; int ndf 1; int fi 1; int cc '.'; int c2 '\''; int ohc OHC; int tdelim IMP; int hyf 1; int hyoff 0; int un1 -1; int tabc 0; int dotc '.'; int adsp 0; int adrem 0; int lastl 0; int nel 0; int admod 0; int *wordp 0; int spflg 0; int *linep 0; int *wdend 0; int *wdstart 0; int wne 0; int ne 0; int nc 0; int nb 0; int lnmod 0; int nwd 0; int nn 0; int ni 0; int ul 0; int cu 0; int ce 0; int in 0; int in1 0; int un 0; int wch 0; int pendt 0; int *pendw 0; int peRAP]; extern int mlist[NTRAP]; extern int *frame; extern int *stk; extern int *pnp; extern int nb; extern int ic; extern int icf; extern int ics; extern int ne; extern int ll; extern int un; extern int un1; extern int in; extern int ls; extern int spread; extern int totout; extern int nwd; extern int *pendw; extern int *linep; extern int line[]; extern int lastl; extern int ch; extern int ce; extern int fi; extern int nlflg; extern int pendt; extern int sps; extern int adsp; extern int pendnf; extern int ov set: *** The first byte of each string means: *** 1... .... underline this character in .ul mode *** .xxx xxxx actual width of character (in ems) *** Within the string a character >=0200 means "plot" motion: *** 100. .... move right *** 101. .... move left *** 110. .... move down *** 111. .... move up *** ...x xxxx number of plot increments to move *** The first character of a plot string must be >= 0200. ***/ char *codetab[256-32]; int zzz; /*** dummy to mark end of structure ***/ } t53, /*upsilon*/ '*f', 0254, /*phi*/ '*x', 0255, /*chi*/ '*q', 0256, /*psi*/ '*w', 0257, /*omega*/ '*A', 0101, /*Alpha*/ '*B', 0102, /*Beta*/ '*G', 0260, /*Gamma*/ '*D', 0261, /*Delta*/ '*E', 0105, /*Epsilon*/ '*Z', 0132, /*Zeta*/ '*Y', 0110, /*Eta*/ '*H', 0262, /*Theta*/ '*I', 0111, /*Iota*/ '*K', 0113, /*Kappa*/ '*L', 0263, /*Lambda*/ '*M', 0115, /*Mu*/ '*N', 0116, /*Nu*/ '*C', 0264, /*Xi*/ '*O', 0117, /*Omicron*/ '*P', 0265, /*Pi*/ '*R', 0120, /*Rho*/ '*S', 0266, /*Sigma*/ '*T', 0124, /*Tau*/ '*U', 0270, bot of big sq bract)*/ 'rf', 0360, /*right floor (rb of ")*/ 'lc', 0361, /*left ceiling (lt of ")*/ 'rc', 0362, /*right ceiling (rt of ")*/ 0,0}; , caseht(); struct contab { int rq; int (*f)(); }contab[NM]{ 'ds',caseds, 'as',caseas, 'sp',casesp, 'ft',caseft, 'ps',caseps, 'vs',casevs, 'nr',casenr, 'if',caseif, 'ie',caseie, 'el',caseel, 'po',casepo, 'tl',casetl, 'tm',casetm, 'bp',casebp, 'ch',casech, 'pn',casepn, 'br',tbreak, 'ti',caseti, 'ne',casene, 'nf',casenf, 'ce',casece, 'fi',casefi, 'in',casein, 'li',caseli, 'll',casell, 'ns',casens, 'mk',casemk, 'rt',casert, 'am',caseam, 'de',casede, 'di',casedi, 'da',caseda, ndnf 0; int spread 0; int it 0; int itmac 0; int lnsize LNSIZE; int *hyptr[NHYP] {0}; int tabtab[NTAB] {DTAB,DTAB*2,DTAB*3,DTAB*4,DTAB*5,DTAB*6,DTAB*7,DTAB*8, DTAB*9,DTAB*10,DTAB*11,DTAB*12,DTAB*13,DTAB*14,DTAB*15,0}; int line[LNSIZE]{0}; int word[WDSIZE]{0}; int blockxxx[EVS-64-NHYP-NTAB-WDSIZE-LNSIZE] {0}; /*spare 7 words*/ int oline[LNSIZE+1]; er; extern int adrem; extern int nel; extern int ad; extern int ohc; extern int hyoff; extern int nhyp; extern int spflg; extern int word[]; extern int *wordp; extern int wne; extern int chbits; extern int cwidth; extern int widthp; extern int hyf; extern int xbitf; extern int vflag; extern int ul; extern int cu; extern int font; extern int sfont; extern int it; extern int itmac; extern int *hyptr[NHYP]; extern int **hyp; extern int *wdstart, *wdend; extern int lnmod; extern int admod; extern int nn; extern int nms; extern int ndf; extern int ni; extern int nform; extern int lnsize; extern int po; extern int ulbit; extern int *vlist; extern int nrbits; extern int nmbits; extern int xxx; int brflg; tbreak(){ register *i, j, pad; trap = 0; if(nb)return; if((!dip->op) && (v.nl == -1)){ newline(1); return; } if(!nc){ setnel(); if(!wch)return; if(pendw)getword(1); movword(); }else if(pendw && !brflg){ getword(1); movword(); } *linep = dip->nls = 0; #ifdef NROFF if(!dip->op)horiz(po); #e+ nw*nms; v.ln++; } text(){ register i; static int spcnt; nflush++; if((!dip->op) && (v.nl == -1)){newline(1); return;} setnel(); if(ce || !fi){ nofill(); return; } if(pendw)goto t4; if(pendt)if(spcnt)goto t2; else goto t3; pendt++; if(spcnt)goto t2; while(((i = GETCH()) & CMASK) == ' ')spcnt++; if(nlflg){ t1: nflush = pendt = ch = spcnt = 0; callsp(); return; } ch = i; if(spcnt){ t2: tbreak(); if(nc || wch)goto rtn; un =+ spcnt*sps; spcnt = 0; setnel(); if(trap)got(){ if(ul && (--ul == 0)){ cu = 0; font = sfont; mchbits(); } if(it && (--it == 0) && itmac)control(itmac,0); } storeline(c,w){ register i; if((c & CMASK) == JREG){ if((i=findr(c>>BYTE)) != -1)vlist[i] = ne; return; } if(linep >= (line + lnsize - 1)){ if(!over){ prstrfl("Line overflow.\n"); over++; c = 0343; w = -1; goto s1; } return; } s1: if(w == -1)w = width(c); ne =+ w; nel =- w; *linep++ = c; nc++; } newline(a) int a; { register i, j, nlss; int opn; if(aif(pto == -1){ flusho(); done1(0); } if(pto & MOT){ pto =& ~MOT; print++; pfrom = 0; } } findt(a) int a; { register i, j, k; k = 32767; if(dip->op){ if(dip->dimac && ((i = dip->ditrap -a) > 0))k = i; return(k); } for(i=0; i i)k = i; return(k); } findt1(){ register i; if(dip->op)i = dip->dnl; else i = v.nl; return(findt(i)); } eject(a) intel(){ if(!nc){ linep = line; if(un1 >= 0){ un = un1; un1 = -1; } nel = ll - un; ne = adsp = adrem = 0; } } getword(x) int x; { register i, j, swp; int noword; noword = 0; if(x)if(pendw){ *pendw = 0; goto rtn; } if(wordp = pendw)goto g1; hyp = hyptr; wordp = word; over = wne = wch = 0; hyoff = 0; while(1){ j = (i = GETCH()) & CMASK; if(j == '\n'){ wne = wch = 0; noword = 1; goto rtn; } if(j == ohc){ hyoff = 1; continue; } if(j == ' '){ storeword#include "tdef.h" /* typewriter driving table structure*/ #ifdef NROFF struct { int bset; int breset; int Hor; int Vert; int Newline; int Char; int Em; int Halfline; int Adj; char *twinit; char *twrest; char *twnl; char *hlr; char *hlf; char *flr; char *bdon; char *bdoff; char *ploton; char *plotoff; char *up; char *down; char *right; char *left; char *codetab[256-32]; int zzz; } t { 0 }; int pipeflg; #endif struct {int op,dnl,dimac,ditrap,ditf,alss,blss,nls,mkline, maxl,hnl,curndif if(lnmod)donum(); lastl = ne; if(brflg != 1){ totout = 0; }else if(ad){ if((lastl = (ll - un)) < ne)lastl = ne; } if(admod && ad && (brflg != 2)){ lastl = ne; adsp = adrem = 0; #ifdef NROFF if(admod == 1)un =+ quant(nel/2,t.Adj); #endif #ifndef NROFF if(admod == 1)un =+ nel/2; #endif NROFF else if(admod ==2)un =+ nel; } totout++; brflg = 0; if(lastl > dip->maxl)dip->maxl = lastl; horiz(un); for(i = line;nc > 0;){ if(((j = *i++) & CMASK) == ' '){ pad = 0; do{ pad = )goto nl1; if(dip->op){ j = lss; pchar1(FLSS); if(flss)lss = flss; i = lss + dip->blss; dip->dnl =+ i; pchar1(i); pchar1('\n'); lss = j; dip->blss = flss = 0; if(dip->alss){ pchar1(FLSS); pchar1(dip->alss); pchar1('\n'); dip->dnl =+ dip->alss; dip->alss = 0; } if(dip->ditrap && !dip->ditf && (dip->dnl >= dip->ditrap) && dip->dimac) if(control(dip->dimac,0)){trap++; dip->ditf++;} return; } j = lss; if(flss)lss = flss; nlss = dip->alss + dip->blss + lss; v. *a; { register savlss; if(dip->op)return; ejf++; if(a)ejl = a; else ejl = frame; if(trap)return; e1: savlss = lss; lss = findt(v.nl); newline(0); lss = savlss; if(v.nl && !trap)goto e1; } movword(){ register i, w, *wp; int savwch, hys; over = 0; wp = wordp; if(!nwd){ while(((i = *wp++) & CMASK) == ' '){ wch--; wne =- width(i); } wp--; } if((wne > nel) && !hyoff && hyf && (!nwd || (nel > 3*sps)) && (!(hyf & 02) || (findt1() > lss)) )hyphen(wp); savwch = wch; (i,cwidth); continue; } break; } swp = widthp; storeword(' ' | chbits, -1); if(spflg){ storeword(' ' | chbits, -1); spflg = 0; } widthp = swp; g0: if(j == CONT){ pendw = wordp; nflush = 0; flushi(); return(1); } if(hyoff != 1){ if(j == ohc){ hyoff = 2; *hyp++ = wordp; if(hyp > (hyptr+NHYP-1))hyp = hyptr+NHYP-1; goto g1; } if((j == '-') || (j == 0203) /*3/4 Em dash*/ )if(wordp > word+1){ hyoff = 2; *hyp++ = wordp + 1; if(hyp > (hyptr+NHYP-1))hypd;} d[NDI]; struct {int pn, nl, yr, hp, ct, dn, mo, dy, dw, ln, dl, st, sb; int vxx[NN-13];} v ; int *vlist &v; int *dip d; /***/ int level; int stdi; int waitf; int nofeed; int quiet; int stop; char ibuf[IBUFSZ]; char xbuf[IBUFSZ]; char *ibufp; char *xbufp; char *eibuf; char *xeibuf; int cbuf[NC]; int *cp; int nx; int mflg; int ch; int cps; int suffid; int sufind[26]; int ibf; int ttyod; int ttys[3]; int ittys[3]; /***/ int iflg; int ioff; char *enda; int rargc; char **argp; char trtab[256]; int lgf; in+ width(j); nc--; }while(((j = *i++) & CMASK) == ' '); i--; pad =+ adsp; if(adrem){ if(adrem < 0){ #ifdef NROFF pad =- t.Adj; adrem =+ t.Adj; }else if((totout&01) || ((adrem/t.Adj)>=(--nwd))){ pad =+ t.Adj; adrem =- t.Adj; #endif #ifndef NROFF pad--; adrem++; }else{ pad++; adrem--; #endif } } horiz(pad); }else{ pchar(j); nc--; } } if(ic){ if((j = ll - un - lastl + ics) > 0)horiz(j); pchar(ic); } if(icf)icfo rtn; if(nlflg)goto t1; } t3: if(spread)goto t5; if(pendw || !wch) t4: if(getword(0))goto t6; if(!movword())goto t3; t5: if(nlflg)pendt = 0; adsp = adrem = 0; if(ad){ if (nwd > 1) /***/ adsp = nel/(nwd-1); #ifdef NROFF adsp = (adsp/t.Adj)*t.Adj; #endif adrem = nel - adsp*(nwd-1); } brflg = 1; tbreak(); spread = 0; if(!trap)goto t3; if(!nlflg)goto rtn; t6: pendt = 0; ckul(); rtn: nflush = 0; } nofill(){ register i, j; if(!pendnf){ over = 0; tbreak(); if(trap)goto rtn;nl =+ nlss; #ifndef NROFF if(ascii){dip->alss = dip->blss = 0;} #endif pchar1('\n'); flss = 0; lss = j; if(v.nl < pl)goto nl2; nl1: ejf = dip->hnl = v.nl = 0; ejl = frame; if(donef){ if((!nc && !wch) || ndone)done1(0); ndone++; donef = 0; if(frame == stk)nflush++; } opn = v.pn; v.pn++; if(npnflg){ v.pn = npn; npn = npnflg = 0; } nlpn: if(v.pn == pfrom){ print++; pfrom = -1; }else if(opn == pto){ print = 0; opn = -1; chkpn(); goto nlpn; } if(stop && print){ dpn++; hyp = hyptr; nhyp = 0; while(*hyp && (*hyp <= wp))hyp++; while(wch){ if((hyoff != 1) && (*hyp == wp)){ hyp++; if(!wdstart || ((wp > (wdstart+1)) && (wp < wdend) && (!(hyf & 04) || (wp < (wdend-1))) && (!(hyf & 010) || (wp > (wdstart+2))) ) ){ nhyp++; storeline(IMP,0); } } i = *wp++; w = width(i); wne =- w; wch--; storeline(i,w); } if(nel >= 0){ nwd++; return(0); } xbitf = 1; hys = width(0200); /*hyphen*/ m1: if(!nhyp){ if(! = hyptr+NHYP-1; } } storeword(i,cwidth); g1: j = (i = GETCH()) & CMASK; if(j != ' '){ if(j != '\n')goto g0; j = *(wordp-1) & CMASK; if((j == '.') || (j == '!') || (j == '?'))spflg++; } *wordp = 0; rtn: wdstart = 0; wordp = word; pendw = 0; *hyp++ = 0; setnel(); return(noword); } storeword(c,w) int c, w; { if(wordp >= &word[WDSIZE - 1]){ if(!over){ prstrfl("Word overflow.\n"); over++; c = 0343; w = -1; goto s1; } return; } s1: if(w == -1)w = width(c); wt copyf; int ch0; int cwidth; int ip; int nlflg; int *nxf; int *ap; int *frame; int *stk; int donef; int nflush; int nchar; int rchar; int nfo; int ifile; int padc; int raw; int iline; int ifl[NSO]; int offl[NSO]; /*** int ifi; ***/ int flss; int nonumb; int trap; int *litlev; int tflg; int ejf; int *ejl; int lit; int gflag; int dilev; int tlss; int offset; int em; int ds; int woff; int app; int ndone; int lead; int ralss; int paper; int nextb; int *argtop; int nrbits; int nform; int oldmn; int newmn; int m++; else ic = 0; ne = nwd = 0; un = in; setnel(); newline(0); if(*dip){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;} else{if(v.nl > dip->hnl)dip->hnl = v.nl;} for(j=ls-1; (j >0) && !trap; j--)newline(0); spread = 0; } donum(){ register i, nw; extern pchar(); nrbits = nmbits; nw = width('1' | nrbits); if(nn){ nn--; goto d1; } if(v.ln%ndf){ v.ln++; d1: un =+ nw*(3+nms+ni); return; } i = 0; if(v.ln<100)i++; if(v.ln<10)i++; horiz(nw*(ni+i)); nform = 0; fnumb(v.ln,pchar); un = if(nlflg){ ch = nflush = 0; callsp(); return; } adsp = adrem = 0; nwd = 10000; } while((j = ((i = GETCH()) & CMASK)) != '\n'){ if(j == ohc)continue; if(j == CONT){ pendnf++; nflush = 0; flushi(); ckul(); return; } storeline(i,-1); } if(ce){ ce--; if((i=quant(nel/2,HOR)) > 0)un =+ i; } if(!nc)storeline(FILLER,0); brflg = 2; tbreak(); ckul(); rtn: pendnf = nflush = 0; } callsp(){ register i; if(flss)i = flss; else i = lss; flss = 0; casesp(i); } ckul if(dpn >= stop){ dpn = 0; dostop(); } } nl2: trap = 0; if(v.nl == 0){ if((j = findn(0)) != NTRAP) trap = control(mlist[j],0); } else if((i = findt(v.nl-nlss)) <= nlss){ if((j = findn1(v.nl-nlss+i)) == NTRAP){ prstrfl("Trap botch.\n"); done2(-5); } trap = control(mlist[j],0); } } findn1(a) int a; { register i, j; for(i=0; i32) && (j<0370) && !(*t.codetab[j-32] & 0200)) i =& ~ulbit; } return(i); } acerr; int apptr; int aplnk; int diflg; int roff; int wbfi; int inc[NN]; int fmt[NN]; int evi; int vflag; int noscale; int po1; int nlist[NTRAP]; int mlist[NTRAP]; int evlist[EVLSZ]; int ev; int tty; int sfont; int sv; int esc; int cs; int bd; int widthp; int xpts; int xfont; int code; int setwdf; int ccs; int xbitf; int mfont; int mpts; int pfont; int ppts; int over; int nhyp; int **hyp; int *olinep; int *pslp; int back; int esct; int mcase; int psflg; int verm; int escm; int ttysave; int dotT; int eqflg; int unlkp; /***/ ne; } ptout1() { register i, k; register char *codep; int *q, w, j, phyw; /***/ register nbold; for(q=oline; q>9) & 03; nbold = 0; /***/ if(*t.bdon){ if(!bdmode && (xfont == 2)){ oputs(t.bdon); bdmode++; } if(bdmode && (xf< 0){ esc = -esc; j = "\b"; p = t.left; }else j = " "; k = esc/t.Char; esc = esc%t.Char; while(k--)oputs(j); } /***/ if((*t.ploton) && (esc || lead)){ if(!plotmode)oputs(t.ploton); esc =/ t.Hor; lead =/ t.Vert; while(esc--)oputs(p); while(lead--)oputs(q); oputs(t.plotoff); } esc = lead = 0; } ptlead(){move();} dostop(){ int junk; flusho(); read(2,&junk,1); } && ((j=(i = getch()) & CMASK) != delim) && (j != '\n'); k++){ o[k] = i; w[k] = width(i); } o[k] = w[k] = 0; if(o[0])for(j=1; j;){ j = 0; for(k=1; o[k] ; k++){ if(w[k-1] < w[k]){ j++; i = w[k]; w[k] = w[k-1]; w[k-1] = i; i = o[k]; o[k] = o[k-1]; o[k-1] = i; } } }else return; p = cbuf; for(k=0; o[k]; k++){ *p++ = o[k]; *p++ = makem(-((w[k]+w[k+1])/2)); } *p++ = makem(w[0]/2); *p = 0; cp = cbuf; } setbra(){ register i, *j, k; int cnt, delim, dwn; x; { register i, j, *fp; int length, ws, npad, temp, type; int **pp, *padptr[NPP]; static int fbuf[FBUFSZ]; int savfc, savtc, savlc; if(x == tabch) rchar = tabc | chbits; else if(x == ldrch) rchar = dotc | chbits; temp = npad = ws = 0; savfc = fc; savtc = tabch; savlc = ldrch; tabch = ldrch = fc = IMP; for(j=0;;j++){ if((tabtab[j] & TMASK)== 0){ if(x==savfc)prstr("Zero field width.\n"); j = 0; goto rtn; } if((length = ((tabtab[j] & TMASK) - v.hp)) > 0 )break; } type = tabtab[j]f +FBUFSZ - 3)) break; } *fp++ = i; *fp++ = 0; if(type == RTAB)length =- ws; else length =- ws/2; /*CTAB*/ if(((j = width(rchar)) == 0) || (length <= 0))nchar = 0; else{ nchar = length/j; length =% j; } length = (length/HOR)*HOR; j = makem(length); cp = fbuf; nlflg = 0; } rtn: fc = savfc; tabch = savtc; ldrch = savlc; return(j); } dummy(){} #include "tdef.h" #include "t.h" #include "tw.h" /* nroff10.c Device interfaces */ extern int lss; extern char obuf[]; extern char *obufp; extern int xfont; extern int esc; extern int lead; extern int *dip; extern int oline[]; extern int *olinep; extern int ulfont; extern int esct; extern int sps; extern int ics; extern int Hinc, Vinc; extern int ttysave; extern int ttys[3]; extern char termtab[]; extern int ptid; extern int waitf; extern int pipeflg; extern int eqflg; extern int xxx; int bdmode; int plotont != 2)){ oputs(t.bdoff); bdmode = 0; } /***/ } else if (xfont == 2) /***/ nbold = 1; /***/ dobold: codep = t.codetab[k-32]; w = t.Char * (*codep++ & 0177); phyw = w; if(i&ZBIT)w = 0; esct =+ w; if(*codep && (esc || lead))move(); if(xfont == ulfont){ for(k=w/t.Char;k>0;k--)oput('_'); for(k=w/t.Char;k>0;k--)oput('\b'); } while(*codep != 0){ if(*codep & 0200){ codep = plot(codep); oputs(t.plotoff); oput(' '); }else{ if(plotmode)oputs(t.plotoff); oput(*codep++); } #include "tdef.h" #include "t.h" #include "tw.h" /* troff9.c misc functions */ extern int cbuf[]; extern int *cp; extern int ch; extern int chbits; extern int dfact; extern int vflag; extern int pts; extern int fc; extern int padc; extern int tabtab[]; extern int nlflg; extern int lss; extern int tabch, ldrch; extern int tabc, dotc; extern int nchar, rchar; extern int xxx; setz(){ register i; if(!((i = getch()) & MOT))i =| ZBIT; return(i); } setline(){ register *i, length, c; int w, cnt, delim, rem if((delim = getch()) & MOT)return; else delim =& CMASK; j = cbuf + 1; cnt = 0; #ifdef NROFF dwn = (2*t.Halfline) | MOT | VMOT; #endif #ifndef NROFF dwn = EM | MOT | VMOT; #endif while(((k = (i = getch()) & CMASK) != delim) && (k != '\n') && (j <= (cbuf+NC-4))){ *j++ = i | ZBIT; *j++ = dwn; cnt++; } if(--cnt < 0)return; else if (!cnt){ ch = *(j-2); return; } *j = 0; #ifdef NROFF *--j = *cbuf = (cnt*t.Halfline) | MOT | NMOT | VMOT; #endif #ifndef NROFF *--j = *cbuf = (cnt*EM)/2 #include "tdef.h" /* troff8.c hyphenation */ char hbuf[NHEX]; char *nexth hbuf; int *hyend; extern int *wdstart, *wdend; extern int *hyptr[]; extern int **hyp; extern int hyoff; extern int suffid; extern int sufind[26]; char *sufoff -1; extern int noscale; extern int xxx; #define THRESH 160 /*digram goodness threshold*/ int thresh THRESH; hyphen(wp) int *wp; { register *i, j; i = wp; while(punct(*i++)); if(!alph(*--i))return; wdstart = i++; while(alph(*i++)); hyend = wdend = --i-1; while(punct(mode; ptinit(){ register i; register char **p, *q; char *x[8]; if((i = open(termtab,0)) < 0){ prstr("Cannot open "); prstr(termtab); prstr("\n"); exit(-1); } read(i,x,sizeof x); read(i,&t.bset,q = 4*(&t.zzz - &t.bset)); /***/ x[2] =- q; q = setbrk(x[2]); seek(i,t.twinit+040,0); /***/ i = read(i,q,x[2]); q =- t.twinit; for(p = &t.twinit; p < &t.zzz; p++){ if(*p)*p =+ q;else *p = &t.zzz; } sps = EM; ics = EM*2; if(t.bset || t.breset){ ttys[2] =& ~t.breset; ttys[2] =| t.bset;} /***/ if (nbold) { /***/ nbold--; /***/ for(k=phyw/t.Char;k>0;k--) oput('\b'); /***/ k = i & CMASK; /***/ goto dobold; /***/ } if(!w)for(k=phyw/t.Char;k>0;k--)oput('\b'); } } plot(x) char *x; { register int i; register char *j, *k; if(!plotmode)oputs(t.ploton); k = x; if((*k & 0377) == 0200)k++; for(; *k; k++){ if(*k & 0200){ if(*k & 0100){ if(*k & 040)j = t.up; else j = t.down; }else{ if(*k & 040)j = t.left; else j = t.right; } if(!(i = *k & 037))return(++k); while(i, temp; if((delim = getch()) & MOT)return; else delim =& CMASK; vflag = 0; dfact = EM; length = quant(atoi(),HOR); dfact = 1; if(!length){ eat(delim); return; } s0: if(((c = getch()) & CMASK) == delim){ ch = c; c = 0204 | chbits; }else if((c & CMASK) == FILLER)goto s0; w = width(c); i = cbuf; if(length < 0){ *i++ = makem(length); length = -length; } if(!(cnt = length/w)){ *i++ = makem(-(temp = ((w-length)/2))); *i++ = c; *i++ = makem(-(w - length - temp)); goto s1; } i| MOT | NMOT | VMOT; #endif *--j =& ~ZBIT; cp = cbuf; } setvline(){ register i, c, *k; int cnt, neg, rem, ver, delim; if((delim = getch()) & MOT)return; else delim =& CMASK; dfact = lss; vflag++; i = quant(atoi(),VERT); dfact = 1; if(!i){ eat(delim); vflag = 0; return; } if(((c = getch()) & CMASK) == delim){ c = 0337 | chbits; /*default box rule*/ }else getch(); c =| ZBIT; neg = 0; if(i < 0){ i = -i; neg = NMOT; } #ifdef NROFF ver = 2*t.Halfline; #endif #ifndef NROFF ver = & (~TMASK); fp = fbuf; pp = padptr; if(x == savfc){while(1){ if(((j = (i = getch()) & CMASK)) == padc){ npad++; *pp++ = fp; if(pp > (padptr + NPP - 1))break; goto s1; }else if(j == savfc) break; else if(j == '\n'){ temp = j; nlflg = 0; break; } ws =+ width(i); s1: *fp++ = i; if(fp > (fbuf + FBUFSZ -3))break; } if(!npad){ npad++; *pp++ = fp; *fp++ = 0; } *fp++ = temp; *fp++ = 0; temp = i = (j = length-ws)/npad; i = (i/HOR)*HOR; if((j =- i*npad) <0)j *i++)); if(*--i)return; if((wdend-wdstart-4) < 0)return; hyp = hyptr; *hyp = 0; hyoff = 2; if(exword() || suffix())goto rtn; digram(); rtn: *hyp++ = 0; if(*hyptr)for(j = 1; j;){ j = 0; for(hyp = hyptr+1; *hyp != 0; hyp++){ if(*(hyp-1) > *hyp){ j++; i = *hyp; *hyp = *(hyp-1); *(hyp-1) = i; } } } } punct(i) int i; { if(!i || alph(i))return(0); else return(1); } alph(i) int i; { register j; j = i & CMASK; if(((j >= 'A') && (j <= 'Z')) || ((j >= 'a') && (j <= 'z'))) stty(1,ttys); } oputs(t.twinit); if(eqflg)t.Adj = t.Hor; } twdone(){ oputs(t.twrest); if(pipeflg){ close(ptid); wait(&waitf); } ttys[2] = ttysave; stty(1,ttys); } ptout(i) int i; { *olinep++ = i; if(olinep >= &oline[LNSIZE])olinep--; if((i&CMASK) != '\n')return; olinep--; lead =+ dip->blss + lss - t.Newline; dip->blss = 0; esct = esc = 0; if(olinep>oline){ move(); ptout1(); oputs(t.twnl); }else{ lead =+ t.Newline; move(); } lead =+ dip->alss; dip->alss = 0; olinep = oli--)oputs(j); }else oput(*k); } return(k); } move(){ register k; register char *i, *j; char *p, *q; /***/ if(esct =+ esc)i = "\0"; else i = t.twnl; j = t.hlf; p = t.right; q = t.down; if(lead){ if(lead < 0){ lead = -lead; if(!esc)i = t.flr; else i = "\0"; j = t.hlr; q = t.up; } /***/ if(*i){ k = lead/t.Newline; lead = lead%t.Newline; while(k--)oputs(i); } /***/ if(*j){ k = lead/t.Halfline; lead = lead%t.Halfline; while(k--)oputs(j); } } if(esc){ if(esc f(rem = length%w){ switch(c & CMASK){ case 0204: /*rule*/ case 0224: /*underrule*/ case 0276: /*root en*/ *i++ = c | ZBIT; default: *i++ = makem(rem); } } if(cnt){ *i++ = RPT; *i++ = cnt; *i++ = c; } s1: *i++ = 0; eat(delim); cp = cbuf; } eat(c) int c; { register i; while(((i = getch() & CMASK) != c) && (i != '\n')); return(i); } setov(){ register i, j, k; int *p, delim, o[NOV], w[NOV]; if((delim = getch()) & MOT)return; else delim =& CMASK; for(k=0; (k 0; npad--){ *(*--pp) = i; if(j){ j =- HOR; (*(*pp)) =+ HOR; } } cp = fbuf; j = 0; }else if(type == 0){ /*plain tab or leader*/ if((j = width(rchar)) == 0)nchar = 0; else{ nchar = length /j; length =% j; } if(length)j = length | MOT; else j = getch0(); }else{ /*center tab*/ /*right tab*/ while(((j = (i = getch()) & CMASK) != savtc) && (j != '\n') && (j != savlc)){ ws =+ width(i); *fp++ = i; if(fp > (fbu return(1); else return(0); } caseht(){ register i; thresh = THRESH; if(skip())return; noscale++; thresh = atoi(); noscale = 0; } casehw(){ register i, k; register char *j; k = 0; while(!skip()){ if((j = nexth) >= (hbuf + NHEX - 2)){ full: prstr("Exception word list full.\n"); *nexth = 0; return; } while(1){ if((i = getch()) & MOT)continue; if(((i =& CMASK) == ' ') || (i == '\n')){ *j++ = 0; nexth = j; *j = 0; if(i == ' ')break; else return; } if(i == '-'){ k = 0200; continue; } *j++ = maplow(i) | k; k = 0; if(j >= (hbuf + NHEX - 2))goto full; } } } exword(){ register int *w, i; register char *e; char *save; e = hbuf; while(1){ save = e; if(*e == 0)return(0); w = wdstart; while((*e && (w <= hyend)) && ((*e & 0177) == maplow(*w & CMASK))){e++; w++;}; if(!*e){ if(((w-1) == hyend) || ((w == wdend) && ((i = maplow(*w & CMASK)) == 's'))){ w = wdstart; for(e = save; *e; e++){ if(*e & 0read(suffid, sufbuf, SBSZ); } return(sufbuf[i & (SBSZ-1)]); } digram(){ register *w, val; int *nhyend, *maxw, maxval; extern char bxh[], bxxh[], xxh[], xhx[], hxx[]; again: if(!(w=chkvow(hyend+1)))return; hyend = w; if(!(w=chkvow(hyend)))return; nhyend = w; maxval = 0; w--; while((++w < hyend) && (w < (wdend-1))){ val = 1; if(w == wdstart)val =* dilook('a',*w,bxh); else if(w == wdstart+1)val =* dilook(*(w-1),*w,bxxh); else val =* dilook(*(w-1),*w,xxh); val =* dilook(*w, *(w+1), xhx); tern int lgf; extern int pl; extern int npn; extern int npnflg; extern int *frame; extern int *dip; extern int copyf; extern char nextf[]; extern int trap; extern int lss; extern int em; extern int evlist[EVLSZ]; extern int evi; extern int ibf; extern int ev; extern int ch; extern int nflush; extern int tty; extern int ittys[3]; /***/ extern int quiet; extern int iflg; extern int eschar; extern int lit; extern int *litlev; extern int ls; extern int ls1; extern int tabtab[]; extern char trtab[]; extern int c(){ dotc = chget(0); } casehy(){ register i; hyf = 1; if(skip())return; noscale++; i = atoi(); noscale = 0; if(nonumb)return; hyf = max(i,0); } casenh(){ hyf = 0; } max(aa,bb) int aa,bb; { if(aa>bb)return(aa); else return(bb); } casece(){ register i; noscale++; skip(); i = max(atoi(),0); if(nonumb)i = 1; tbreak(); ce = i; noscale = 0; } casein(){ register i; if(skip())i = in1; else i = max(hnumb(&in),0); tbreak(); in1 = in; in = i; if(!nc){ un = in; setnel(); } } casell() lgf++; skip(); if(!(j=getrq()))return; else for(k=0; kop)return; savframe = frame; skip(); ifi >= NIF){ prstr("if-else overflow.\n"); ifi = 0; edone(040); } caseif(1); ifi++; } caseif(x) int x; { register i, notflag, true; if(x == 2){ notflag = 0; true = iflist[ifi]; goto i1; } true = 0; skip(); if(((i = getch()) & CMASK) == '!'){ notflag = 1; }else{ notflag = 0; ch = i; } i = atoi(); if(!nonumb){ if(i > 0)true++; goto i1; } switch((i = getch()) & CMASK){ case 'e': if(!(v.pn & 01))true++; break; case 'o': if(v.pn & 01)true++; break; #ifdef NRO200)*hyp++ = w; if(hyp > (hyptr+NHYP-1)) hyp = hyptr+NHYP-1; w++; } return(1); }else{e++; continue;} }else while(*e++); } } suffix(){ register int *w; register char *s, *s0; int i; char *off; again: if(!alph(i = *hyend & CMASK))return(0); if(i < 'a')i =- 'A'; else i =- 'a'; if(!(off = sufind[i]))return(0); while(1){ if((i = *(s0 = getsuf(off)) & 017) == 0)return(0); off =+ i; s = s0 + i - 1; w = hyend - 1; while(((s > s0) && (w >= wdstart)) && ((*s & 0177) ul; extern int cu; extern int sfont; extern int font; extern int fontlab[]; extern int it; extern int itmac; extern int noscale; extern int ic; extern int icf; extern int ics; extern int *vlist; extern int sv; extern int esc; extern int nn; extern int nms; extern int ndf; extern int lnmod; extern int ni; extern int lnsize; extern int nb; extern int offset; extern int nlflg; extern int apts, apts1, pts, pts1, font, font1; extern int ulfont; extern int ulbit; extern int error; extern int nmbits; extern int ch{ register i; if(skip())i = ll1; else i = max(hnumb(&ll),INCH/10); ll1 = ll; ll = i; setnel(); } caselt(){ register i; if(skip())i = lt1; else i = max(hnumb(<),0); lt1 = lt; lt = i; } caseti(){ register i; if(skip())return; i = max(hnumb(&in),0); tbreak(); un1 = i; setnel(); } casels(){ register i; noscale++; if(skip())i = ls1; else i = max(inumb(&ls),1); ls1 = ls; ls = i; noscale = 0; } casepo(){ register i; if(skip())i = po1; else i = max(hnumb(&po),0); po1 = po; po = i if((i = inumb(&v.pn)) < 0)i = 0; tbreak(); if(!nonumb){ npn = i; npnflg++; }else if(dip->nls)return; eject(savframe); } casetm(){ register i; char tmbuf[NTM]; lgf++; copyf++; skip(); for(i=0; inls || trap)return; i = findt1(); if(!a){ skip(); j = vnumb(0); if(nonumb)j = lss; }else j = a; if(j == FF case 'n': true++; case 't': #endif #ifndef NROFF case 't': true++; case 'n': #endif case ' ': break; default: true = cmpstr(i); } i1: true =^ notflag; if(x == 1)iflist[ifi] = !true; if(true){ i2: do{ v.hp = 0; } while(((i = getch()) & CMASK) == ' '); if((i & CMASK) == LEFT)goto i2; ch = i; nflush++; }else{ copyf++; if(eat(LEFT) == LEFT){ while(eatblk(RIGHT,LEFT) != RIGHT)nlflg = 0; } copyf--; } } eatblk(right,left) int right,left; { register i; e0 == maplow(*w))){s--; w--;}; if(s == s0)break; } s = s0 + i - 1; w = hyend; if(*s0 & 0200)goto mark; while(s > s0){ w--; if(*s-- & 0200){ mark: hyend = w - 1; if(*s0 & 0100)continue; if(!chkvow(w))return(0); *hyp++ = w; } } if(*s0 & 040)return(0); if(exword())return(1); goto again; } maplow(i) int i; { if((i =& CMASK) < 'a')i =+ 'a' - 'A'; return(i); } vowel(i) int i; { switch(maplow(i)){ case 'a': case 'e': case 'i': case 'o': case 'u': case 'y': return(1); val =* dilook(*(w+1), *(w+2), hxx); if(val > maxval){ maxval = val; maxw = w + 1; } } hyend = nhyend; if(maxval > thresh)*hyp++ = maxw; goto again; } dilook(a,b,t) int a, b; char t[26][13]; { register i, j; i = t[maplow(a)-'a'][(j = maplow(b)-'a')/2]; if(!(j & 01))i =>> 4; return(i & 017); } bits; extern int tdelim; extern int xxx; int iflist[NIF]; int ifi; extern struct contab { int rq; int (*f)(); }contab[NM]; casead(){ register i; ad = 1; /*leave admod alone*/ if(skip())return; switch((i = getch()) & CMASK){ case 'r': /*right adj, left ragged*/ admod = 2; break; case 'l': /*left adj, right ragged*/ admod = ad = 0; /*same as casena*/ break; case 'c': /*centered adj*/ admod = 1; break; case 'b': case 'n': admod = 0; break; } } casena(){ ad = 0; } case; #ifndef NROFF if(!ascii)esc =+ po - po1; #endif } casepl(){ register i; skip(); if((i = vnumb(&pl)) == 0)pl = 11 * INCH; /*11in*/ else pl = i; if(v.nl > pl)v.nl = pl; } casewh(){ register i, j, k; lgf++; skip(); i = vnumb(0); if(nonumb)return; skip(); j = getrq(); if((k=findn(i)) != NTRAP){ mlist[k] = j; return; } for(k=0; kop)i = dip->dnl; else i = v.nl; if((i + j) < 0)j = -i; lss = j; newline(0); lss = savlss; } casert(){ register a, *p; skip(); if(dip->op)p = &dip->dnl; else p = &v.nl; a = vnumb(p); if(nonumb)a = dip->mkline; if((a < 0) || (a >= *p))return; nb++; casesp(a - *p); } caseem(){ lgf++; skip(); em = getrq(); } casefl(){ tbreak(); flusho(); } caseev(){ register nxev; extern int block; if(skip()){ e0: if(evi == 0)return; nxev = evlist[--e: while(((i = getch() & CMASK) != right) && (i != left) && (i != '\n')); if(i == left){ while((i=eatblk(right,left)) != right)nlflg = 0; goto e0; } return(i); } cmpstr(delim) int delim; { register i, j, p; int begin, cnt, k; int savapts, savapts1, savfont, savfont1, savpts, savpts1; if(delim & MOT)return(0); delim =& CMASK; if(dip->op)wbfl(); if((offset = begin = alloc()) == 0)return(0); cnt = 0; v.hp = 0; savapts = apts; savapts1 = apts1; savfont = font; savfont1 = font1; savpt default: return(0); } } chkvow(w) int *w; { while(--w >= wdstart)if(vowel(*w & CMASK))return(w); return(0); } getsuf(x) char *x; { register char *s; register cnt; static char suff[20]; s = suff; for(cnt = ((*s++ = rdsufb(x++)) & 017); cnt > 1; cnt--) *s++ = rdsufb(x++); suff[suff[0] & 017] = 0; return(suff); } #define SBSZ 128 /*suffix file buffer size*/ rdsufb(i) char *i; { register char *j; static char sufbuf[SBSZ]; if((j = i & ~(SBSZ-1)) != sufoff){ seek(suffid, sufoff = j, 0); #include "tdef.h" #include "t.h" /* troff5.c misc processing requests */ extern int ascii; extern int nonumb; extern int admod; extern int ad; extern int fi; extern int cc; extern int c2; extern int ohc; extern int tabc; extern int dotc; extern int pendnf; extern int hyf; extern int ce; extern int po; extern int po1; extern int nc; extern int in; extern int un; extern int un1; extern int in1; extern int ll; extern int ll1; extern int lt; extern int lt1; extern int nlist[NTRAP]; extern int mlist[NTRAP]; exfi(){ tbreak(); fi++; pendnf = 0; lnsize = LNSIZE; } casenf(){ tbreak(); fi = 0; /* can't do while oline is only LNSIZE lnsize = LNSIZE + WDSIZE; */ } casers(){ dip->nls = 0; } casens(){ dip->nls++; } chget(c) int c; { register i; if(skip() || ((i = getch()) & MOT) || ((i&CMASK) == ' ') || ((i&CMASK) == '\n')){ ch = i; return(c); }else return(i & BMASK); } casecc(){ cc = chget('.'); } casec2(){ c2 = chget('\''); } casehc(){ ohc = chget(OHC); } casetc(){ tabc = chget(0); } casel  vi]; goto e1; } noscale++; nxev = atoi(); noscale = 0; if(nonumb)goto e0; flushi(); if((nxev >= NEV) || (nxev < 0) || (evi >= EVLSZ)){ prstrfl("Cannot do ev.\n"); if(error)done2(040);else edone(040); return; } evlist[evi++] = ev; e1: if(ev == nxev)return; seek(ibf, ev*EVS*4, 0); /***/ write(ibf, &block, EVS*4); /***/ seek(ibf, nxev*EVS*4, 0); /***/ read(ibf, &block, EVS*4); /***/ ev = nxev; } caseel(){ if(--ifi < 0){ ifi = 0; iflist[0] = 0; } caseif(2); } caseie(){ if(s = pts; savpts1 = pts1; while(((j = (i=getch()) & CMASK) != delim) && (j != '\n')){ wbf(i); cnt++; } wbt(0); k = !cnt; if(nlflg)goto rtn; p = begin; apts = savapts; apts1 = savapts1; font = savfont; font1 = savfont1; pts = savpts; pts1 = savpts1; mchbits(); v.hp = 0; while(((j = (i=getch()) & CMASK) != delim) && (j != '\n')){ if(rbf0(p) != i){ eat(delim); k = 0; break; } p = incoff(p); k = !(--cnt); } rtn: apts = savapts; apts1 = savapts1; font = savfont; font1 = savfont1; pts = savpts; pts1 = savpts1; mchbits(); offset = dip->op; free(begin); return(k); } casest(){ dummy(); } caserd(){ lgf++; skip(); getname(); if(!iflg){ if(quiet){ ittys[2] =& ~ECHO; /***/ stty(0,ittys); /***/ prstrfl(""); /*bell*/ }else{ if(nextf[0]){ prstr(nextf); prstr(":"); }else{ prstr(""); /*bell*/ } } } collect(); tty++; pushi(-1); } rdtty(){ char onechar; /***/ onechar = 0; if(read(0, &onechar, 1) == 1){ if(onechar == '\n')tty++;t(){ register i; lgf++; it = itmac = 0; noscale++; skip(); i = atoi(); skip(); if(!nonumb && (itmac = getrq()))it = i; noscale = 0; } casemc(){ register i; if(icf > 1)ic = 0; icf = 0; if(skip())return; ic = getch(); icf = 1; skip(); i = max(hnumb(0),0); if(!nonumb)ics = i; } casemk(){ register i, j; if(dip->op)j = dip->dnl; else j = v.nl; if(skip()){ dip->mkline = j; return; } if((i = getrq()) == 0)return; vlist[findr(i)] = j; } casesv(){ register i; skip(); if((i = vnumb(extern int ch; extern int res; extern int xxx; int fontlab[] {'R','I','B','S',0}; width(c) int c; { register i,j,k; j = c; k = 0; if(j & MOT){ if(j & VMOT)goto rtn; k = j & ~MOTV; if(j & NMOT)k = -k; goto rtn; } if((i = (j & CMASK)) == 010){ k = -widthp; goto rtn; } if(i == PRESC)i = eschar; if((i == ohc) || (i >= 0370))goto rtn; if(j & ZBIT)goto rtn; i = trtab[i] & BMASK; if(i < 040)goto rtn; k = (*(t.codetab[i-32]) & 0177) * t.Char; widthp = k; rtn: return(k); } setch(){ sb)v.sb = base; if((k=base + em) > v.st)v.st = k; } nform = 0; setn1(wid); v.hp = savhp; level = savlevel; font = savfont; font1 = savfont1; mchbits(); setwdf = 0; } vmot(){ dfact = lss; vflag++; return(mot()); } hmot(){ dfact = EM; return(mot()); } mot(){ register i, j; j = HOR; getch(); /*eat delim*/ if(i = atoi()){ if(vflag)j = VERT; i = makem(quant(i,j)); } getch(); vflag = 0; dfact = 1; return(i); } sethl(k) int k; { register i; i = t.Halfline; if(k == 'u')i = -i; elsint nform; extern int ll; extern int in; extern int font; extern int lss; extern int pts; extern int font1; extern int *dip; extern int fi; extern int res; extern int cwidth; extern int dotT; extern int ulfont; extern int ev; extern int xxx; extern struct contab { int rq; int (*f)(); }contab[NM]; setn() { register i,j; int f; f = nform = 0; if((i=getch() & CMASK) == '+')f = 1; else if(i == '-')f = -1; else ch = i; if((i=getsn()) == 0)return; switch(i){ case '.s': i = pts & 077; break; casorm){ default: case '1': case 0: return(decml(i,f) + j); case 'i': case 'I': return(roman(i,f) + j); case 'a': case 'A': return(abc(i,f) + j); } } decml(i,f) int i, (*f)(); { register j,k; k = 0; nform--; if((j=i/10) || (nform > 0))k = decml(j,f); return(k + (*f)((i%10 + '0') | nrbits)); } roman(i,f) int i, (*f)(); { if(!i)return((*f)('0' | nrbits)); if(nform == 'i')return(roman0(i,f,"ixcmz","vldw")); else return(roman0(i,f,"IXCMZ","VLDW")); } roman0(i,f,onesp,fivesp) int i, (*f)(); else tty = 1; if(tty != 3)return(onechar); } popi(); tty = 0; if(quiet){ ittys[2] =| ECHO; /***/ stty(0,ittys); /***/ } return(0); } caseec(){ eschar = chget('\\'); } caseeo(){ eschar = 0; } caseli(){ skip(); lit = max(inumb(0),1); litlev = frame; if((!dip->op) && (v.nl == -1))newline(1); } caseta(){ register i, j; tabtab[0] = nonumb = 0; for(i=0; ((i < (NTAB-1)) && !nonumb); i++){ if(skip())break; tabtab[i] = max(hnumb(&tabtab[max(i-1,0)]),0) & TMASK; if(!nonumb) switch(0)) < 0)return; if(nonumb)i = 1; sv =+ i; caseos(); } caseos(){ register savlss; if(sv <= findt1()){ savlss = lss; lss = sv; newline(0); lss = savlss; sv = 0; } } casenm(){ register i; lnmod = nn = 0; if(skip())return; lnmod++; noscale++; i = inumb(&v.ln); if(!nonumb)v.ln = max(i,0); getnm(&ndf,1); getnm(&nms,0); getnm(&ni,0); noscale = 0; nmbits = chbits; } getnm(p,min) int *p, min; { register i; eat(' '); if(skip())return; i = atoi(); if(nonumb)return; *p = max(i,min);register i,*j,k; extern int chtab[]; if((i = getrq()) == 0)return(0); for(j=chtab;*j != i;j++)if(*(j++) == 0)return(0); k = *(++j) | chbits; return(k); } find(i,j) int i,j[]; { register k; if(((k = i-'0') >= 1) && (k <= 4) && (k != smnt))return(--k); for(k=0; j[k] != i; k++)if(j[k] == 0)return(-1); return(k); } mchbits(){ register i, j, k; chbits = (((pts)<<2) | font) << (BYTE + 1); sps = width(' ' | chbits); } setps(){ register i,j; if((((i=getch() & CMASK) == '+') || (i == '-')) && (e if(k == 'r')i = -2*i; vflag++; i = makem(i); vflag = 0; return(i); } makem(i) int i; { register j; if((j = i) < 0)j = -j; j = (j & ~MOTV) | MOT; if(i < 0)j =| NMOT; if(vflag)j =| VMOT; return(j); } casefp(){ register i, j, k; skip(); if(((i = (getch() & CMASK) - '0' -1) < 0) || (i >3))return; if(skip() || !(j = getrq()))return; fontlab[i] = j; } casevs(){ register i; skip(); vflag++; dfact = INCH; /*default scaling is points!*/ dfactd = 72; res = VERT; i = inumb(&lss); if(nonumb)e '.v': i = lss; break; case '.f': i = font + 1; break; case '.p': i = pl; break; case '.t': i = findt1(); break; case '.o': i = po; break; case '.l': i = ll; break; case '.i': i = in; break; case '.$': i = *frame; break; case '.A': i = ascii; break; case '.c': i = iline; break; case '.n': i = lastl; break; case '.a': i = ralss; break; case '.h': i = dip->hnl; break; case '.d': if(dip->op)i = dip->dnl; else i = v.nl; break; case '.u': i = fi; break; case '.w': char *onesp, *fivesp; { register q, rem, k; k = 0; if(!i)return(0); k = roman0(i/10,f,onesp+1,fivesp+1); q = (i=i%10)/5; rem = i%5; if(rem == 4){ k =+ (*f)(*onesp | nrbits); if(q)i = *(onesp+1); else i = *fivesp; return(k =+ (*f)(i | nrbits)); } if(q)k =+ (*f)(*fivesp | nrbits); while(--rem >= 0) k =+ (*f)(*onesp | nrbits); return(k); } abc(i,f) int i, (*f)(); { if(!i)return((*f)('0' | nrbits)); else return(abc0(i-1,f)); } abc0(i,f) int i, (*f)(); { register j, k; k = 0; if(j=ij = ch & CMASK){ case 'C': tabtab[i] =| CTAB; break; case 'R': tabtab[i] =| RTAB; break; default: /*includes L*/ break; } nonumb = ch = 0; } tabtab[i] = 0; } casene(){ register i, j; skip(); i = vnumb(0); if(nonumb)i = lss; if(i > (j = findt1())){ i = lss; lss = j; dip->nls = 0; newline(0); lss = i; } } casetr(){ register i, j; lgf++; skip(); while((i = getch() & CMASK) != '\n'){ if((j = getch()) & MOT)return; if((j =& CMASK) == '\n')j = ' '; t } casenn(){ noscale++; skip(); nn = max(atoi(),1); noscale = 0; } ((j=(ch = getch() & CMASK) - '0') >= 0) && (j <= 9))){ ch = 0; return; } if((i =- '0') == 0){ return; } if((i > 0) && (i <= 9)){ if((i <= 3) && ((j=(ch = getch() & CMASK) - '0') >= 0) && (j <= 9)){ i = 10*i +j; ch = 0; } } } caseft(){ skip(); setfont(1); } setfont(a) int a; { register i,j; if(a)i = getrq(); else i = getsn(); if(!i || (i == 'P')){ j = font1; goto s0; } if(i == 'S')return; if((j = find(i,fontlab)) == -1)return; s0: font1 = font; font = j; mchbits();i = lss1; if(i < VERT)i = VERT; lss1 = lss; lss = i; } xlss(){ register i, j; getch(); dfact = lss; i = quant(atoi(),VERT); dfact = 1; getch(); if((j = i) < 0)j = -j; ch0 = ((j & 03700)<<3) | HX; if(i < 0)ch0 =| 040000; return(((j & 077)<<9) | LX); } caseps(){} caselg(){} casecs(){} casebd(){} casess(){} getlg(i) int i; { return(i); } i = cwidth; break; case '.x': i = ulfont + 1; break; case '.y': i = font1; break; case '.T': i = dotT; break; case '.V': i = VERT; break; case '.H': i = HOR; break; case '.z': i = dip->curd; cbuf[0] = i & BMASK; cbuf[1] = (i >> BYTE) & BMASK; cbuf[2] = 0; cp = cbuf; return; default: if((j=findr(i)) == -1)i = 0; else{ i = (vlist[j] = (vlist[j] + inc[j]*f)); nform = fmt[j]; } } setn1(i); cp = &cbuf; } setn1(i) int i; { int j; extern int wrc(); cp = &/26)k = abc0(j-1,f); return(k + (*f)((i%26 + nform) | nrbits)); } wrc(i) int i; { if(cp >= &cbuf[NC])return(0); *cp++ = i; return(1); } atoi(){ register i; extern LONG0 atoi0(); return(i=atoi0()); } LONG0 atoi0() { register ii, k, cnt; LONG0 i, acc; extern LONG0 ckph(); i = 0; acc = 0; nonumb = 0; cnt = -1; a0: cnt++; switch((ii=getch()) & CMASK){ default: ch = ii; if(cnt)break; case '+': i = ckph(); if(nonumb)break; acc =+ i; goto a0; case '-': i = ckph(); if(rtab[i] = j; } } casecu(){ cu++; caseul(); } caseul(){ register i; noscale++; if(skip())i = 1; else i = atoi(); if(ul && (i == 0)){ font = sfont; ul = cu = 0; } if(i){ if(!ul){ sfont = font; font = ulfont; } ul = i; } noscale = 0; mchbits(); } caseuf(){ register i, j; if(skip() || !(i = getrq()) || (i == 'S') || ((j = find(i,fontlab)) == -1)) ulfont = 1; /*default position 2*/ else ulfont = j; #ifdef NROFF if(ulfont == 0)ulfont = 1; #endif ulbit = ulfont<<9; } casei#include "tdef.h" #include "t.h" #include "tw.h" /* troff6.c width functions, sizes and fonts */ extern int eschar; extern int widthp; extern int ohc; extern int xfont; extern int smnt; extern int setwdf; extern char trtab[]; extern int chbits; extern int nonumb; extern int noscale; extern int font; extern int font1; extern int pts; extern int sps; extern int nlflg; extern int nform; extern int dfact; extern int dfactd; extern int lss; extern int lss1; extern int vflag; extern int ch0; extern int level; } setwd(){ register i, base, wid; int delim, em, k; int savlevel, savhp, savfont, savfont1; base = v.st = v.sb = wid = v.ct = 0; if((delim = getch() & CMASK) & MOT)return; savhp = v.hp; savlevel = level; v.hp = level = 0; savfont = font; savfont1 = font1; setwdf++; while((((i = getch()) & CMASK) != delim) && !nlflg){ wid =+ width(i); if(!(i & MOT)){ em = 2*t.Halfline; }else if(i & VMOT){ k = i & ~MOTV; if(i & NMOT)k = -k; base =- k; em = 0; }else continue; if(base < v.#include "tdef.h" #include "t.h" #include "tw.h" /* troff4.c number registers, conversion, arithmetic */ extern int ascii; extern int cbuf[NC]; extern int *cp; extern int r[NN]; extern int *vlist; extern int inc[NN]; extern int fmt[NN]; extern int ch; extern int lgf; extern int *frame; extern int pl; extern int iline; extern int lastl; extern int ralss; extern int totout; extern int nrbits; extern int nonumb; extern int vflag; extern int noscale; extern int dfact; extern int dfactd; extern int po; extern cbuf; nrbits = 0; j=fnumb(i,wrc); *cp = 0; cp = &cbuf; } findr(i) int i; { register j; static int numerr; if(i == 0)return(-1); for(j=0;j 1)done2(04); else edone(04); } return(j); } fnumb(i,f) int i, (*f)(); { register j; j = 0; if(i < 0){ j = (*f)('-' | nrbits); i = -i; } switch(nf          nonumb)break; acc =- i; goto a0; case '*': i = ckph(); if(nonumb)break; acc = acc * i; goto a0; case '/': i = ckph(); if(nonumb)break; if(i == 0){ prstrfl("Divide by zero.\n"); acc = 0; }else acc =/ i; goto a0; case '%': i = ckph(); if(nonumb)break; acc =% i; goto a0; case '&': /*and*/ i = ckph(); if(nonumb)break; if((acc > 0) && (i > 0))acc = 1; else acc = 0; goto a0; case ':': /*or*/ i = ckph(); if(nonumb)break; if((acc > j = EM; #ifndef NROFF i = 2; #endif #ifdef NROFF i = 1; /*Same as Ems in NROFF*/ #endif break; case 'p': /*Points*/ j = INCH; i = 72; break; case 'i': /*Inches*/ j = INCH; i = 1; break; case 'c': /*Centimeters*/ j = INCH*50; i = 127; break; case 'P': /*Picas*/ j = INCH; i = 6; break; default: j = dfact; ch = i; i = dfactd; } if(neg) acc = -acc; if(!noscale){ acc = (acc*j)/i; } if((field != digits) && (digits > 0))while(digits--)acc =/#include "tdef.h" #include "t.h" /* troff3.c macro and string routines, storage allocation */ #define NBLIST 256 /*allocation list*/ #define BLK 128 /*alloc block words*/ /* BLK*NBLIST=32768 words */ extern int ch; extern int ibf; extern int nextb; extern char *enda; extern int lgf; extern int copyf; extern int ch0; extern int ip; extern int app; extern int ds; extern int nlflg; extern int *nxf; extern int *argtop; extern int *ap; extern int nchar; extern int *frame; extern int *stk; extern int pendt; b[i].f); contab[i].rq = contab[i].f = 0; } } finds(mn) int mn; { register i, savip; oldmn = findmn(mn); newmn = apptr = aplnk = 0; if(app && (oldmn >= 0) && (contab[oldmn].rq & MMASK)){ savip = ip; ip = contab[oldmn].f; oldmn = -1; while((i=rbf()) != 0); apptr = ip; if(!diflg)ip = incoff(ip); nextb = ip; ip = savip; }else{ for(i=0;i 1)done2(02); prstr("             & , 2 ! *p++ = pendt; *p++ = ap; *p++ = cp; *p++ = ch0; *p++ = ch; cp = nchar = rchar = pendt = ap = ch0 = ch = 0; frame = nxf; if(*nxf == 0) nxf =+ STKSIZE; else nxf = argtop; return(ip = newip); } setbrk(x) char *x; { register char *i; char *sbrk(); if((i = sbrk(x)) == -1){ prstrfl("Core limit reached.\n"); edone(0100); }else{ enda = i + x; } return(i); } getsn(){ register i; if((i=getach()) == 0)return(0); if(i == '(')return(getrq()); else return(i); } setstr(){ register i; lgf++0) || (i > 0))acc = 1; else acc = 0; goto a0; case '=': if(((ii=getch()) & CMASK) != '=')ch = ii; i = ckph(); if(nonumb){acc = 0; break;} if(i == acc)acc = 1; else acc = 0; goto a0; case '>': k = 0; if(((ii=getch()) & CMASK) == '=')k++; else ch =ii; i = ckph(); if(nonumb){acc = 0; break;} if(acc > (i - k))acc = 1; else acc = 0; goto a0; case '<': k = 0; if(((ii=getch()) & CMASK) == '=')k++; else ch =ii; i = ckph(); if(nonumb){acc = 0; break;} if(ac 10; if(abs){ if(dip->op)j = dip->dnl; else j = v.nl; if(!vflag)j = v.hp; if(abs == 2)j = -j; acc =- j; } a2: nonumb = !field; return(acc); } caserr(){ register i,j; lgf++; skip(); if((i=getrq()) == 0)return; for(j=13; j>BYTE; j =& BMASK; copyf++; flushi(); nlflg = 0; state = 1; wt i; { return(NEV*EVS + i*BLK); } wbt(i) int i; { wbf(i); wbfl(); } wbf(i) int i; { register j; if(!offset)return; if(!woff){ woff = offset; wbfi = 0; } wbuf[wbfi++] = i; if(!((++offset) & (BLK-1))){ wbfl(); if(blist[j = blisti(--offset)] == -1){ if(alloc() == 0){ prstr("Out of temp file space.\n"); done2(01); } blist[j] = nextb; } offset = blist[j]; } if(wbfi >= BLK)wbfl(); } wbfl(){ if(woff == 0)return; seek(ibf, woff<<2, 0); /***/ write(ibf, &wbuf, wbfi<<2); ; if(((i=getsn()) == 0) || ((i=findmn(i)) == -1) || !(contab[i].rq & MMASK)){ lgf--; return(0); }else{ if((enda-2) < nxf)setbrk(DELTA); *nxf = 0; strflg++; lgf--; return(pushi(contab[i].f)); } } collect() { register i; register int *strp; int *argpp, *argppend; int quote, *savnxf, *lim; copyf++; *nxf = 0; if(skip())goto rtn; savnxf = nxf; lim = nxf =+ 20*STKSIZE; strflg = 0; if((argppend = strp = (argpp = savnxf+STKSIZE) + 9) > enda)setbrk(DELTA); while((argpp != argppec < (i + k))acc = 1; else acc = 0; goto a0; case ')': break; case '(': acc = atoi0(); goto a0; } return(acc); } LONG0 ckph(){ register i; LONG0 j; extern LONG0 atoi0(); extern LONG0 atoi1(); if(((i = getch()) & CMASK) == '(')j = atoi0(); else{ ch = i; j = atoi1(); } return(j); } LONG0 atoi1() { register i, j, digits; LONG0 acc; int neg, abs, field; neg = abs = field = digits = 0; acc = 0; a0: switch((i = getch()) & CMASK){ default: ch = i; break; case '+': gotj = atoi(); if(nonumb)goto rtn; inc[i] = j; rtn: return; } caseaf(){ register i, j, k; lgf++; if(skip() || !(i = getrq()) || skip())return; k = 0; if(!alph(j=getch())){ ch = j; while(((j = getch() & CMASK) >= '0') && (j <= '9'))k++; } if(!k)k=j; fmt[findr(i)] = k & BMASK; } vnumb(i) int i; { vflag++; dfact = lss; res = VERT; return(inumb(i)); } hnumb(i) int i; { dfact = EM; res = HOR; return(inumb(i)); } inumb(n) int *n; { register i, j, f; f = 0; if(n){ if((j = (i = getch()) { register i; offset = 0; if((i = copyb()) != '.')control(i,1); } casern(){ register i,j; lgf++; skip(); if(((i=getrq())==0) || ((oldmn=findmn(i)) < 0))return; skip(); clrmn(findmn(j=getrq())); if(j)contab[oldmn].rq = (contab[oldmn].rq & MMASK) | j; } caserm(){ lgf++; skip(); clrmn(findmn(getrq())); } caseas(){ app++; caseds(); } caseds(){ ds++; casede(); } caseam(){ app++; casede(); } casede(){ register i, savoff, req; if(dip->op)wbfl(); req = '.'; lgf++; skip(); if((i=getrq())=hile(1){ i = (ii = getch()) & CMASK; if(state == 3){ if(i == k)break; if(!k){ ch = ii; i = getach(); ch = ii; if(!i)break; } state = 0; goto c0; } if(i == '\n'){ state = 1; nlflg = 0; goto c0; } if((state == 1) && (i == '.')){ state++; savoff = offset; goto c0; } if((state == 2) && (i == j)){ state++; goto c0; } state = 0; c0: if(offset)wbf(ii); } if(offset){ wbfl(); offset = savoff; wbt(0); } copyf--; return(req); } cop /***/ if((woff & (~(BLK-1))) == (roff & (~(BLK-1))))roff = -1; woff = 0; } blisti(i) int i; { return((i-NEV*EVS)/(BLK)); } rbf(){ register i; if((i=rbf0(ip)) == 0){ if(!app)i = popi(); }else{ ip = incoff(ip); } return(i); } rbf0(p) int p; { register i; if((i = (p & (~(BLK-1)))) != roff){ roff = i; seek(ibf, roff<<2, 0); /***/ if(read(ibf, &rbuf, BLK<<2) == 0)return(0); /***/ } return(rbuf[p & (BLK-1)]); } incoff(p) int p; { register j; if(!((j = (++p)) & (BLK-1))){ if((j = bnd) && (!skip())){ *argpp++ = strp; quote = 0; if(((i = getch()) & CMASK) == '"')quote++; else ch = i; while(1){ i = getch(); if( nlflg || ((!quote) && ((i & CMASK) == ' ')))break; if(quote && ((i & CMASK) == '"') && (((i=getch()) & CMASK) != '"')){ ch = i; break; } *strp++ = i; if(strflg && (strp >= lim)){ prstrfl("Macro argument too long.\n"); copyf--; edone(004); } if((enda-4) <= strp)setbrk(DELTA); } *strp++ = 0; } nxf = savnxf; *nxo a0; case '-': neg = 1; goto a0; case '|': abs = 1 + neg; neg = 0; goto a0; } a1: while(((j = ((i = getch()) & CMASK) - '0') >= 0) && (j <= 9)){ field++; digits++; acc = 10*acc + j; } if((i & CMASK) == '.'){ field++; digits = 0; goto a1; } ch = i; if(!field)goto a2; switch((i = getch()) & CMASK){ case 'u': i = j = 1; break; case 'v': /*VSs - vert spacing*/ j = lss; i = 1; break; case 'm': /*Ems*/ j = EM; i = 1; break; case 'n': /*Ens*/ & CMASK) == '+')f = 1; else if(j == '-')f = -1; else ch = i; } i = atoi(); if(n && f)i = *n + f*i; i = quant(i,res); vflag = 0; res = dfactd = dfact = 1; if(nonumb)i = 0; return(i); } quant(n,m) int n, m; { register i, neg; neg = 0; if(n<0){ neg++; n = -n; } i = n/m; if((n - m*i) > (m/2))i =+ 1; i =* m; if(neg)i = -i; return(i); } =0)goto de1; if((offset=finds(i)) == 0)goto de1; if(ds)copys(); else req = copyb(); wbfl(); clrmn(oldmn); if(newmn)contab[newmn].rq = i | MMASK; if(apptr){ savoff = offset; offset = apptr; wbt(IMP); offset = savoff; } offset = dip->op; if(req != '.')control(req,1); de1: ds = app = 0; return; } findmn(i) int i; { register j; for(j=0;j= 0){ if(contab[i].rq & MMASK)free(contays() { register i; copyf++; if(skip())goto c0; if(((i=getch()) & CMASK) != '"')wbf(i); while(((i=getch()) & CMASK) != '\n')wbf(i); c0: wbt(0); copyf--; } alloc() { register i; int j; for(i=0;i 0) && (i <= 9) && (i <= *frame))ap = *(i + frame + STKSIZE -1); } caseda(){ app++; casedi(); } casedi(){ register i, j; lgf++; if(skip() || ((i=getrq()) == 0)){ if(dip->op > 0)wbt(0); if(dilev > 0){ v.dn = dip->dnl; v.dl = dip->maxl; dip = &d[--dilev]; offset = dip->op; } goto rtn; } if(++dilev == NDI){ --dilev; prstr("Cannot divert.\n"); edone(02); } if(dip->op)wbt(0); diflg++; dip = &d[dilev]; dip->op = finds(i); dip->curd = i; clrmn(oldmn); for(j=1; j<=10; j++)dip[j] = 0; /*not op and curd*/ rtn: app = 0; diflg = 0; } casedt(){ lgf++; dip->dimac = dip->ditrap = dip->ditf = 0; skip(); dip->ditrap = vnumb(0); if(nonumb)return; skip(); dip->dimac = getrq(); } casetl(){ register i; int w1, w2, w3, begin, delim; extern width(), pchar(); dip->nls = 0; skip(); if(dip->op)wbfl(); if((offset = begin = alloc()) == 0)return; if((delim = g0 + '0'; *p++ = '\n'; *p = 0; } rn; } if(!tflg && !print){ if(j == '\n')dip->alss = dip->blss = 0; return; } if(j == FILLER)return; #ifndef NROFF if(ascii){ if(i & MOT){ oput(' '); return; } if(j < 0177){ oput(i); return; } switch(j){ case 0200: case 0210: oput('-'); break; case 0211: oputs("fi"); break; case 0212: oputs("fl"); break; case 0213: oputs("ff"); break; case 0214: oputs("ffi"); break; case 0215: oputs("ffl"); break; default: STKSIZE; ip = 0; done(x); } #ifndef NROFF report(){ register i; struct {int use; char uid;} a; if((ptid != 1) && paper && ((i=open("/usr/adm/tr.acct",1)) >0)){ seek(i,0,2); a.use = paper; a.uid = getuid(); write(i,&a,3); close(i); } } #endif #ifdef NROFF casepi(){ register i; int id[2]; if(toolate || skip() || !getname() || (pipe(id) == -1) || ((i=fork()) == -1)){ prstr("Pipe not created.\n"); return; } ptid = id[1]; if(i>0){ close(id[0]); toolate++; pipeflg++; retur00,0200,0000,0000, 0200,0000,0120,0002,0220,0010,0000,0160,0006,0000,0140,0000,0320, 0020,0000,0020,0000,0020,0000,0000,0020,0000,0000,0020,0000,0000, 0043,0163,0065,0044,0022,0043,0104,0042,0061,0146,0061,0000,0007, 0100,0000,0140,0000,0040,0000,0000,0100,0000,0000,0120,0000,0000, 0140,0000,0040,0011,0060,0004,0001,0120,0003,0000,0140,0000,0040, 0200,0000,0100,0000,0140,0000,0000,0140,0000,0000,0140,0000,0240, 0200,0000,0140,0000,0160,0000,0000,0220,0000,0000,0140,0000,0240, 0200,0000,0140,0000,0160200,0000,0020,0000,0140,0000,0000,0120,0000,0000,0120,0000,0040, 0120,0000,0040,0000,0060,0000,0000,0060,0000,0000,0160,0000,0040, 0120,0000,0040,0000,0120,0000,0000,0040,0000,0000,0160,0000,0040, 0120,0000,0020,0000,0140,0000,0000,0120,0000,0000,0140,0000,0040, 0051,0126,0150,0140,0060,0210,0146,0006,0006,0165,0003,0017,0244, 0120,0000,0040,0000,0160,0000,0000,0140,0000,0000,0060,0000,0140, 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, 0140,0000,0140,0000,0060,0000,0000,0100,000etch()) & MOT){ ch = delim; delim = '\''; }else delim =& CMASK; if(!nlflg) while(((i = getch()) & CMASK) != '\n'){ if((i & CMASK) == delim)i = 004; wbf(i); } wbf(004);wbf(004);wbt(0); w1 = hseg(width,begin); w2 = hseg(width,0); w3 = hseg(width,0); offset = dip->op; #ifdef NROFF if(!offset)horiz(po); #endif hseg(pchar,begin); if(w2 || w3)horiz((lt - w2)/2-w1); hseg(pchar,0); if(w3){ horiz((lt - w2)/2 - w3); hseg(pchar,0); } newline(0); if(*dip){if(dip->dnl > dip->hnl)dip->hn#include "tdef.h" #include "t.h" /* troff2.c output, cleanup */ extern char obuf[OBUFSZ]; extern char *obufp; extern int dilev; extern int *dip; extern int eschar; extern int tlss; extern int tflg; extern int ascii; extern int print; extern char trtab[]; extern int waitf; extern char ptname[]; extern int ptid; extern int offset; extern int em; extern int ds; extern int ip; extern int mflg; extern int woff; extern int nflush; extern int lgf; extern int app; extern int nfo; extern int donef; extern int *fr for(k=chtab; *++k != j; k++) if(*k == 0)return; oput('\\'); oput('('); oput(*--k & BMASK); oput(*k >> BYTE); } }else #endif ptout(i); } oput(i) char i; { *obufp++ = i; if(obufp == (obuf + OBUFSZ + ascii - 1))flusho(); } oputs(i) char *i; { while(*i != 0)oput(*i++); } flusho(){ if(!ascii)*obufp++ = 0; if(!ptid){ while((ptid=open(ptname,1)) < 0){ if(++waitf <=2)prstr("Waiting for Typesetter.\n"); sleep(15); } } toolate =+ write(ptid, obuf, obufp-obuf); obufp = ob ' - 3 " ( . 4 # /0,0000,0000,0220,0000,0000,0060,0000,0240, 0021,0043,0041,0121,0040,0023,0042,0003,0142,0042,0061,0001,0022, 0120,0000,0140,0010,0140,0010,0000,0140,0002,0000,0120,0000,0120, 0000,0000,0000,0000,0360,0000,0000,0000,0000,0000,0160,0000,0000, 0100,0000,0040,0005,0120,0000,0000,0100,0000,0000,0060,0000,0140, 0140,0040,0100,0001,0240,0041,0000,0242,0000,0002,0140,0000,0100, 0240,0000,0120,0002,0200,0000,0000,0320,0007,0000,0240,0000,0340, 0101,0021,0041,0020,0040,0005,0042,0121,0002,0021,0201,0000,0020, 0,0000,0140,0000,0020, 0120,0000,0020,0000,0060,0000,0000,0060,0000,0000,0060,0000,0040, 0140,0000,0020,0000,0100,0000,0000,0140,0000,0000,0140,0000,0020, 0070,0125,0051,0162,0120,0105,0126,0104,0006,0044,0000,0017,0052, 0140,0000,0020,0000,0140,0000,0000,0060,0000,0000,0060,0000,0040, 0020,0000,0000,0000,0020,0000,0000,0000,0000,0000,0000,0000,0060, 0140,0000,0160,0000,0200,0000,0000,0140,0000,0000,0000,0000,0240, 0065,0042,0060,0200,0000,0210,0222,0146,0006,0204,0220,0012,0003, 0240,0000,0020,0000l = dip->dnl;} else{if(v.nl > dip->hnl)dip->hnl = v.nl;} free(begin); } casepc(){ pagech = chget(IMP); } hseg(f,p) int (*f)(); int *p; { register acc, i; static int *q; acc = 0; if(p)q = p; while(1){ i = rbf0(q); q = incoff(q); if(!i || (i == 004))return(acc); if((i & CMASK) == pagech){ nrbits = i & ~CMASK; nform = fmt[findr('%')]; acc =+ fnumb(v.pn,f); }else acc =+ (*f)(i); } } casepm(){ register i, k; register char *p; int j, xx, cnt, kk, tot; char pmline[10]; kk = cnt =ame; extern int *stk; extern int *pendw; extern int nofeed; extern int trap; extern int ittys[3]; /***/ extern int quiet; extern int pendnf; extern int ndone; extern int lead; extern int ralss; extern int paper; extern int gflag; extern int *nxf; extern char *unlkp; extern char *nextf[]; extern int pipeflg; extern int ejf; extern int xxx; int toolate; int error; pchar(c) int c; { register i, j; if((i=c) & MOT){pchar1(i); return;} switch(j = i & CMASK){ case 0: case IMP: case RIGHT: case LEFT: uf; } done(x) int x;{ register i; error =| x; app = ds = lgf = 0; if(i=em){ donef = -1; em = 0; if(control(i,0))reset(); } if(!nfo)done3(0); mflg = 0; dip = &d[0]; if(woff)wbt(0); if(pendw)getword(1); pendnf = 0; if(donef == 1)done1(0); donef = 1; ip = 0; frame = stk; nxf = frame + STKSIZE; if(!ejf)tbreak(); nflush++; eject(0); reset(); } done1(x) int x; { error =| x; if(v.nl){ trap = 0; eject(0); reset(); } if(nofeed){ ptlead(); flusho(); done3(0); }else{ if(!gn; } close(0); dup(id[0]); close(id[1]); execl(nextf,nextf,0); prstr("Cannot exec: "); prstr(nextf); prstr("\n"); exit(-4); } #endif 0160,0000,0100,0000,0140,0000,0000,0160,0006,0000,0220,0000,0140, 0140,0000,0020,0001,0020,0000,0000,0100,0001,0000,0300,0000,0000, 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, 0106,0041,0040,0147,0040,0000,0063,0041,0001,0102,0160,0002,0002, 0300,0000,0040,0017,0140,0017,0000,0240,0000,0000,0140,0000,0120 }; char bxxh[] { 0005,0150,0153,0062,0062,0246,0152,0127,0146,0203,0310,0017,0206, 0100,0000,0120,0000,0140,0000,0000,0100,0000,0000,0120,0000,0060, 0100,0000,0040,0000,0060,0120,0000,0000,0200,0000,0000,0200,0000,0240 }; char xhx[] { 0032,0146,0042,0107,0076,0102,0042,0146,0202,0050,0006,0000,0051, 0036,0377,0057,0013,0057,0366,0377,0057,0001,0377,0057,0000,0040, 0037,0377,0020,0000,0100,0022,0377,0057,0362,0116,0100,0000,0017, 0057,0377,0057,0031,0137,0363,0377,0037,0362,0270,0077,0000,0117, 0074,0142,0012,0236,0076,0125,0063,0165,0341,0046,0047,0000,0024, 0020,0017,0075,0377,0040,0001,0377,0017,0001,0204,0020,0000,0040, 0057,0017,0057,0340,0140,0362,0314,0117,0003, 0; tot = !skip(); for(i = 0; i> BYTE) & 0177)) *(p-1) = ' '; /***/ *p++ = xx & 0177; /***/ *p++ = ' '; kvt(k,p); prstr(pmline); } } if(tot || (cnt > 1)){ kvt(kk,pmline); prstr(pmline); } } kvt(k,p) int k; char *p; { if(k>=100)*p++ = k/100 + '0'; if(k>=10)*p++ = (k%100)/10 + '0'; *p++ = k%1 return; case HX: j = (tlss>>9) | ((i&~0777)>>3); if(i & 040000){ j =& ~(040000>>3); if(j > dip->blss)dip->blss = j; }else{ if(j > dip->alss)dip->alss = j; ralss = dip->alss; } tlss = 0; return; case LX: tlss = i; return; case PRESC: if(!dip->op)j = eschar; default: i = (trtab[j] & BMASK) | (i & ~CMASK); } pchar1(i); } pchar1(c) int c; { register i, j, *k; extern int chtab[]; j = (i = c) & CMASK; if(dip->op){ wbf(i); dip->op = offset; retuflag)lead =+ TRAILER; done2(0); } } done2(x) int x; { register i; ptlead(); #ifndef NROFF if(!ascii){ oput(T_INIT); oput(T_STOP); if(!gflag)for(i=8; i>0; i--)oput(T_PAD); } #endif flusho(); done3(x); } done3(x) int x;{ error =| x; signal(SIGINT, 1); signal(SIGKILL,1); unlink(unlkp); #ifdef NROFF twdone(); #endif if(quiet){ ittys[2] =| ECHO; /***/ stty(0,ittys); /***/ } if(ascii)mesg(1); #ifndef NROFF report(); #endif exit(error); } edone(x) int x;{ frame = stk; nxf = frame +/* hyphenation digram tables*/ char bxh[] { 0060,0000,0040,0000,0040,0000,0000,0040,0000,0000,0040,0000,0040 }; char hxx[] { 0006,0042,0041,0123,0021,0024,0063,0042,0002,0043,0021,0001,0022, 0140,0000,0200,0003,0260,0006,0000,0160,0007,0000,0140,0000,0320, 0220,0000,0160,0005,0240,0010,0000,0100,0006,0000,0200,0000,0320, 0240,0000,0120,0003,0140,0000,0000,0240,0010,0000,0220,0000,0160, 0042,0023,0041,0040,0040,0022,0043,0041,0030,0064,0021,0000,0041, 0100,0000,0140,0000,0220,0006,0000,0140,0003,00,0000,0000,0060,0000,0000,0220,0000,0040, 0100,0000,0120,0000,0200,0000,0000,0100,0000,0000,0140,0000,0060, 0043,0142,0046,0140,0062,0147,0210,0131,0046,0106,0246,0017,0111, 0060,0000,0020,0000,0060,0000,0000,0040,0000,0000,0100,0000,0000, 0060,0000,0040,0000,0040,0000,0000,0040,0000,0000,0100,0000,0040, 0100,0000,0100,0000,0100,0000,0000,0040,0000,0000,0100,0000,0140, 0066,0045,0145,0140,0000,0070,0377,0030,0130,0103,0003,0017,0006, 0040,0000,0040,0000,0020,0000,0000,0040,0000,0000,0100,0000,0000, 5 $ * 0 6 % + 1 8 > D J 9 ?0302,0100,0000,0057, 0057,0357,0077,0017,0100,0366,0314,0057,0342,0346,0037,0000,0060, 0252,0145,0072,0157,0377,0165,0063,0066,0164,0050,0363,0000,0362, 0000,0000,0020,0000,0020,0000,0000,0017,0000,0000,0020,0000,0000, 0117,0017,0237,0377,0200,0354,0125,0110,0004,0257,0000,0000,0300, 0057,0367,0054,0357,0157,0216,0314,0114,0217,0353,0053,0000,0057, 0077,0213,0077,0077,0177,0317,0377,0114,0377,0352,0077,0000,0076, 0077,0213,0077,0077,0157,0177,0377,0054,0377,0352,0117,0000,0075, 0125,0230,0065,0216,0 0120,0026,0042,0020,0140,0161,0042,0143,0000,0022,0162,0017,0040, 0121,0042,0060,0020,0140,0200,0000,0123,0000,0021,0220,0017,0041, 0121,0042,0060,0120,0140,0200,0000,0123,0000,0021,0160,0017,0041, 0051,0126,0150,0141,0060,0210,0146,0066,0026,0165,0026,0017,0247, 0120,0000,0040,0003,0160,0000,0000,0140,0000,0021,0100,0017,0140, 0000,0000,0000,0000,0200,0000,0000,0000,0000,0000,0000,0017,0000, 0141,0023,0122,0040,0160,0143,0042,0142,0000,0047,0143,0017,0020, 0120,0000,0040,0006,0140,0060,0000,0141,00 int ch0; extern int cwidth; extern int ip; extern int nlflg; extern int *nxf; extern int *ap; extern int *frame; extern int *stk; extern int donef; extern int nflush; extern int nchar; extern int rchar; extern int nfo; extern int ifile; extern int fc; extern int padc; extern int tabc; extern int dotc; extern int raw; extern int tabtab[NTAB]; extern int iline; extern char nextf[]; extern int nfi; #ifdef NROFF extern char termtab[]; extern int tti; #endif extern int ifl[NSO]; extern int offl[NSO]; extern intum(&argv[0][3]); continue; case 'm': p = &nextf[nfi]; q = &argv[0][2]; while((*p++ = *q++) != 0); mflg++; continue; case 'o': getpn(&argv[0][2]); continue; #ifdef NROFF case 'e': eqflg++; continue; case 'T': p = &termtab[tti]; q = &argv[0][2]; if(!((*q) & 0177))continue; while((*p++ = *q++) != 0); dotT++; continue; #endif #ifndef NROFF case 'a': ascii = 1; nofeed++; case 't': ptid = 1; continue; case 'w': waitf = 1; continue; flushi(); goto loop; } lt: ch = i; text(); goto loop; } catch(){ /* prstr("Interrupt\n"); */ done3(01); } fpecatch(){ prstrfl("Floating Exception.\n"); signal(SIGFPE,fpecatch); } kcatch(){ signal(SIGKILL,1); done3(01); } init1(a) char a; { register char *p; register i; extern int block; if((suffid=open(suftab,0)) < 0){ prstr("Cannot open suftab.\n"); exit(-1); } seek(suffid,32,0); /***/ read(suffid,sufind,4*26); /***/ p = mktemp("/tmp/taXXXXX"); if(a == 'a')p = &p[5]; if((i =eturn(0); if(contab[j].rq & MMASK){ *nxf = 0; if(b)collect(); flushi(); return(pushi(contab[j].f)); }else{ if(!b)return(0); return((*contab[j].f)(0)); } } getrq(){ register i,j; if(((i=getach()) == 0) || ((j=getach()) == 0))goto rtn; i = (i< 0)goto options; } start: argp = argv; rargc = argc; init2(); setexit(); loop: copyf = lgf = nb = nflush = nlflg = 0; cframe creat(p, 0600)) < 0){ prstr("Cannot create temp file.\n"); exit(-1); } close(i); ibf = open(p, 2); for(i=256; --i;)trtab[i]=i; trtab[UNPAD] = ' '; mchbits(); for(i=NEV; i--;)write(ibf, &block, EVS*4); /***/ if(a != 'a')unlkp = p; } init2() { register i,j; ttyod = 2; /***/ if (ttyn(0) != 'x') /***/ gtty(0, ittys); /***/ else /***/ iflg = 1; /***/ if ((i=ttyn(1)) != 'x') { /***/ ttyx[8]=i; /***/ gtty(1, ttys); /***/ ttysave = ttys[2]; /***/ } if(ascii)mesg(0); if((!ptid) && (!waitf)){k == FLSS){ copyf++; raw++; i = getch0(); if(!fi)flss = i; copyf--; raw--; goto g0; } if(k == RPT){ setrpt(); goto g0; } if(!copyf){ if((k == 'f') && lg && !lgf){ i = getlg(i); goto g2; } if((k == fc) || (k == tabch) || (k == ldrch)){ if((i=setfield(k)) == 0)goto g0; else goto g2; } if(k == 010){ i = makem(-width(' ' | chbits)); goto g2; } } goto g2; } k = (j = getch0()) & CMASK; if(j & MOT){ i = j; goto g2; } /* if(k == tdelim), 0037,0232,0157,0361,0040,0003,0125,0010,0001,0256,0000,0000,0340, 0377,0377,0377,0377,0377,0377,0377,0377,0377,0377,0377,0017,0277, 0253,0315,0257,0216,0377,0206,0146,0306,0371,0126,0232,0000,0004, 0057,0012,0100,0360,0160,0360,0000,0040,0000,0017,0157,0000,0176 }; char xxh[] { 0045,0150,0154,0162,0042,0246,0210,0147,0152,0103,0230,0017,0206, 0100,0000,0040,0000,0140,0000,0000,0100,0000,0021,0120,0017,0060, 0100,0000,0040,0002,0140,0320,0000,0060,0000,0001,0220,0017,0040, 0100,0001,0120,0001,024#include "tdef.h" #include "t.h" #include "tw.h" /* troff1.c consume options, initialization, main loop, input routines, escape function calling */ extern int stdi; extern int waitf; extern int nofeed; extern int quiet; extern int ptid; extern int ascii; extern int npn; extern int xflg; extern int stop; extern char ibuf[IBUFSZ]; extern char xbuf[IBUFSZ]; extern char *ibufp; extern char *xbufp; extern char *eibuf; extern char *xeibuf; extern int cbuf[NC]; extern int *cp; extern int *vlist; extern int nx; einal value of ttys[2] ***/ extern int tdelim; extern int dotT; extern int tabch, ldrch; extern int eqflg; extern int xxx; char ttyx[] "/dev/ttyx"; /*** name of output tty ***/ extern struct contab { int rq; int (*f)(); }contab[NM]; int ms[] {31,28,31,30,31,30,31,31,30,31,30,31}; main(argc,argv) int argc; char **argv; { char *p, *q; int *cframe; register i, j; extern catch(), fpecatch(), kcatch(); signal(SIGHUP,catch); if(signal(SIGINT,catch) & 01){ signal(SIGHUP,1); signal(SIGINT,1); signal( E K : @ F L ; A M < B H N = C I O P V \ b Q W ] c R X ^ if((ptid = open(ptname,1)) < 0){ prstr("Typesetter busy.\n"); done3(-2); } } ptinit(); olinep = oline; ibufp = eibuf = ibuf; v.hp = ioff = init = 0; v.nl = -1; cvtime(); frame = stk = setbrk(DELTA); nxf = frame + STKSIZE; nx = mflg; } cvtime(){ int tt[2]; register i; time(tt); /*** sub1(tt,3600*ZONE); /*5hrs for EST*/ v.dy = ldiv(tt[0],tt[1],60*60*8)/3 + 1; v.dw = (v.dy + 3)%7 + 1; for(v.yr=70;; v.yr++){ if((v.yr)%4)ms[1]=28;else ms[1]=29; for(i=0;i<12;){ if(v.dy<=ms[i]){{ i = TDELIM; tdelim = IMP; goto g2; } */ switch(k){ case '\n': /*concealed newline*/ goto g0; case 'n': /*number register*/ setn(); goto g0; case '*': /*string indicator*/ setstr(); goto g0; case '$': /*argument indicator*/ seta(); goto g0; case '{': /*LEFT*/ i = LEFT; goto gx; case '}': /*RIGHT*/ i = RIGHT; goto gx; case '"': /*comment*/ while(((i=getch0()) & CMASK ) != '\n'); goto g2; case ESC: /*double backslash*/ i = eschar; goto gx;1,0000,0000,0100,0000,0020,0140,0017,0060, 0023,0162,0046,0142,0022,0207,0210,0131,0052,0106,0250,0017,0110, 0060,0000,0042,0000,0160,0000,0000,0040,0000,0212,0100,0017,0000, 0140,0000,0040,0002,0140,0000,0000,0120,0000,0040,0120,0017,0040, 0100,0000,0100,0000,0140,0001,0021,0140,0000,0046,0100,0017,0140, 0066,0045,0025,0201,0020,0130,0146,0030,0130,0103,0025,0017,0006, 0100,0000,0040,0000,0020,0000,0000,0040,0000,0000,0200,0017,0000, 0200,0000,0020,0001,0140,0000,0000,0140,0000,0000,0120,0017,0040, xtern int mflg; extern int ch; extern int pto; extern int pfrom; extern int cps; extern int chbits; extern int suffid; extern int sufind[26]; extern char suftab[]; extern int ibf; extern int ttyod; extern int ttys[3]; /*** modes for output tty ***/ extern int ittys[3]; /*** modes for input tty ***/ extern int iflg; /*** set to 0 if input is from tty ***/ extern int ioff; extern int init; extern int rargc; extern char **argp; extern char trtab[256]; extern int lgf; extern int copyf; extern int eschar; externSIGQUIT,1); } signal(SIGFPE,fpecatch); signal(SIGPIPE,catch); signal(SIGKILL,kcatch); init1(argv[0][0]); options: while(--argc > 0 && (++argv)[0][0]=='-') switch(argv[0][1]){ case 0: goto start; case 'i': stdi++; continue; case 'q': quiet++; continue; case 'n': npn = cnum(&argv[0][2]); continue; case 'p': xflg = 0; cps = cnum(&argv[0][2]); continue; case 's': if(!(stop = cnum(&argv[0][2])))stop++; continue; case 'r': vlist[findr(argv[0][2])] = cn= frame; i = getch(); if((frame != cframe) && ejf && (frame <= ejl)){ nflush++; trap = 0; ch = i; eject(0); goto loop; } if(pendt)goto lt; if(lit && (frame <= litlev)){ lit--; goto lt; } if((j = (i & CMASK)) == XPAR){ copyf++; tflg++; for(;(i & CMASK) != '\n';)pchar(i = getch()); tflg = 0; copyf--; goto loop; } if((j == cc) || (j == c2)){ if(j == c2)nb++; copyf++; while(((j=((i=getch()) & CMASK)) == ' ') || (j == '\t')); ch = i; copyf--; control(getrq(),1); v.mo = i+1; return; } v.dy =- ms[i++]; } } } cnum(a) char *a; { register i; ibufp = a; eibuf = -1; i = atoi(); ch = 0; return(i); } mesg(f) int f; { static int mode; if(!f){ stat(ttyx,cbuf); mode = cbuf[2]; chmod(ttyx,mode & ~022); }else{ chmod(ttyx,mode); } } prstrfl(s) char *s; { flusho(); prstr(s); } prstr(s) char *s; { register i; for(i=0;*s;i++)s++; write(ttyod,s-i,i); } control(a,b) int a,b; { register i,j; i = a; if((i == 0) || ((j = findmn(i)) == -1))r case 'e': /*printable version of current eschar*/ i = PRESC; goto gx; case ' ': /*unpaddable space*/ i = UNPAD; goto gx; case '|': /*narrow space*/ i = NARSP; goto gx; case '^': /*half of narrow space*/ i = HNSP; goto gx; case '\'': /*\(aa*/ i = 0222; goto gx; case '`': /*\(ga*/ i = 0223; goto gx; case '_': /*\(ul*/ i = 0224; goto gx; case '-': /*current font minus*/ i = 0210; goto gx; case '&': /*filler*/ i = FILLER; goto gx; case 'c': /*to be continued*/ i = CONT; goto gx; case ':': /*lem's char*/ i = COLON; goto gx; case '!': /*transparent indicator*/ i = XPAR; goto gx; case 't': /*tab*/ i = '\t'; goto g2; case 'a': /*leader (SOH)*/ i = LEADER; goto g2; case '%': /*ohc*/ i = OHC; goto g2; case '.': /*.*/ i = '.'; gx: i = (j & ~CMASK) | i; goto g2; } g1: if(!copyf) switch(k){ case 'p': /*spread*/ spread++; goto g0; case '(': /*special char name*/ if((i=; } }else if(ap){ if((i = *ap++) == 0){ ap = 0; goto again; } }else if(ip){ if(ip == -1)i = rdtty(); else i = rbf(); }else{ if(donef)done(0); if(nx || ((ibufp >= eibuf) && (ibufp != -1))){ if(nfo)goto g1; g0: if(nextfile() && (ibufp < eibuf))goto g2; g1: nx = 0; if((j=read(ifile,ibuf,IBUFSZ)) <= 0)goto g0; ibufp = ibuf; eibuf = ibuf + j; } g2: i = *ibufp++ & 0177; ioff++; if(i >= 040)goto g4; else i = ifilt[i]; } if(raw)return(i); if((j = i & CMASK) =skip(); getname(); nx++; nextfile(); nlflg++; ip = ap = nchar = pendt = 0; frame = stk; nxf = frame + STKSIZE; } getname(){ register int i, j, k; lgf++; for(k=0; k < (NS-1); k++){ if(((j=(i=getch()) & CMASK) <= ' ') || (j > 0176))break; nextf[k] = j; } nextf[k] = 0; ch = i; lgf--; return(nextf[0]); } caseso(){ register i, *p, *q; lgf++; if(skip() || !getname() || ((i=open(nextf,0)) <0) || (ifi >= NSO))return; flushi(); ifl[ifi] = ifile; ifile = i; offl[ifi] = ioff; ioff = 0* suftab - suffix table suftab equ * dc sufa+32 dc 0 dc sufc+32 dc sufd+32 dc sufe+32 dc suff+32 dc sufg+32 dc sufh+32 dc sufi+32 dc 0 dc sufk+32 dc sufl+32 dc sufm+32 dc sufn+32 dc sufo+32 dc sufp+32 dc 0 dc sufr+32 dc sufs+32 dc suft+32 dc 0 dc 0 dc 0 dc 0 dc sufy+32 dc 0 sufa equ * db 2,x'80'+c't' /-TA db 2,x'80'+c's' /-SA db 3,x'80'+c't',c'r' /-TRA db 3,x'80'+c'd',c'r' /-DRA db 3,x'80'+c'b',c'r' /-BRA db 2,x'80'+c'p' /-PA db 2,x'80'+c'n' /-NA db 2,x'80'+c'm' /-MA db b 4,x'80'+c'w',c'o',c'o' /-WOOD db 4,x'80'+c'h',c'o',c'o' /-HOOD db 4,x'80'+c'm',c'o',c'n' /-MOND db 4,x'80'+c't',c'e',c'n' /-TEND db 5,x'80'+c's',c't',c'a',c'n' /-STAND db 4,x'80'+c'l',c'a',c'n' /-LAND db 4,x'80'+c'h',c'a',c'n' /-HAND db 4,x'80'+c'h',c'o',c'l' /-HOLD db 4,x'80'+c'f',c'o',c'l' /-FOLD db 5,x'80'+c'f',c'i',c'e',c'l' /-FIELD db 3,x'80'+c'v',c'i' /-VID db 3,x'80'+c'c',c'i' /-CID db 4,x'80'+c's',c'a',c'i' /-SAID db 4,x'80'+c'm',c'a',c'i' /-MAID db 4,c't',x'80'+c't',c'e' /T-TED db S Y _ e T Z ` f [ a g h n t z i o u { j p v | k q w } l r x ~ m s y  setch()) == 0)goto g0; break; case 's': /*size indicator*/ setps(); goto g0; case 'f': /*font indicator*/ setfont(0); goto g0; case 'w': /*width function*/ setwd(); goto g0; case 'v': /*vert mot*/ if(i = vmot())break; goto g0; case 'h': /*horiz mot*/ if(i = hmot())break; goto g0; case 'z': /*zero with char*/ i = setz(); break; case 'l': /*hor line*/ setline(); goto g0; case 'L': /*vert line*/ setvline(); goto g0; = IMP)goto again; if((i == 0) && !init)goto again; g4: if((copyf == 0) && ((i & ~BMASK) == 0) && ((i & CMASK) < 0370)) i =| chbits; if((i & CMASK) == eschar)i = (i & ~CMASK) | ESC; return(i); } nextfile(){ register char *p; n0: if(ifile)close(ifile); if(nx){ p = nextf; if(*p != 0)goto n1; } if(ifi > 0){ if(popf())goto n0; /*popf error*/ return(1); /*popf ok*/ } if(rargc-- <= 0)goto n2; p = (argp++)[0]; n1: if((p[0] == '-') && (p[1] == 0)){ ifile = 0; }else if((ifile=open(p,0)) < 0; nx++; nflush++; if(!ifl[ifi++]){ p = ibuf; q = xbuf; xbufp = ibufp; xeibuf = eibuf; while(p < eibuf)*q++ = *p++; } } getpn(a) char *a; { register i, neg; LONG0 atoi1(); neg = 0; ibufp = a; eibuf = -1; noscale++; while((i = getch() & CMASK) != 0)switch(i){ case '+': case ',': continue; case '-': neg = MOT; goto d2; default: ch = i; d2: i = atoi1(); if(nonumb)goto fini; else{ *pnp++ = i | neg; neg = 0; if(pnp >= &pnlist[NPN-2]){ prstr("To3,x'80'+c'p',c'l' /-PLA db 2,x'80'+c'l' /-LA db 2,x'80'+c'k' /-KA db 3,x'80'+c't',c'h' /-THA db 3,x'80'+c's',c'h' /-SHA db 2,x'80'+c'g' /-GA db 2,x'80'+c'd' /-DA db 2,x'80'+c'c' /-CA db 2,x'80'+c'b' /-BA db 0 sufc equ * db 4,c'e',c't',x'80'+c'i' /ET-IC db 7,c'a',c'l',x'80'+c'i',c's',x'80'+c't',c'i' /AL-IS-TIC db 4,c's',x'80'+c't',c'i' /S-TIC db 4,c'p',x'80'+c't',c'i' /P-TIC db 5,x'80'+c'l',c'y',c't',x'80'+c'i' /-LYT-IC db 4,c'o',c't',x'80'+c'i' /OT-IC db 5,c'a',c'n',x'80'+c't',c'i' /AN-TIC 3,c't',x'80'+c'e' /T-ED db 4,x'80'+c'd',c'r',c'e' /-DRED db 4,x'80'+c'c',c'r',c'e' /-CRED db 4,x'80'+c'b',c'r',c'e' /-BRED db 5,c'v',x'80'+c'e',c'l',c'e' /V-ELED db x'40'+4,c'a',c'l',x'80'+c'e' /AL/ED db x'60'+3,x'80'+c'e',c'e' //EED db x'20'+5,c'e',c'd',x'80'+c'd',c'e' /ED-DED db 4,c'd',x'80'+c'd',c'e' /D-DED db x'20'+4,c'e',c'd',x'80'+c'e' /ED-ED db 3,c'd',x'80'+c'e' /D-ED db 5,x'80'+c'd',c'u',c'c',c'e' /-DUCED db x'c0'+2,c'e' /E/D db 5,x'80'+c's',c't',c'e',c'a' /-STEAD db 4,x'80'+c'h',c'e',x'80'+c'u',c'r' /-FIG-URE db x'20'+3,x'80'+c't',c'r' /-TRE db 5,x'80'+c's',c't',c'o',c'r' /-STORE db 4,x'80'+c'f',c'o',c'r' /-FORE db 5,x'80'+c'w',c'h',c'e',c'r' /-WHERE db 6,x'80'+c's',c'p',c'h',c'e',c'r' /-SPHERE db 3,x'80'+c'd',c'r' /-DRE db 3,x'80'+c'c',c'r' /-CRE db 3,x'80'+c'b',c'r' /-BRE db 5,x'80'+c's',c'c',c'o',c'p' /-SCOPE db 4,c'y',x'80'+c'o',c'n' /Y-ONE db 5,x'80'+c's',c't',c'o',c'n' /-STONE db 5,x'80'+c'p',c'h',c'o',c'n' /-PHONE db 4,x'80'+c'g',c'o',c'n' /-GONE db 4,c'e',x'80'+c'o case 'b': /*bracket*/ setbra(); goto g0; case 'o': /*overstrike*/ setov(); goto g0; case 'k': /*mark hor place*/ if((i=findr(getsn())) == -1)goto g0; vlist[i] = v.hp; goto g0; case 'j': /*mark output hor place*/ if(!(i=getach()))goto g0; i = (i<= eibuf)return(1); return(0); } flushi(){ if(nflush)return; ch = 0; if((ch0 & CMASK) == '\n')nlflg++; ch0 = 0; copyf++; while(!nlflg){ if(donef && (frame == stk))break; getch(); } copyf--; v.hp = 0; } getach(){ register i; lgf++; if(((i = getch()) & MOT) || ((i&CMASK) == ' ') || ((i&CMASK) == '\n')|| (i & 0200)){ ch = i; i = 0; } lgf--; return(i & 0177); } casenx(){ lgf++; This directory contains source for both nroff and troff. Use the preprocessor symbol NROFF to determine which one is being compiled. (See run) Suftab.s is assembled to make /usr/lib/nsuftab. Needless to say, troff has never been tested. I-AC db 0 sufd equ * db 4,x'80'+c'w',c'o',c'r' /-WORD db 4,x'80'+c'l',c'o',c'r' /-LORD db 4,x'80'+c'f',c'o',c'r' /-FORD db 4,x'80'+c'y',c'a',c'r' /-YARD db 4,x'80'+c'w',c'a',c'r' /-WARD db 5,x'80'+c'g',c'u',c'a',c'r' /-GUARD db 4,x'80'+c't',c'a',c'r' /-TARD db 5,x'80'+c'b',c'o',c'a',c'r' /-BOARD db 4,x'80'+c'n',c'a',c'r' /-NARD db 5,x'80'+c'l',c'i',c'a',c'r' /-LIARD db 4,x'80'+c'i',c'a',c'r' /-IARD db 4,x'80'+c'g',c'a',c'r' /-GARD db 4,x'80'+c'b',c'a',c'r' /-BARD db 3,x'80'+c'r',c'o' /-ROD du',c'a',c't' / QUAT/E db 4,c'u',x'80'+c'a',c't' /U-ATE db 5,x'80'+c's',c't',c'a',c't' /-STATE db 4,x'80'+c't',c'a',c't' /-TATE db 6,x'80'+c't',c'o',c'r',x'80'+c'a',c't' /-TOR-ATE db 5,c'e',c'n',x'80'+c'a',c't' /EN-ATE db 4,x'80'+c'm',c'a',c't' /-MATE db 5,x'80'+c'h',c'o',c'u',c's' /-HOUSE db 5,x'80'+c'c',c'l',c'o',c's' /-CLOSE db 4,c'i',x'80'+c'o',c's' /I-OSE db 4,x'80'+c'w',c'i',c's' /-WISE db 5,c'a',c's',x'80'+c'u',c'r' /AS-URE db x'20'+4,x'80'+c's',c'u',c'r' /-SURE db 6,x'80'+c'f',c'i',c'g',c'l' /CK-LE db 3,x'80'+c'k',c'l' /-KLE db 3,x'80'+c'g',c'l' /-GLE db 3,x'80'+c'f',c'l' /-FLE db 3,x'80'+c'd',c'l' /-DLE db 3,x'80'+c'c',c'l' /-CLE db 5,x'80'+c'p',c'a',x'80'+c'b',c'l' /-PA-BLE db 5,c'f',c'a',x'80'+c'b',c'l' /FA-BLE db 5,x'80'+c'c',c'a',x'80'+c'b',c'l' /-CA-BLE db 6,x'80'+c's',c't',c'a',c'b',c'l' /-STABLE db 4,x'80'+c'a',c'b',c'l' /-ABLE db 3,x'80'+c'b',c'l' /-BLE db 4,x'80'+c'd',c'a',c'l' /-DALE db 4,x'80'+c'm',c'a',c'l' /-MALE db 4,x'80'+c's',c'a',c'l' /-SALE db 4,x'80'+c'l',c'i',c'k' /-LIKE db x'e0'+5,c'g',x'80'+c'u',c'a',c'g' /-G/UAGE db 5,x'80'+c'r',c'i',c'a',c'g' /-RIAGE db 5,c'e',c'r',x'80'+c'a',c'g' /ER-AGE db 4,c'm',x'80'+c'a',c'g' /M-AGE db 4,c'k',x'80'+c'a',c'g' /K-AGE db 4,c'd',x'80'+c'a',c'g' /D-AGE db 4,x'80'+c'w',c'i',c'f' /-WIFE db 5,x'80'+c'k',c'n',c'i',c'f' /-KNYFE db 3,x'80'+c's',c'e' /-SEE db 4,x'80'+c'f',c'r',c'e' /-FREE db x'e0'+2,c'e' /EE db 4,x'80'+c'w',c'i',c'd' /-WIDE db 4,x'80'+c't',c'i',c'd' /-TIDE db 4,x'80'+c's',c'i',c'd' /-SIDE db 6,0'+c'g',c'l',c'i',c'n' /-GLING db 5,x'80'+c'f',c'l',c'i',c'n' /-FLING db 5,x'80'+c'd',c'l',c'i',c'n' /-DLING db 5,x'80'+c'c',c'l',c'i',c'n' /-CLING db 5,x'80'+c'b',c'l',c'i',c'n' /-BLING db 6,c'y',x'80'+c't',c'h',c'i',c'n' /Y-THING db 7,c'e',c'e',c't',c'h',x'80'+c'i',c'n' /EETH-ING db 6,c'e',x'80'+c't',c'h',c'i',c'n' /E-THING db 5,c'g',x'80'+c'g',c'i',c'n' /G-GING db 5,c'd',x'80'+c'd',c'i',c'n' /D-DING db 5,c'b',x'80'+c'b',c'i',c'n' /B-BING db 3,x'80'+c'i',c'n' /-ING db 0 sufh equ * db 5,x'80'+b 3,c'u',x'80'+c'e' /U-EL db 3,c'k',x'80'+c'e' /K-EL db 4,c't',c'h',x'80'+c'e' /TH-EL db 5,c't',c'c',c'h',x'80'+c'e' /TCH-EL db 3,c'a',x'80'+c'e' /A-EL db x'60'+4,x'80'+c'q',c'u',c'a' //QUAL db x'20'+3,c'u',x'80'+c'a' /U-AL db 3,x'80'+c't',c'a' /-TAL db 4,c'u',c'r',x'80'+c'a' /UR-AL db x'20'+5,c'g',x'80'+c'o',x'80'+c'n',c'a' /G-O-NAL db 4,c'o',c'n',x'80'+c'a' /ON-AL db 3,x'80'+c'n',c'a' /-NAL db 4,x'80'+c't',c'i',c'a' /-TIAL db 4,x'80'+c's',c'i',c'a' /-SIAL db x'20'+5,x'80'+c't',c'r',c'i',x'80'+c'i',x'80'+c'a',x'80'+c't',c'i',c'o' /L-I-A-TION db 4,x'80'+c't',c'i',c'o' /-TION db x'20'+5,c's',x'80'+c's',c'i',c'o' /S-SION db 4,x'80'+c's',c'i',c'o' /-SION db 4,c'n',x'80'+c'i',c'o' /N-ION db 4,x'80'+c'g',c'i',c'o' /-GION db 4,x'80'+c'c',c'i',c'o' /-CION db 3,x'80'+c'c',c'o' /-CON db 3,x'80'+c't',c'o' /-TON db 3,x'80'+c's',c'o' /-SON db 3,x'80'+c'r',c'i' /-RIN db 3,x'80'+c'p',c'i' /-PIN db 3,x'80'+c'n',c'i' /-NIN db 3,x'80'+c'm',c'i' /-MIN db 3,x'80'+c'l',c'i' /-LIN db 3,x'80'+c'k',c'i''t',x'80'+c'e' /-WRIT-ER db x'20'+5,c'i',c's',x'80'+c't',c'e' /IS-TER db x'20'+5,c'e',c's',x'80'+c't',c'e' /ES-TER db x'20'+5,c'a',c's',x'80'+c't',c'e' /AS-TER db 4,x'80'+c's',c't',c'e' /-STER db 5,c'a',c'r',x'80'+c't',c'e' /AR-TER db 4,c'r',c't',x'80'+c'e' /RT-ER db x'20'+5,c'm',x'80'+c'e',x'80'+c't',c'e' /M-E-TER db 5,x'80'+c'w',c'a',x'80'+c't',c'e' /-WA-TER db 3,c'r',x'80'+c'e' /R-ER db 4,c'o',c'p',x'80'+c'e' /OP-ER db 5,x'80'+c'p',c'a',x'80'+c'p',c'e' /-PA-PER db 4,c'w',c'n',x'80'+c'e' /WN-Ex'60'+2,x'80'+c's' //SS db x'20'+5,c'p',x'80'+c'o',x'80'+c'l',c'i' /P-O-LIS db x'60'+2,x'80'+c'i' //IS db x'40'+3,x'80'+c'x',c'e' /X/ES db x'40'+3,x'80'+c's',c'e' /S/ES db x'40'+4,c's',c'h',x'80'+c'e' /SH/ES db x'40'+4,c'c',c'h',x'80'+c'e' /CH/ES db x'c0'+1 //S db 0 suft equ * db 6,c'i',c'o',c'n',x'80'+c'i',c's' /ION-IST db 5,c'i',c'n',x'80'+c'i',c's' /IN-IST db 5,c'a',c'l',x'80'+c'i',c's' /AL-IST db 6,c'l',x'80'+c'o',x'80'+c'g',c'i',c's' /L-O-GIST db 5,c'h',c't',x'80'+c'e',c's' /HT-EST db 4,cx'80'+c'q',c'u',c'e',c'n',c'c' /-QUENCE db 7,x'80'+c'f',c'l',c'u',x'80'+c'e',c'n',c'c' /-FLU-ENCE db x'20'+6,c'e',c's',x'80'+c'e',c'n',c'c' /ES-ENCE db 6,c'e',c'r',x'80'+c'e',c'n',c'c' /ER-ENCE db 5,c'i',x'80'+c'e',c'n',c'c' /I-ENCE db x'20'+5,x'80'+c's',c'a',c'n',c'c' /-SANCE db 6,c'e',c'r',x'80'+c'a',c'n',c'c' /ER-ANCE db 6,c'a',c'r',x'80'+c'a',c'n',c'c' /AR-ANCE db 5,x'80'+c'n',c'a',c'n',c'c' /-NANCE db 7,x'80'+c'b',c'a',c'l',x'80'+c'a',c'n',c'c' /-BAL-ANCE db 5,c'i',x'80'+c'a',c'n',c'c' /I-ANCc'm',c'o',c'u',c't' /-MOUTH db 5,x'80'+c'w',c'o',c'r',c't' /-WORTH db 4,x'80'+c'w',c'i',c't' /-WITH db 5,c't',x'80'+c't',c'i',c's' /T-TISH db 5,c'e',x'80'+c't',c'i',c's' /E-TISH db 5,c'p',x'80'+c'p',c'i',c's' /P-PISH db 5,c'r',x'80'+c'n',c'i',c's' /R-NISH db 5,c'n',x'80'+c'n',c'i',c's' /N-NISH db 5,x'80'+c'p',c'l',c'i',c's' /-PLISH db 5,x'80'+c'g',c'u',c'i',c's' / -GUISH db 5,x'80'+c'g',c'l',c'i',c's' / -GLISH db 5,c'b',x'80'+c'l',c'i',c's' / B-LISH db 5,c'g',x'80'+c'g',c'i',c's' /G-GISH db 5,c'+c'a' /-TRI-AL db 4,c'r',c'i',x'80'+c'a' /RI-AL db 4,x'80'+c'n',c'i',x'80'+c'a' /-NI-AL db 4,x'80'+c'd',c'i',x'80'+c'a' /-DI-AL db 4,x'80'+c'c',c'i',c'a' /-CIAL db 3,x'80'+c'g',c'a' /-GAL db 4,x'80'+c'm',c'e',c'a' /-MEAL * db x'20'+4,x'80'+c'r',c'e',x'80'+c'a' /-RE-AL db x'20'+4,x'80'+c'r',c'e',c'a' /-REAL db 6,c'c',x'80'+c't',c'i',x'80'+c'c',c'a' /C-TI-CAL db 5,x'80'+c's',c'i',x'80'+c'c',c'a' /-SI-CAL db 4,x'80'+c'i',x'80'+c'c',c'a' /-I-CAL db 3,x'80'+c'c',c'a' /-CAL db 3,x'80'+c'b',c'a' /-BAL /-KIN db 5,x'80'+c's',c't',c'e',c'i' /-STEIN db 4,x'80'+c't',c'a',c'i' /-TAIN db 5,c'g',c'h',c't',x'80'+c'e' /GHT-EN db 5,x'80'+c'w',c'o',c'm',x'80'+c'e' /-WOM-EN db 3,x'80'+c'm',c'e' /-MEN db 4,c'o',x'80'+c'k',c'e' /O-KEN db 3,c'k',x'80'+c'e' /K-EN db 4,x'80'+c't',c'e',c'e' /-TEEN db 4,x'80'+c's',c'e',c'e' /-SEEN db x'20'+3,x'80'+c's',c'a' /-SAN db 5,x'80'+c'w',c'o',c'm',x'80'+c'a' /-WOM-AN db 3,x'80'+c'm',c'a' /-MAN db 4,x'80'+c't',c'i',c'a' /-TIAN db 4,x'80'+c's',c'i',c'a' /-SIAN db x'20'R db x'20'+4,c's',x'80'+c'n',c'e' /S-NER db 4,c'o',c'n',x'80'+c'e' /ON-ER db 4,c'r',c'm',x'80'+c'e' /RM-ER db 3,x'80'+c'm',c'e' /-MER db 4,c'l',c'l',x'80'+c'e' /LL-ER db 5,c'd',x'80'+c'd',c'l',c'e' /D-DLER db 4,x'80'+c'b',c'l',c'e' /-BLER db 3,c'k',x'80'+c'e' /K-ER db 5,c'n',x'80'+c't',c'h',c'e' /N-THER db 6,x'80'+c'f',c'a',x'80'+c't',c'h',c'e' /-FA-THER db 6,c'e',c'i',x'80'+c't',c'h',c'e' /EI-THER db 4,c't',c'h',x'80'+c'e' /TH-ER db 4,c's',c'h',x'80'+c'e' /SH-ER db 4,x'80'+c'p',c'h',c'e' /-PH'i',x'80'+c'e',c's' /I-EST db 5,c'g',x'80'+c'g',c'e',c's' /G-GEST db 4,c'g',x'80'+c'e',c's' /G-EST db 5,c'd',x'80'+c'd',c'e',c's' /D-DEST db 4,c'd',x'80'+c'e',c's' /D-EST db 4,x'80'+c'c',c'a',c's' /-CAST db 5,x'80'+c'h',c'e',c'a',c'r' /-HEART db 4,x'80'+c'f',c'o',c'o' /-FOOT db 3,c'i',x'80'+c'o' /I-OT db 5,x'80'+c'f',c'r',c'o',c'n' /-FRONT db 5,x'80'+c'p',c'r',c'i',c'n' /-PRINT db 4,x'80'+c'm',c'e',c'n' /-MENT db 5,x'80'+c'c',c'i',c'e',c'n' /-CIENT db 4,c'i',x'80'+c'a',c'n' /I-ANT db 6,x'80'+cE db 7,x'80'+c'j',c'u',c's',x'80'+c't',c'i',c'c' /-JUS-TICE db 5,x'80'+c's',c't',c'i',c'c' /-STICE db 5,x'80'+c'p',c'i',c'e',c'c' /-PIECE db 5,x'80'+c'p',c'l',c'a',c'c' /-PLACE db x'e0'+1 //E db 0 suff equ * db 5,x'80'+c'p',c'r',c'o',c'o' /-PROOF db 4,x'80'+c's',c'e',c'l' /-SELF db 3,x'80'+c'r',c'i' /-RIF db x'20'+4,x'80'+c'l',c'i',c'e' /-LIEF db 0 sufg equ * db 3,x'80'+c'l',c'o' /-LOG db 4,x'80'+c'l',c'o',c'n' /-LONG db 5,c't',x'80'+c't',c'i',c'n' /T-TING db 6,x'80'+c's',c't',c'r',c'i',c'n' 'd',x'80'+c'd',c'i',c's' /D-DISH db 3,x'80'+c'i',c's' /-ISH db 5,x'80'+c'g',c'r',c'a',c'p' /-GRAPH db 7,x'80'+c'b',c'o',c'r',x'80'+c'o',c'u',c'g' /-BOR-OUGH db 5,x'80'+c'b',c'u',c'r',c'g' /-BURGH db 4,x'80'+c'v',c'i',c'c' /-VICH db 3,x'80'+c'n',c'a' /-NAH db 3,x'80'+c'l',c'a' /-LAH db 4,x'80'+c'm',c'i',x'80'+c'a' /-MI-AH db 0 sufi equ * db 3,x'80'+c't',c'r' /-TRI db 3,x'80'+c'c',c'h' /-CHI db x'80'+3,c'i',c'f' /IF-I db x'80'+3,c'e',c'd' /ED-I db 5,x'80'+c'a',c's',c'c',c'i' /-ASCII db 0 sufk e db 6,x'80'+c'n',c'o',x'80'+c'm',c'i',x'80'+c'a' /-NO-MI-AL db 0 sufm equ * db 3,x'80'+c'n',c'u' /-NUM db 5,c'o',x'80'+c'r',c'i',x'80'+c'u' /O-RI-UM db x'20'+3,c'i',x'80'+c'u' /I-UM db x'20'+3,c'e',x'80'+c'u' /E-UM db 5,c'i',c'v',x'80'+c'i',c's' /IV-ISM db 4,x'80'+c't',c'i',c's' /-TISM db 5,c'i',x'80'+c'm',c'i',c's' /I-MISM db 5,c'a',c'l',x'80'+c'i',c's' /AL-ISM db x'20'+4,c'e',x'80'+c'i',c's' /E-ISM db x'20'+4,c'a',x'80'+c'i',c's' /A-ISM db 4,x'80'+c'r',c'o',c'o' /-ROOM db 3,x'80'+c'd',c'o' /+4,c'e',x'80'+c'i',c'a' /E-IAN db 4,x'80'+c'c',c'i',c'a' /-CIAN db x'c0'+3,c'i',c'a' /IA/N db 5,x'80'+c'c',c'l',c'e',c'a' /-CLEAN db 4,x'80'+c'm',c'e',c'a' /-MEAN db x'20'+3,c'e',x'80'+c'a' /E-AN db 0 sufo equ * db 5,x'80'+c'm',c'a',c'c',x'80'+c'r' /-MAC-RO db 0 sufp equ * db 5,x'80'+c'g',c'r',c'o',c'u' /-GROUP db 2,x'80'+c'u' /-UP db 4,x'80'+c's',c'h',c'i' /-SHIP db 4,x'80'+c'k',c'e',c'e' /-KEEP db 0 sufr equ * db 4,x'80'+c'z',c'a',c'r' /-ZARR db x'c0'+2,c'r' /R/R db 3,x'80'+c't',c'o' /-TORER db 4,c'c',c'h',x'80'+c'e' /CH-ER db 4,c'd',c'g',x'80'+c'e' /DG-ER db 4,c'r',c'd',x'80'+c'e' /RD-ER db 6,c'o',c'u',c'n',c'd',x'80'+c'e' /OUND-ER db 4,c'l',c'd',x'80'+c'e' /LD-ER db 4,c'i',c'd',x'80'+c'e' /ID-ER db 5,x'80'+c'd',c'u',c'c',x'80'+c'e' /-DUC-ER db 4,c'n',c'c',x'80'+c'e' /NC-ER db x'40'+2,x'80'+c'e' / /ER db 3,x'80'+c's',c'a' /-SAR db x'20'+6,c'a',c'c',x'80'+c'u',x'80'+c'l',c'a' /AC-U-LAR db x'20'+6,c'e',c'c',x'80'+c'u',x'80'+c'l',c'a' /EC-U-LAR db x'20'+6,c'i',c'c',x'80'+c'u',x'80'w',c'r',c'i',c'g',c'h' /-WRIGHT db 6,x'80'+c'b',c'r',c'i',c'g',c'h' /-BRIGHT db 6,x'80'+c'f',c'l',c'i',c'g',c'h' /-FLIGHT db 6,x'80'+c'w',c'e',c'i',c'g',c'h' /-WEIGHT db 5,x'80'+c's',c'h',c'i',c'f' /-SHIFT db 5,x'80'+c'c',c'r',c'a',c'f' /-CRAFT db x'20'+4,c'd',c'g',x'80'+c'e' /DG-ET db 4,x'80'+c'g',c'o',c'a' /-GOAT db 4,x'80'+c'c',c'o',c'a' /-COAT db 4,x'80'+c'b',c'o',c'a' /-BOAT db 4,x'80'+c'w',c'h',c'a' /-WHAT db 4,x'80'+c'c',c'u',c'i' /-CUIT db 0 sufy equ * db x'20'+4,c'e',c's',x'80'+c't' // -STRING db 5,c'r',x'80'+c'r',c'i',c'n' /R-RING db 5,c'p',x'80'+c'p',c'i',c'n' /P-PING db 5,c'n',x'80'+c'n',c'i',c'n' /N-NING db 5,c'm',x'80'+c'm',c'i',c'n' /M-MING db 5,c'l',x'80'+c'l',c'i',c'n' / L-LING db 5,x'80'+c'z',c'l',c'i',c'n' /-ZLING db 5,x'80'+c't',c'l',c'i',c'n' /-TLING db x'20'+5,c's',x'80'+c'l',c'i',c'n' /S-LING db 5,c'r',x'80'+c'l',c'i',c'n' /R-LING db 5,x'80'+c'p',c'l',c'i',c'n' /-PLING db 6,c'n',x'80'+c'k',c'l',c'i',c'n' /N-KLING db 5,c'k',x'80'+c'l',c'i',c'n' /K-LING db 5,x'8qu * db 4,x'80'+c'w',c'o',c'r' /-WORK db 4,x'80'+c'm',c'a',c'r' /-MARK db 4,x'80'+c'b',c'o',c'o' /-BOOK db 4,x'80'+c'w',c'a',c'l' /-WALK db 5,x'80'+c'c',c'r',c'a',c'c' /-CRACK db 4,x'80'+c'b',c'a',c'c' /-BACK db 0 sufl equ * db 3,x'80'+c'f',c'u' /-FUL db 5,c's',x'80'+c'w',c'e',c'l' /S-WELL db 4,x'80'+c't',c'e',c'l' /-TELL db 5,x'80'+c's',c'h',c'e',c'l' /-SHELL db 5,x'80'+c's',c't',c'a',c'l' /-STALL db 4,x'80'+c's',c't',c'a' /-STAL db 4,x'80'+c'b',c'a',c'l' /-BALL db 3,c'v',x'80'+c'e' /V-EL d-DOM db 3,x'80'+c'h',c'a' /-HAM db 6,x'80'+c'a',x'80'+c'r',c'i',c't',c'h' /-A-RITHM db 5,x'80'+c'r',c'i',c't',c'h' /-RITHM db 0 sufn equ * db 4,x'80'+c't',c'o',c'w' /-TOWN db 4,x'80'+c'd',c'o',c'w' /-DOWN db 4,x'80'+c't',c'u',c'r' /-TURN db 5,x'80'+c's',c'p',c'o',c'o' /-SPOON db 4,x'80'+c'n',c'o',c'o' /-NOON db 4,x'80'+c'm',c'o',c'o' /-MOON db 9,c'a',c'l',x'80'+c'i',x'80'+c'z',c'a',x'80'+c't',c'i',c'o' /AL-I-ZA-TION db 7,x'80'+c'i',x'80'+c'z',c'a',x'80'+c't',c'i',c'o' /-I-ZA-TION db 7,c'l',x'80 db x'20'+3,x'80'+c's',c'o' /-SOR db x'20'+4,x'80'+c'r',c'i',x'80'+c'o' /-RI-OR db 4,c'i',c'z',x'80'+c'e' /IZ-ER db 5,x'80'+c'c',c'o',c'v',x'80'+c'e' /-COV-ER * db 4,c'o',x'80'+c'v',c'e' /O-VER db 4,x'80'+c'o',c'v',c'e' /-OVER db 4,x'80'+c'e',c'v',x'80'+c'e' /-EV-ER db 8,x'80'+c'c',c'o',c'm',x'80'+c'p',c'u',c't',x'80'+c'e' /-COM-PUT-ER db x'20'+5,c'u',c's',x'80'+c't',c'e' /US-TER db 5,c'o',c's',c't',x'80'+c'e' /OST-ER db x'20'+5,x'80'+c'a',c'c',x'80'+c't',c'e' /-AC-TER db 6,x'80'+c'w',c'r',c'i',c'+c'l',c'a' /IC-U-LAR db x'20'+6,c'e',c'g',x'80'+c'u',x'80'+c'l',c'a' /EG-U-LAR db 0 sufs equ * db x'20'+4,c'u',x'80'+c'o',c'u' /U-OUS db 5,x'80'+c't',c'i',c'o',c'u' /-TIOUS db 5,x'80'+c'g',c'i',c'o',c'u' /-GIOUS db 5,x'80'+c'c',c'i',c'o',c'u' /-CIOUS db x'20'+4,c'i',x'80'+c'o',c'u' /I-OUS db 5,x'80'+c'g',c'e',c'o',c'u' /-GEOUS db 5,x'80'+c'c',c'e',c'o',c'u' /-CEOUS db 4,c'e',x'80'+c'o',c'u' /E-OUS db x'60'+2,x'80'+c'u' //US db 4,x'80'+c'n',c'e',c's' /-NESS db 4,x'80'+c'l',c'e',c's' /-LESS db ES-TY db x'20'+5,c'q',c'u',c'i',x'80'+c't' /QUI-TY db 4,x'80'+c't',c'i',x'80'+c't' /-TI-TY db x'20'+5,c'o',c's',x'80'+c'i',x'80'+c't' /OS-I-TY db 4,x'80'+c's',c'i',x'80'+c't' /-SI-TY db 5,c'i',c'n',x'80'+c'i',x'80'+c't' /IN-I-TY db 4,c'n',c'i',x'80'+c't' /NI-TY db x'20'+8,c'f',c'a',x'80'+c'b',c'i',c'l',x'80'+c'i',x'80'+c't' /FA-BIL-I-TY db 8,x'80'+c'c',c'a',x'80'+c'b',c'i',c'l',x'80'+c'i',x'80'+c't' /-CA-BIL-I-TY db 8,x'80'+c'p',c'a',x'80'+c'b',c'i',c'l',x'80'+c'i',x'80'+c't' /-PA-BIL-I-TY db 6,x'80'+c'b',c'i',c'l',x'80'+c'i',x'80'+c't' /-BIL-I-TY db 3,c'i',x'80'+c't' /I-TY db 4,x'80'+c'b',c'u',c'r' /-BUR-Y db 4,x'80'+c't',c'o',x'80'+c'r' /-TO-RY db 5,x'80'+c'q',c'u',c'a',c'r' /-QUAR-Y db x'20'+4,c'u',x'80'+c'a',c'r' /U-ARY db 7,x'80'+c'm',c'e',c'n',x'80'+c't',c'a',x'80'+c'r' /-MEN-TA-RY db 6,c'i',c'o',c'n',x'80'+c'a',c'r' /ION-ARY db 4,c'i',x'80'+c'a',c'r' /I-ARY db 4,c'n',x'80'+c'o',x'80'+c'm' /N-O-MY db 3,x'80'+c'p',c'l' /-PLY db 4,c'g',x'80'+c'g',c'l' /G-GLY db 5,x'80'+c'p',c'a',x'80nt1; extern int pts; extern int pts1; extern int apts; extern int apts1; extern int sps; extern int nlflg; extern int nform; extern int dfact; extern int lss; extern int lss1; extern int vflag; extern int ch0; extern int lg; char fontfile[] "/usr/lib/font/XX"; int ffi 14; extern int bd; extern int level; extern int ch; extern int res; extern int ptid; extern int xxx; extern char W1[],W2[],W3[],W4[]; int *fontab[] {W1,W2,W3,W4}; int fontlab[] {'R','I','B','S',0}; char pstab[] {6,7,8,9,10,11,12,14,16,18,20,22s =| DBL; oldbits = j; pfont = xfont; ppts = xpts; goto rtn; } switch(xbitf){ case 0: xfont = font; xpts = pts; break; case 1: xfont = pfont; xpts = ppts; break; case 2: xfont = mfont; xpts = mpts; } rtn: xbitf = 0; } setch(){ register i,*j,k; extern int chtab[]; if((i = getrq()) == 0)return(0); for(j=chtab;*j != i;j++)if(*(j++) == 0)return(0); k = *(++j) | chbits; /* if((i & CMASK) == '*'){ if(((i = find('R',fontlab)) < 0) && ((i = find('G',fontlab)) turn; } if((i =- '0') == 0){ casps1(apts1); return; } if((i > 0) && (i <= 9)){ if((i <= 3) && ((j=(ch = getch() & CMASK) - '0') >= 0) && (j <= 9)){ i = 10*i +j; ch = 0; } casps1(i); } } caseft(){ skip(); setfont(1); } setfont(a) int a; { register i,j; if(a)i = getrq(); else i = getsn(); if(!i || (i == 'P')){ j = font1; goto s0; } if(i == 'S')return; if((j = find(i,fontlab)) == -1)return; s0: font1 = font; font = j; mchbits(); } setwd(){ register i, base, wid; in = 0214; break; case 'l': j = 0215; break; default: ch0 = k; j = 0213; } }else j = 0213; break; case 'l': j = 0212; break; case 'i': j = 0211; break; default: ch0 = j; j = i; } return((i & ~CMASK) | j); } caselg(){ register i; lg++; if(skip())return; lg = atoi(); } casefp(){ register i, j, k; int x; skip(); if(((i = (getch() & CMASK) - '0' -1) < 0) || (i >3))return; if(skip() || !(j = getrq()))return; fontfile[ffi] = j &((j & 077)<<9) | LX); } '+c'b',c'l' /-PA-BLY db 5,c'f',c'a',x'80'+c'b',c'l' /FA-BLY db 5,x'80'+c'c',c'a',x'80'+c'b',c'l' /-CA-BLY db 4,x'80'+c'a',c'b',c'l' /-ABLY db 3,x'80'+c'b',c'l' /-BLY db 2,x'80'+c'l' /-LY db 3,x'80'+c's',c'k' /-SKY db x'20'+6,c'g',x'80'+c'r',c'a',x'80'+c'p',c'h' /G-RA-PHY db 4,c'l',x'80'+c'o',x'80'+c'g' /L-O-GY db 2,x'80'+c'f' /-FY db 3,x'80'+c'n',c'e' /-NEY db 3,x'80'+c'l',c'e' /-LEY db 4,c'c',c'k',x'80'+c'e' /CK-EY db 3,x'80'+c'k',c'e' /-KEY db 4,x'80'+c'b',c'o',c'd' /-BODY db 5,x'80'+c's',c,24,28,36,0}; char psctab[] {010,000,001,007,002,003,004,005,0211,006, 0212,0213,0214,0215,0216,0}; int cstab[4], ccstab[4]; int bdtab[4]; int sbold 0; width(c) int c; { register i,j,k; j = c; k = 0; if(j & MOT){ if(j & VMOT)goto rtn; k = j & ~MOTV; if(j & NMOT)k = -k; goto rtn; } if((i = (j & CMASK)) == 010){ k = -widthp; goto rtn; } if(i == PRESC)i = eschar; if((i == ohc) || (i >= 0370))goto rtn; if((j>>BYTE) == oldbits){ xfont = pfont; xpts = ppts; }else xbits(j); if(j< 0)) return(k); else return((k & ~(03<<(BYTE+1))) | (i<<(BYTE+1))); } */ return(k); } find(i,j) int i,j[]; { register k; if(((k = i-'0') >= 1) && (k <= 4) && (k != smnt))return(--k); for(k=0; j[k] != i; k++)if(j[k] == 0)return(-1); return(k); } caseps(){ register i; if(skip())i = apts1; else{ noscale++; i = inumb(&apts); noscale = 0; if(nonumb)return; } casps1(i); } casps1(i) int i; { if(i <= 0)return; apts1 = apts; apts = i; pts1 = pts; pts = findps(i & 077); mchbits(); } ft delim, em, k; int savlevel, savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; base = v.st = v.sb = wid = v.ct = 0; if((delim = getch() & CMASK) & MOT)return; savhp = v.hp; savlevel = level; v.hp = level = 0; savapts = apts; savapts1 = apts1; savfont = font; savfont1 = font1; savpts = pts; savpts1 = pts1; setwdf++; while((((i = getch()) & CMASK) != delim) && !nlflg){ wid =+ width(i); if(!(i & MOT)){ em = (xpts & 077)*6; }else if(i & VMOT){ k = i & ~MOTV; if(i & N BMASK; fontfile[ffi+1] = j>>BYTE; if((k = open(fontfile,0)) < 0){ prstr("Cannot open "); c0: prstr(fontfile); prstr("\n"); done(-1); } if(seek(k,16,0) < 0)goto c1; if(read(k,fontab[i],256-32) != 256-32){ c1: prstr("Cannot read "); goto c0; } close(k); if(i == (smnt-1)){smnt = 0; sbold = 0;} if((fontlab[i] = j) == 'S')smnt = i + 1; bdtab[i] = cstab[i] = ccstab[i] = 0; if(ptid != 1){ prstr("Mount font "); prstr(&fontfile[ffi]); prstr(" on "); x = i + '1'; prstr(&x); prstr#include "tdef.h" #include "t.h" /* troff10.c CAT interface */ extern int *olinep; extern int oline[]; extern int *pslp; extern int back; extern int xpts; extern int mpts; extern int po; extern int xflg; extern int line[]; extern int lss; extern int xbitf; extern char obuf[]; extern char *obufp; extern int esct; extern int trflg; extern int cs; extern int smnt; extern int mfont; extern int xfont; extern int code; extern int mcase; extern int esc; extern int lead; extern int paper; extern int cps; extern i't',c'u',c'd' /-STUDY db x'e0'+4,c'e',c'e',c'd' /EEDY db 2,x'80'+c'b' /-BY db 3,x'80'+c'w',c'a' /-WAY db 3,x'80'+c'd',c'a' /-DAY db 0 align adc end & ZBIT)goto rtn; if(!trflg)i = trtab[i] & BMASK; if((i =- 32) < 0)goto rtn; k = getcw(i); if(bd)k =+ bd - 1; if(cs)k = cs; rtn0: widthp = k; rtn: xbitf = trflg = 0; return(k); } getcw(i) int i; { register j, k; register char *p; extern int ldivr, ldiv(); extern char codetab[]; bd = 0; if((code = codetab[i]) & 0200){ if(smnt){ p = fontab[smnt-1]; if(xfont == (sbold-1))bd = bdtab[smnt-1]; goto g0; } code = 0; k = 36; goto g1; } p = fontab[xfont]; g0: if(!i)k = spacesz; indps(i) int i; { register j, k; for(j=0; i > (k = pstab[j]);j++)if(!k){k=pstab[--j];break;} if(psctab[j] < 0)k =| DBL; return(k); } mchbits(){ register i, j, k; i = pts & 077; for(j=0; i > (k = pstab[j]);j++)if(!k){k=pstab[--j];break;} chbits = (((++j)<<2) | font) << (BYTE + 1); sps = width(' ' | chbits); } setps(){ register i,j; if((((i=getch() & CMASK) == '+') || (i == '-')) && (((j=(ch = getch() & CMASK) - '0') >= 0) && (j <= 9))){ if(i == '-')j = -j; ch = 0; casps1(apts+j); reMOT)k = -k; base =- k; em = 0; }else continue; if(base < v.sb)v.sb = base; if((k=base + em) > v.st)v.st = k; } nform = 0; setn1(wid); v.hp = savhp; level = savlevel; apts = savapts; apts1 = savapts1; font = savfont; font1 = savfont1; pts = savpts; pts1 = savpts1; mchbits(); setwdf = 0; } vmot(){ dfact = lss; vflag++; return(mot()); } hmot(){ dfact = 6 * (pts & 077); return(mot()); } mot(){ register i, j; j = HOR; getch(); /*eat delim*/ if(i = atoi()){ if(vflag)j = VERT; ("\n"); } } casecs(){ register i, j; noscale++; skip(); if(!(i=getrq()) || ((i = find(i,fontlab)) < 0))goto rtn; skip(); cstab[i] = atoi(); skip(); j = atoi(); if(!nonumb)ccstab[i] = findps(j); rtn: noscale = 0; } casebd(){ register i, j, k; k = 0; bd0: if(skip() || !(i = getrq()) || ((j = find(i,fontlab)) == -1)){ if(k)goto bd1; else return; } if(j == (smnt-1)){ k = smnt; goto bd0; } if(k){ sbold = j + 1; j = k -1; } bd1: skip(); noscale++; bdtab[j] = atoi(); nosnt psflg; extern int ptid; extern int verm; extern int escm; extern char pstab[], psctab[]; extern int *dip; extern int dpn; extern int ascii; int mrail 0; /*0=LR,1=UR*/ int mmag 1; /*0=UM,1=LM*/ extern int nofeed; extern int gflag; extern int fontlab[]; int papflg; extern int pfont; extern int ppts; extern int oldbits; extern int bd; extern int vflag; extern int xxx; ptinit(){ if(ascii || gflag)return; oput(T_INIT); esc = T_IESC; ptesc(); esct = 0; esc = po; oput(0140); /*some initial lead*/ } pto#include "tdef.h" #include "t.h" /* troff6.c width functions, sizes and fonts */ extern int eschar; extern int widthp; extern int ohc; extern int trflg; extern int xpts; extern int xfont; extern int code; extern int smnt; extern int setwdf; extern int cs; extern int ccs; extern int spacesz; extern char trtab[]; extern int xbitf; extern int mfont; extern int mpts; extern int pfont; extern int ppts; extern int oldbits; extern int chbits; extern int nonumb; extern int noscale; extern int font; extern int foelse k = *(p + i) & BMASK; if(setwdf)v.ct =| ((k>>6) & 3); g1: k = ldiv(0, (k&077)*(xpts&077),6); if(ldivr >= 3)k++; if(cs = cstab[xfont]){ if(ccs = ccstab[xfont])xpts = ccs; cs = ldiv(0, (cs&077)*(xpts&077), 6); if(ldivr >= 3)cs++; } if(!bd)bd = bdtab[xfont]; return(k); } xbits(i) int i; { register j, k; /* if((j = i >> BYTE) == oldbits){ xfont = pfont; xpts = ppts; goto rtn; } */ j = i >> BYTE; xfont = (j>>1) & 03; if(k = (j>>3) & 017){ xpts = pstab[--k]; if(psctab[k] < 0)xpt i = makem(quant(i,j)); } getch(); vflag = 0; dfact = 1; return(i); } sethl(k) int k; { register i; i = 3 * (pts & 077); if(k == 'u')i = -i; else if(k == 'r')i = -2*i; vflag++; i = makem(i); vflag = 0; return(i); } makem(i) int i; { register j; if((j = i) < 0)j = -j; j = (j & ~MOTV) | MOT; if(i < 0)j =| NMOT; if(vflag)j =| VMOT; return(j); } getlg(i) int i; { register j, k; switch((j = getch0()) & CMASK){ case 'f': if(lg!=2){switch((k =getch0()) & CMASK){ case 'i': jcale = 0; } casevs(){ register i; skip(); vflag++; dfact = 6; /*default scaling is points!*/ res = VERT; i = inumb(&lss); if(nonumb)i = lss1; if(i < VERT)i = VERT; lss1 = lss; lss = i; } casess(){ register i; noscale++; skip(); if(i = atoi()){ spacesz = i& 0177; sps = width(' ' | chbits); } noscale = 0; } xlss(){ register i, j; getch(); dfact = lss; i = quant(atoi(),VERT); dfact = 1; getch(); if((j = i) < 0)j = -j; ch0 = ((j & 03700)<<3) | HX; if(i < 0)ch0 =| 040000; return(ut(i) int i; { register *k, lw, *j; int ds, de, inith, temp, *slp, dv; int psl[16]; if((i & CMASK) != '\n'){ *olinep++ = i; return; } if(olinep == oline){ lead =+ lss; return; } pslp = psl; *pslp = lw = inith = dv = 0; for(k=oline; kblss + lss; dip->blss = 0; slp = k; scan: temp = esct - po; if(mpts & DBL)temp =- rn; if(cps){ psflg++; i = findps(cps); }else i = xpts; for(j=0; (i&077) > (k = pstab[j]);j++)if(!k){k=pstab[--j];break;} j = psctab[j]; oput((j & ~0200) | 0120); if((!(mpts & DBL))^(!(j & 0200))){ if(j & 0200)k = 55; else k = -55; esc =+ k; } mpts = i; } ptlead(){ register i, k; if(k = lead < 0)lead = -lead; if(k^verm)oput(0112 + ((verm=k)<<1)); if(((k=lead)%3) == 2)k++; k =/ 3; while(k > 0){ if((i=31) > k)i = k; if(verm)paper =- i; else paper =+ i; oput(((~i) & 037) | 014/* character name and code tables default width tables modified for BTL special font version 4 and Commercial II */ int chtab [] { 'hy', 0200, /*hyphen*/ 'bu', 0201, /*bullet*/ 'sq', 0202, /*square*/ 'em', 0203, /*3/4em*/ 'ru', 0204, /*rule*/ '14', 0205, /*1/4*/ '12', 0206, /*1/2*/ '34', 0207, /*3/4*/ 'mi', 0302, /*equation minus*/ 'fi', 0211, /*fi*/ 'fl', 0212, /*fl*/ 'ff', 0213, /*ff*/ 'Fi', 0214, /*ffi*/ 'Fl', 0215, /*ffl*/ 'de', 0216, /*degree*/ 'dg', 0217, /*dagger*/ 'sc', 0220, /*section*/ 'fm', 0221ltiply*/ 'di', 0314, /*divide*/ '+-', 0315, /*plus-minus*/ 'cu', 0316, /*cup (union)*/ 'ca', 0317, /*cap (intersection)*/ 'sb', 0320, /*subset of*/ 'sp', 0321, /*superset of*/ 'ib', 0322, /*improper subset*/ 'ip', 0323, /* " superset*/ 'if', 0324, /*infinity*/ 'pd', 0325, /*partial derivative*/ 'gr', 0326, /*gradient*/ 'no', 0327, /*not*/ 'is', 0330, /*integral sign*/ 'pt', 0331, /*proportional to*/ 'es', 0332, /*empty set*/ 'mo', 0333, /*member of*/ 'pl', 0334, /*equation plus*/ 'rg', 0335, /*registered*/ 223, /*down arrow*/ 0232, /*equation equal*/ 0323, /*multiply*/ 0324, /*divide*/ 0325, /*plus-minus*/ 0260, /*cup (union)*/ 0305, /*cap (intersection)*/ 0270, /*subset of*/ 0271, /*superset of*/ 0350, /*improper subset*/ 0246, /* improper superset*/ 0244, /*infinity*/ 0273, /*partial derivative*/ 0253, /*gradient*/ 0307, /*not*/ 0266, /*integral sign*/ 0247, /*proportional to*/ 0343, /*empty set*/ 0341, /*member of*/ 0353, /*equation plus*/ 0141, /*registered*/ 0153, /*copyright*/ 0346, /*box rule (was para55; ds = temp - inith; de = lw - temp; if(de >= ds){ back = 0; esc = -ds; for(k=slp; k=slp; --k)ptout0(*k); } if(xflg && (--pslp >= psl))goto scan; olinep = oline; lead =+ dip->alss; dip->alss = 0; } ptout0(i) int i; { register j, k, w; int z; if(i & MOT){ j = i & ~MOTV; if(i & NMOT)j = -j; if(back)j = -j; if(i & VMOT)lead =+ j; else esc =+ j; return; } xbitf = 2; if((i>>BYTE) == oldbits){ xfont , /*foot mark*/ 'aa', 0222, /*acute accent*/ 'ga', 0223, /*grave accent*/ 'ul', 0224, /*underrule*/ 'sl', 0225, /*slash (longer)*/ '*a', 0230, /*alpha*/ '*b', 0231, /*beta*/ '*g', 0232, /*gamma*/ '*d', 0233, /*delta*/ '*e', 0234, /*epsilon*/ '*z', 0235, /*zeta*/ '*y', 0236, /*eta*/ '*h', 0237, /*theta*/ '*i', 0240, /*iota*/ '*k', 0241, /*kappa*/ '*l', 0242, /*lambda*/ '*m', 0243, /*mu*/ '*n', 0244, /*nu*/ '*c', 0245, /*xi*/ '*o', 0246, /*omicron*/ '*p', 0247, /*pi*/ '*r', 0250, /*rho*/ '*s', 0251, /*sigma*/ 'co', 0336, /*copyright*/ 'br', 0337, /*box vert rule*/ 'ct', 0340, /*cent sign*/ 'dd', 0341, /*dbl dagger*/ 'rh', 0342, /*right hand*/ 'lh', 0343, /*left hand*/ '**', 0344, /*math * */ 'bs', 0345, /*bell system sign*/ 'or', 0346, /*or*/ 'ci', 0347, /*circle*/ 'lt', 0350, /*left top (of big curly)*/ 'lb', 0351, /*left bottom*/ 'rt', 0352, /*right top*/ 'rb', 0353, /*right bot*/ 'lk', 0354, /*left center of big curly bracket*/ 'rk', 0355, /*right center of big curly bracket*/ 'bv', 0356, /*bold vertical*/ '/*d*/ 031, /*e*/ 014, /*f*/ 045, /*g*/ 001, /*h*/ 006, /*i*/ 015, /*j*/ 017, /*k*/ 005, /*l*/ 004, /*m*/ 003, /*n*/ 033, /*o*/ 021, /*p*/ 042, /*q*/ 035, /*r*/ 010, /*s*/ 002, /*t*/ 016, /*u*/ 037, /*v*/ 041, /*w*/ 013, /*x*/ 051, /*y*/ 007, /*z*/ 0332, /*{*/ 0151, /*|*/ 0333, /*}*/ 0342, /*~*/ 00, /*narrow space*/ 040, /*hyphen*/ 0146, /*bullet*/ 0154, /*square*/ 022, /*3/4 em*/ 026, /*rule*/ 034, /*1/4*/ 036, /*1/2*/ 046, /*3/4*/ 0123, /*minus*/ 0124, /*fi*/ 0125, /*fl*/ 0126, /*ff*/ 0131, /*ffi*/ 0130, /llel sign)*/ 0127, /*cent sign*/ 0345, /*dbl dagger*/ 0250, /*right hand*/ 0340, /*left hand*/ 0347, /*math * */ 0243, /*bell system sign*/ 0226, /*or (was star)*/ 0351, /*circle*/ 0311, /*left top (of big curly)*/ 0314, /*left bottom*/ 0315, /*right top*/ 0317, /*right bot*/ 0313, /*left center of big curly bracket*/ 0316, /*right center of big curly bracket*/ 0312, /*bold vertical*/ 0321, /*left floor (left bot of big sq bract)*/ 0320, /*right floor (rb of ")*/ 0322, /*left ceiling (lt of ")*/ 0310}; /*ri = pfont; xpts = ppts; xbitf = 0; }else xbits(i); if((k = (i & CMASK)) < 040){ return; } w = getcw(k-32); if(i & ZBIT){ w = 0; z = 1; }else z = 0; if(cs){ j = (cs-w)/2; w = cs - j; }else j = 0; if(back){ k = j; j = -w; w = -k; } esc =+ j; if((!xflg || (xpts == *pslp)) && (code & 077)){ if(code & 0200){ if(smnt)xfont = smnt -1; else goto p1; } if((k=(code>>6)&01)^mcase)oput((mcase=k)+0105); if(xfont != mfont){ mfont = xfont; if(mrail != (xfont&01)) oput0); if((paper > (11*144*15)) && !papflg){ prstr("Excessive paper use.\n"); papflg++; if(ptid != 1)done2(0200); } k =- i; } lead = 0; } ptesc(){ register i, j, k; if(k = esc < 0)esc = -esc; if(k^escm)oput(0107 + (escm=k)); k = esc; while(k > 0){ if((i=127) > k)i = k; if(((j = (esct + i*(1-2*escm))) > (46*72+18-T_IESC)) || (j < 0))break; /* oput(~i); */ *obufp++ = ~i; if(obufp == (obuf + OBUFSZ + ascii - 1))flusho(); esct = j; k =- i; } esc = 0; } dostop(){ registe '*t', 0252, /*tau*/ '*u', 0253, /*upsilon*/ '*f', 0254, /*phi*/ '*x', 0255, /*chi*/ '*q', 0256, /*psi*/ '*w', 0257, /*omega*/ '*A', 0101, /*Alpha*/ '*B', 0102, /*Beta*/ '*G', 0260, /*Gamma*/ '*D', 0261, /*Delta*/ '*E', 0105, /*Epsilon*/ '*Z', 0132, /*Zeta*/ '*Y', 0110, /*Eta*/ '*H', 0262, /*Theta*/ '*I', 0111, /*Iota*/ '*K', 0113, /*Kappa*/ '*L', 0263, /*Lambda*/ '*M', 0115, /*Mu*/ '*N', 0116, /*Nu*/ '*C', 0264, /*Xi*/ '*O', 0117, /*Omicron*/ '*P', 0265, /*Pi*/ '*R', 0120, /*Rho*/ '*S', 0266, /*Sigma*/ '*Tlf', 0357, /*left floor (left bot of big sq bract)*/ 'rf', 0360, /*right floor (rb of ")*/ 'lc', 0361, /*left ceiling (lt of ")*/ 'rc', 0362, /*right ceiling (rt of ")*/ 0,0}; char codetab[256-32] { /*cat codes*/ 00, /*space*/ 0145, /*!*/ 0230, /*"*/ 0337, /*#*/ 0155, /*$*/ 053, /*%*/ 050, /*&*/ 032, /*' close*/ 0132, /*(*/ 0133, /*)*/ 0122, /***/ 0143, /*+*/ 047, /*,*/ 040, /*- hyphen*/ 044, /*.*/ 043, /*/*/ 0110, /*0*/ 0111, /*1*/ 0112, /*2*/ 0113, /*3*/ 0114, /*4*/ 0115, /*5*/ 0116, /*6*/ 0117, /*7*/ 01*ffl*/ 0136, /*degree*/ 0137, /*dagger*/ 0355, /*section*/ 0150, /*foot mark*/ 0334, /*acute accent*/ 0335, /*grave accent*/ 0240, /*underrule*/ 0304, /*slash (longer)*/ 00, /*half nar sp*/ 00, /**/ 0225, /*alpha*/ 0212, /*beta*/ 0245, /*gamma*/ 0211, /*delta*/ 0231, /*epsilon*/ 0207, /*zeta*/ 0214, /*eta*/ 0202, /*theta*/ 0206, /*iota*/ 0217, /*kappa*/ 0205, /*lambda*/ 0204, /*mu*/ 0203, /*nu*/ 0213, /*xi*/ 0233, /*omicron*/ 0221, /*pi*/ 0235, /*rho*/ 0210, /*sigma*/ 0237, /*tau*/ 0216, /*upsilon*/ 0215, /ght ceiling (rt of ")*/ /*modified for Commercial II*/ char W1[256-32] { /*Times Roman widths*/ 12, /*space*/ 12, /*!*/ 0, /*"*/ 0, /*#*/ 19, /*$*/ 29, /*%*/ 28, /*&*/ 12, /*' close*/ 16, /*(*/ 16, /*)*/ 16, /***/ 36, /*+*/ 12, /*,*/ 13, /*- hyphen*/ 10, /*.*/ 17, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+0200, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+0200, /*7*/ 19+0200, /*8*/ 19+0200, /*9*/ 10, /*:*/ 12, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 20, /*?*/ 0, /*@*/ (0101 + (mrail=xfont&01)); if(mmag != (xfont<2)) oput(0103 + (mmag=(xfont<2))); } if(xpts != mpts)ptps(); if(lead)ptlead(); if(esc)ptesc(); /* oput(code & 077); */ *obufp++ = code & 077; if(obufp == (obuf + OBUFSZ + ascii - 1))flusho(); if(bd){ bd =- 1; if(back && !z)bd = -bd; if(esc =+ bd)ptesc(); oput(code & 077); if(z)esc =- bd; } }else if(bd && !z){ bd =- 1; if(back)bd = -bd; esc =+ bd; } p1: esc =+ w; return; } ptps(){ register i, j, k; if(psflg)retur i; if(ascii)return; if(!nofeed && !gflag)lead =+ TRAILER; ptlead(); flusho(); oput(T_INIT); oput(T_STOP); if(gflag){ oput('f'); for(i=0; i<4; i++){ oput(fontlab[i] & BMASK); oput((fontlab[i]>>BYTE) & BMASK); } }else for(i=8; i>0; i--)oput(T_PAD); flusho(); mcase = mpts = mfont = mrail = verm = escm = 0; mmag = 1; report(); paper = 0; esc = T_IESC; ptesc(); esct = 0; esc = po; } ', 0124, /*Tau*/ '*U', 0270, /*Upsilon*/ '*F', 0271, /*Phi*/ '*X', 0130, /*Chi*/ '*Q', 0272, /*Psi*/ '*W', 0273, /*Omega*/ 'sr', 0274, /*square root*/ 'ts', 0275, /*terminal sigma*/ 'rn', 0276, /*root en*/ '>=', 0277, /*>=*/ '<=', 0300, /*<=*/ '==', 0301, /*identically equal*/ '~=', 0303, /*approx =*/ 'ap', 0304, /*approximates*/ '!=', 0305, /*not equal*/ '->', 0306, /*right arrow*/ '<-', 0307, /*left arrow*/ 'ua', 0310, /*up arrow*/ 'da', 0311, /*down arrow*/ 'eq', 0312, /*equation equal*/ 'mu', 0313, /*mu20, /*8*/ 0121, /*9*/ 0142, /*:*/ 023, /*;*/ 0303, /*<*/ 0140, /*=*/ 0301, /*>*/ 0147, /*?*/ 0222, /*@*/ 0103, /*A*/ 075, /*B*/ 070, /*C*/ 074, /*D*/ 072, /*E*/ 0101, /*F*/ 065, /*G*/ 060, /*H*/ 066, /*I*/ 0105, /*J*/ 0107, /*K*/ 063, /*L*/ 062, /*M*/ 061, /*N*/ 057, /*O*/ 067, /*P*/ 055, /*Q*/ 064, /*R*/ 076, /*S*/ 056, /*T*/ 0106, /*U*/ 071, /*V*/ 0104, /*W*/ 0102, /*X*/ 077, /*Y*/ 073, /*Z*/ 0134, /*[*/ 0241, /*\*/ 0135, /*]*/ 0336, /*^*/ 0240, /*_*/ 030, /*` open*/ 025, /*a*/ 012, /*b*/ 027, /*c*/ 011, *phi*/ 0227, /*chi*/ 0201, /*psi*/ 0251, /*omega*/ 0265, /*Gamma*/ 0274, /*Delta*/ 0256, /*Theta*/ 0263, /*Lambda*/ 0302, /*Xi*/ 0267, /*Pi*/ 0276, /*Sigma*/ 00, /**/ 0306, /*Upsilon*/ 0255, /*Phi*/ 0242, /*Psi*/ 0257, /*Omega*/ 0275, /*square root*/ 0262, /*terminal sigma (was root em)*/ 0261, /*root en*/ 0327, /*>=*/ 0326, /*<=*/ 0330, /*identically equal*/ 0264, /*equation minus*/ 0277, /*approx =*/ 0272, /*approximates*/ 0331, /*not equal*/ 0354, /*right arrow*/ 0234, /*left arrow*/ 0236, /*up arrow*/ 029+0200, /*A*/ 23+0200, /*B*/ 26+0200, /*C*/ 30+0200, /*D*/ 24+0200, /*E*/ 23+0200, /*F*/ 30+0200, /*G*/ 29+0200, /*H*/ 13+0200, /*I*/ 16+0200, /*J*/ 28+0200, /*K*/ 24+0200, /*L*/ 35+0200, /*M*/ 29+0200, /*N*/ 27+0200, /*O*/ 22+0200, /*P*/ 27+0300, /*Q*/ 27+0200, /*R*/ 20+0200, /*S*/ 24+0200, /*T*/ 29+0200, /*U*/ 27+0200, /*V*/ 36+0200, /*W*/ 28+0200, /*X*/ 27+0200, /*Y*/ 23+0200, /*Z*/ 14, /*[*/ 0, /*\*/ 14, /*]*/ 0, /*^*/ 0, /*_*/ 12, /*` open*/ 17, /*a*/ 20+0200, /*b*/ 16, /*c*/ 20+0200, /*d*/ 18, /*e*/ 13+0200, /*f*/ 18+0100, /*g*/ 21+0200, /*h*/ 10+0200, /*i*/ 9+0300, /*j*/ 20+0200, /*k*/ 10+0200, /*l*/ 32, /*m*/ 21, /*n*/ 20, /*o*/ 19+0100, /*p*/ 19+0100, /*q*/ 14, /*r*/ 15, /*s*/ 12+0200, /*t*/ 21, /*u*/ 20, /*v*/ 26, /*w*/ 20, /*x*/ 18+0100, /*y*/ 17, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 13, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 29, /*1/4*/ 29, /*1/2*/ 29, /*3/4*/ 36, /*minus*/ 21, /*fi*/ 21, /*fl*/ 24, /*ff*/ /*u*/ 16, /*v*/ 24, /*w*/ 18, /*x*/ 16+0100, /*y*/ 14, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 13, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 27, /*1/4*/ 27, /*1/2*/ 27, /*3/4*/ 36, /*minus*/ 21, /*fi*/ 21, /*fl*/ 21, /*ff*/ 31, /*ffi*/ 31, /*ffl*/ 15, /*degree*/ 19, /*dagger*/ 16, /*section*/ 7, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /4*/ 28, /*1/2*/ 28, /*3/4*/ 36, /*minus*/ 22, /*fi*/ 22, /*fl*/ 23, /*ff*/ 33, /*ffi*/ 33, /*ffl*/ 15, /*degree*/ 20, /*dagger*/ 0, /*section*/ 9, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copyright*/ 0, 19, /*cent*/ }; /* Modified for Commercial II and with +, -, and = for equations */ char W4[ arrow*/ 27, /*equal*/ 27, /*multiply*/ 27, /*divide*/ 36, /*plus-minus*/ 36, /*cup (union)*/ 36, /*cap (intersection)*/ 36, /*subset of*/ 36, /*superset of*/ 36, /*improper subset*/ 36, /*improper superset*/ 34, /*infinity*/ 21, /*partial derivative*/ 36+0200, /*gradient*/ 22, /*not*/ 24, /*integral sign*/ 27, /*proportional to*/ 28, /*empty set*/ 27, /*member of*/ 27, /*plus*/ 0, 0, 0, /*box vert rule (was 2.)*/ 0, 17, /*dbl dagger*/ 42, /*right hand*/ 42, /*left hand*/ 16, /*math * struct { /***/ short word; }; struct { /*"put stack", currently gathering args*/ /***/ short prev; /*previous frame ptr, self-relative*/ /***/ short pan; /*argument number of arg being collected*/ /***/ short pa0; /*self-relative ptr oo arg0*/ #define pend 6 }; struct { /*"get stack", currently expanding macros*/ /***/ short prev; /* prev frame ptr, self-realtive*/ /***/ short mframe; /* ptr to macro definition frame*/ /***/ short mchar; /* next char relative to def. frame*/ /***/ short marg; /* 0 or# #include "m6.h" main(argc,argv) char **argv; { extern fin; int t; gf = ge = g0; pf = pe = p0; t = g0; gmax =+ t-10; t = d0; dmax =+ t-10; t = p0; pmax =+ t-10; revptr(d0,d0+2,&df,&de); if(argc>1) { fin = open(argv[1],0); control(); close(fin); } fin = dup(0); control(); } diag(m) { printf("%s\n",m); /***/ abort(); } /* abort */ 32, /*ffi*/ 32, /*ffl*/ 15, /*degree*/ 20, /*dagger*/ 0, /*section*/ 8, /*foot mark*/ 0, /*'*/ 0, /*`*/ 0, /*_*/ 0, 3, /*half nar sp*/ 0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copyright*/ 0, 19, /*cent*/ }; char W2[256-32] { /*Times Italic widths*/ 12, /*space*/ 13, /*!*/ 0, /*"*/ 0, /*#*/ 19, /*$*/ 27, /*%*/ 26, /*&*/ 11, /*' close*/ 15, /*(*/ 15, /*)*0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0, 20, /*registered*/ 20, /*copyright*/ 0, 19, /*cent*/ }; char W3[256-32] { /*Times Bold widths*/ 12, /*space*/ 13, /*!*/ 0, /*"*/ 0, /*#*/ 18, /*$*/ 28, /*%*/ 27, /*&*/ 12, /*' close*/ 16, /*(*/ 16, /*)*/ 18, /***/ 36, /*+*/ 12, /*,*/ 14, /*- hyphen*/ 12, /*.*/ 18, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+0200, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+0200, /*7*/ 19+0200, /*8*/ 19+0200,256-32] { /*Special font widths*/ 0,0, /*.=Sw+042-40*/ 13, /*"*/ 29, /*#*/ 0,0,0,0, /*.=Sw+074-40*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0, 36, /*<*/ 0, /*.=Sw+076-40*/ 36, /*>*/ 0, /*.=Sw+100-40*/ 36, /*@*/ 0,0,0,0,0,0,0, /*.=Sw+134-40*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0, 15, /*\\*/ 0, /*.=Sw+136-40*/ 15, /*^*/ 18, /*_ underrule*/ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0, 14, /*{*/ 0, /*.=Sw+175-40*/ 14, /*}*/ 15, /*~*/ 0, /*.=Sw+220-40*/ 0,0,0,0,0,0,0,0, */ 41, /*bell system sign*/ 9, /*or*/ 27, /*circle*/ 9, /*left top (of big curly)*/ 9, /*left bottom*/ 9, /*right top*/ 9, /*right bot*/ 9, /*left center of big curly bracket*/ 9, /*right center of big curly bracket*/ 9, /*bold vertical*/ 9, /*left floor (left bot of big sq bract)*/ 9, /*right floor (rb of ")*/ 9, /*left ceiling (lt of ")*/ 9 }; /*right ceiling (rt of ")*/ ptr to next arg char reltive to gf*/ /***/ short ga0; /* arg0 ptr self-rel*/ }; struct { /*"definition stack"*/ /***/ short prev; /* prev frame ptr, self-relative*/ /***/ short dswitch; /* builtin func code, neg for dead definition*/ /***/ short dtext; /* definition text prt rel to df*/ /***/ short dident; /* first char of identifier naming def*/ #define dend 6 }; char metas[]; #define lquote metas[0] #define rquote metas[1] #define sharp metas[2] #define colon metas[3] #define semi metas[4] #define com# #include "m6.h" control() { /***/ for (;;) { get(); if(c==0 && lg>0) { popget(); trash(); rescan = 1; } else { if(!rescan) put(); else if(lq>0) { if(c==lquote) { lq++; put(); } else if(c==rquote || c==0) { lq--; if(lq>0 || l9>0) put (rquote); } else put(); } else if(l9>0) if(c==colon||c==0||c==semi) if(--l9<=0) endcall(); else put(); else { if(c==sharp) l9++; else if(c==lquote) lq++; put(); / 16, /***/ 36, /*+*/ 11, /*,*/ 13, /*- hyphen*/ 11, /*.*/ 9, /*/*/ 19+0200, /*0*/ 19+0200, /*1*/ 19+0200, /*2*/ 19+0200, /*3*/ 19+0200, /*4*/ 19+0200, /*5*/ 19+0200, /*6*/ 19+0200, /*7*/ 19+0200, /*8*/ 19+0200, /*9*/ 11, /*:*/ 11, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 20, /*?*/ 0, /*@*/ 25+0200, /*A*/ 24+0200, /*B*/ 26+0200, /*C*/ 27+0200, /*D*/ 23+0200, /*E*/ 21+0200, /*F*/ 27+0200, /*G*/ 29+0200, /*H*/ 14+0200, /*I*/ 16+0200, /*J*/ 28+0200, /*K*/ 24+0200, /*L*/ 34+0200, /*M*/ 27+0200, /*N*/ 27+0 /*9*/ 13, /*:*/ 13, /*;*/ 0, /*<*/ 36, /*=*/ 0, /*>*/ 22, /*?*/ 0, /*@*/ 28+0200, /*A*/ 26+0200, /*B*/ 26+0200, /*C*/ 29+0200, /*D*/ 25+0200, /*E*/ 23+0200, /*F*/ 28+0200, /*G*/ 32+0200, /*H*/ 16+0200, /*I*/ 21+0200, /*J*/ 28+0200, /*K*/ 25+0200, /*L*/ 36+0200, /*M*/ 30+0200, /*N*/ 29+0200, /*O*/ 25+0200, /*P*/ 29+0300, /*Q*/ 28+0200, /*R*/ 23+0200, /*S*/ 25+0200, /*T*/ 29+0200, /*U*/ 27+0200, /*V*/ 36+0200, /*W*/ 27+0200, /*X*/ 28+0200, /*Y*/ 27+0200, /*Z*/ 12, /*[*/ 0, /*\*/ 12, /*]*/ 0, /*^*/ 0,0,0,0,0,0,0,0, 17, /*section*/ 0, /*.=Sw+222-40*/ 10, /*acute accent*/ 10, /*grave accent*/ 18, /*underrule*/ 15, /*slash (longer)*/ 0, /**/ 0, /**/ 24, /*alpha*/ 23+0300, /*beta*/ 23+0100, /*gamma*/ 19+0200, /*delta*/ 18, /*epsilon*/ 18+0300, /*zeta*/ 23+0100, /*eta*/ 19+0200, /*theta*/ 13, /*iota*/ 21, /*kappa*/ 22+0200, /*lambda*/ 25+0100, /*mu*/ 20, /*nu*/ 20+0300, /*xi*/ 20, /*omicron*/ 27, /*pi*/ 21+0100, /*rho*/ 27, /*sigma*/ 20, /*tau*/ 21, /*upsilon*/ 25+0300, /*phi*/ 22+0100, echo == installing formatters cp nsuftab /usr/lib/nsuftab cp nroff /usr/bin/nroff : cp troff /usr/bin/troff : rm troff rm nsuftab nroff rm *.o ma metas[5] #define dollar metas[6] #define NMETA 7 char one[]; int rescan; int traceflag; int trashflag; /* nonzero when dead def'n exist*/ int lp; /* arg collection level (out level)*/ int lg; /*input level (get level) */ int lq; /*quote level*/ int l9; /*apparent call level within arg 9*/ char c; /*current input character*/ char *pf; /*put stack frame ptr*/ char *pe; /*put stack end*/ char *pmax; /*top of put stack*/ char p0[]; /*put stack*/ char *gf; /*get stack frame ptr*/ char *ge; } else { if(c==sharp) begincall(); else if(c==lquote) lq++; else if(lp>0) { if(c==colon||c==0||c==semi) endcall(); else if(c==comma) newarg(); else put(); } else if(c==0) return; /* lg=lp=lq=0 */ else put(); } } } } endcall() { char *pt, *p; rescan = c!=semi; newarg(); pushget(); pt = &pf->pa0; ge = move(pt,&gf->ga0,pe-pt); if(ge>gmax) diag("Call stack overflow"); if(traceflag) dotrace(); p = finddef(0); setscan(p); popput(); lp--; func200, /*O*/ 22+0200, /*P*/ 27+0300, /*Q*/ 27+0200, /*R*/ 20+0200, /*S*/ 23+0200, /*T*/ 28+0200, /*U*/ 25+0200, /*V*/ 36+0200, /*W*/ 24+0200, /*X*/ 24+0200, /*Y*/ 25+0200, /*Z*/ 13, /*[*/ 0, /*\*/ 13, /*]*/ 0, /*^*/ 0, /*_*/ 11, /*` open*/ 19, /*a*/ 18+0200, /*b*/ 15, /*c*/ 18+0200, /*d*/ 16, /*e*/ 11+0200, /*f*/ 17+0100, /*g*/ 19+0200, /*h*/ 9+0200, /*i*/ 9+0300, /*j*/ 19+0200, /*k*/ 9+0200, /*l*/ 28, /*m*/ 19, /*n*/ 18, /*o*/ 17+0100, /*p*/ 18+0100, /*q*/ 13, /*r*/ 14, /*s*/ 10+0200, /*t*/ 19, 0, /*_*/ 12, /*` open*/ 19, /*a*/ 19+0200, /*b*/ 16, /*c*/ 19+0200, /*d*/ 17, /*e*/ 13+0200, /*f*/ 18+0100, /*g*/ 22+0200, /*h*/ 12+0200, /*i*/ 12+0300, /*j*/ 23+0200, /*k*/ 12+0200, /*l*/ 32, /*m*/ 22, /*n*/ 18, /*o*/ 20+0100, /*p*/ 19+0100, /*q*/ 15, /*r*/ 17, /*s*/ 13+0200, /*t*/ 21, /*u*/ 19, /*v*/ 27, /*w*/ 21, /*x*/ 19+0100, /*y*/ 17, /*z*/ 0, /*{*/ 2, /*|*/ 0, /*}*/ 0, /*~*/ 6, /*narrow space*/ 14, /*hyphen*/ 27, /*bullet*/ 27, /*square*/ 36, /*3/4 em*/ 18, /*rule*/ 28, /*1/*chi*/ 24+0300, /*psi*/ 25, /*omega*/ 24+0200, /*Gamma*/ 26+0200, /*Delta*/ 28+0200, /*Theta*/ 28+0200, /*Lambda*/ 27+0200, /*Xi*/ 29+0200, /*Pi*/ 25+0200, /*Sigma*/ 0, /**/ 28+0200, /*Upsilon*/ 29+0200, /*Phi*/ 32+0200, /*Psi*/ 36+0200, /*Omega*/ 30, /*square root*/ 18+0100, /*terminal sigma*/ 18, /*root en*/ 36, /*>=*/ 36, /*<=*/ 36, /*identically equal*/ 27, /*minus*/ 36, /*approx =*/ 36, /*approximates*/ 36, /*not equal*/ 36, /*right arrow*/ 36, /*left arrow*/ 18, /*up arrow*/ 18, /*downcc -m -o m6 m6?.c /*get stack end*/ char *gmax; /*get stack limit*/ char g0[]; /*get stack*/ char *df; /*definition stack frame ptr*/ char *de; /*def stack end*/ char *dmax; /*def stack limit*/ char d0[]; /*def stack*/ char dummy[]; /*dummy empty macro*/ /***/ char *lookup(), *move(), *arg(); tion(p->dswitch); } begincall() { lp++; pushput(); pe = pf+pend; pf->pan = pf->pa0 = 0; } newarg() { char *p; if(++pf->pan>=9) if(c==comma) l9++; *pe++ = 0; /***/ pe = (pe+1)&~1; p = &pf->pa0; while(p->word!=0) p =+ p->word; p->word = pe - p; *pe++ = *pe++ = 0; } setscan(p) char *p; { gf->mchar = (gf->mframe = p)->dtext; gf->marg = 0; } # #include "m6.h" char * finddef(n) { char *p; if((p = lookup(arg(n)))==0) if((p = lookup(""))==0) diag("Software error"); return(p); } char * lookup(s) { char *dt; dt = df; while(dt>d0) { if(dt->dswitch>=0 && comp(s,&dt->dident)) return(dt); dt =+ dt->prev; } return(0); } comp(s,t) char *s, *t; { for(;*s++ == *t;t++) if(*t==0) return(1); return(0); } remove(n) { char *p; if(p = lookup(arg(n))) if(p>d0+2) { trashflag++; p->dswitch = -1; } } trash() { char *p,*q,*r; i pf =+ pf->word; if(pf->prev&1) { pe--; /***/ pf->prev =& ~1; } if(pfword = df-de; df = de; de =+2; } put() { if(lp>0) { *pe++ = c; if(pe>pmax) diag("Arg collection overflow"); } else putchar(c); } get() { /***/ register char *p; /***/ register n; if(lg==0) c = getchar(); else while(1) { if(gf->marg!=0) { if((c = gf[gf->marg++])==0) gf->marg = 0; else return; } c = (p = gf->mframe)[gf->mchar++]; case 35: traceflag = comp(arg(1),one); return; } } } (n=decbin(1))<=0) return; p = df; for(i=1;;) { if(p<=d0) return; if(p->dswitch>=0) if(i++>=n) break; p =+ p->prev; } for(p = &p->dident;c = *p++;) put(); } copy() { /***/ register char *p; p = finddef(1); remove(2); newdef(p->dswitch); setdef(arg(2),p+p->dtext); } go(n) { if(comp(arg(1),one)) { popget(); if(lg>0) if(n==26) popget(); else setscan(gf->mframe); /* gobk=27 */ } } size() { /***/ register i; /***/ register char *p; i = 0; p = arg(1); while(*p++ != 0) i++;,8, 'l','t',0,0, 0,10, 0,5, 0,8, 'n','e',0,0, 0,10, 0,6, 0,8, 'l', 'e',0,0, 0,10, 0,21, 0,9, 'd','e','f',0, 0,10, 0,20, 0,8, 'i','f',0, 0,0 }; /***/short dummy[] { 0, 0, 6, '$0', 0 }; char metas[] { '<', '>', '#', ':', ';', ',', '$' }; int rescan 1; int traceflag 0; int trashflag 0; char one[] { '1',0 }; f(lg>0) return; while(df->dswitch<0) { de = df; df =+ df->prev; trashflag--; } if(trashflag<=0) return; /***/ de = (de+1)&~1; revptr(de,df,&p,&q); q = p; for(;p->word!=0;p=+r->word) { r = p; if(p->dswitch>=0) { r = q; q = move(p,q,p->word); } } q->word = 0; revptr(d0,d0+2,&df,&de); } revptr(p,q,np,nq) char *p, *q, **np, **nq; { /***/ register t; p->word = 0; while((t = q->word)!=0) { q->word = p-q; p = q; q =+ t; if(qdmax) diag("Software error"); } * if(c!=dollar) return; n = p[gf->mchar] - '0'; if(n<0 || n>9) return; ++gf->mchar; gf->marg = arg(n) - gf; } } # #include "m6.h" doif() { /***/ register i; /***/ register short *p; char *arg(); i = 1; while(!comp(arg(i),one)) if((i =+ 2)>8) return; p = arg(i+1) - 2; ge = move(p,&gf->ga0,p->word+1); setscan(dummy); } bindec(n) { if(n == 0) return; bindec(n/10); *ge++ = (n%10) + '0'; } result(n) { /***/ register char *p; setscan(dummy); ge = 2 + (p = &gf->ga0); if(n<0) { *ge++ = '-'; n = -n; } if(n==0) *ge++ = '0'; else bindec(n); *ge++ = 0; /***/ ge = (ge+1)&~1; p->word = ge - p; *ge+ result(i); } meta() { char d; /***/ register i; char *arg(); if((d = *arg(2))!=0) { for(i=0;i0 && *s!=0) s++; while(arg3-->0) { if((*de++ = *s++)==0) return; if(de>dmax) diag("No room for substr"); } *de++ = 0; } cp m6 /usr/bin/m6 rm m6 *.o np = p; *nq = q; } char * move(from,to,count) char *from, *to; { while(count-->0) *to++ = *from++; return(to); } # #include "m6.h" define() { remove(1); newdef(decbin(3)); setdef(arg(1),arg(2)); } newdef(n) { pushdef(); de = &df[df->dtext = dend]; if((df->dswitch = n)<0) trashflag++; } setdef(s1,s2) { copydef(s1); df->dtext = de -df; copydef(s2); } copydef(s) /***/ register char *s; { while(*de++ = *s++) if(de>dmax) diag("Definition table overflow"); } char * arg(n) { char *p; p = &gf->ga0; while(--n>=0 && p->word!=0) p =+ p->word; return(p->word!=0?p+2:p); } function(n) { if(n==0) ; el+ = *ge++ = 0; } binop(code) { int r1,r2; int r,t; int arg1, arg2; arg1 = decbin(1); arg2 = decbin(2); if(code < 7) /* relationals */ result((code & ((arg1ga0 = 0; return; case 13: /*#define PSIZE 1000 #define GSIZE 2000 #define DSIZE 5000 int pmax PSIZE; char p0[PSIZE]; int gmax GSIZE; char g0[GSIZE]; int dmax DSIZE; char d0[DSIZE] { 0,0, 0,8, 0,0, 0,6, 0,0, /*null*/ 0,12, 0,35, 0,11, 't','r','a','c','e',0, 0,12, 0,23, 0,10, 'w','a','r','n',0,0, 0,12, 0,22, 0,10, 'c','o','p','y',0,0, 0,12, 0,32, 0,11, 'q','u','o','t','e',0, 0,14, 0,33, 0,12, 's','e','r','i','a','l',0,0, 0,12, 0,34, 0,10, 'l','i','s','t',0,0, 0,12, 0,24, 0,10, 's','i','z','e',0,0, 0,14, 0,25, 0,12, 's','2           # #include "m6.h" pushget() { /***/ ge = (ge+1)&~1; ge->word = gf-ge; gf = ge; ge =+2; ++lg; } dotrace() { char *arg(); /***/ register i,j; printf("\n%d %c%s",lg,sharp,arg(0)); for(j=9;j>0&&*arg(j)==0;j--); for(i=1;i<=j;i++) printf("%c%c%s%c",comma,lquote,arg(i),rquote); printf("%c\n",c); } popget() { ge = gf; gf =+ gf->word; --lg; if(gfprev =| 1; pe++; } pe->word = pf-pe; pf = pe; pe =+2; } popput() { pe = pf; se if(1<=n && n<=13) binop(n); else { switch(n) { case 20: doif(); return; case 21: define(); return; case 22: copy(); return; case 23: meta(); return; case 24: size(); return; case 25: substr(); return; case 26: case 27: go(n); return; case 28: remove(1); return; case 29: dnl(); return; case 32: quote(); return; case 33: result(finddef(1)->dswitch); return; case 34: list(); return; exp */ r = 1; while(arg2-->0) r =* arg1; result(r); if(arg2<-1) gf->ga0 = 0; } } decbin(i) { /***/ register char *s; char t; /***/ register n; if(t = (*(s = arg(i))=='-')) s++; n = 0; while(*s>='0' && *s<='9') n = 10*n + *s++ - '0'; return(t?-n:n); } dnl() { /***/ register char d; d = 0; while(d=getchar()) if(d=='\n') return; } quote() { /***/ register char *p,*s; p = finddef(1); s = &p[p->dtext]; while(c = *s++) put(); } list() { /***/ register n,i; /***/ register char *p; if(u','b','s','t','r',0,0, 0,10, 0,26, 0,8, 'g','o',0,0, 0,12, 0,27, 0,10, 'g','o','b','k',0,0, 0,10, 0,28, 0,9, 'd','e','l',0, 0,10, 0,29, 0,9, 'd','n','l',0, 0,10, 0,7, 0,9, 's','e','q',0, 0,10, 0,8, 0,9, 's','n','e',0, 0,10, 0,9, 0,9, 'a','d','d',0, 0,10, 0,10, 0,9, 's','u','b',0, 0,10, 0,11, 0,9, 'm','p','y',0, 0,10, 0,12, 0,9, 'd','i','v',0, 0,10, 0,13, 0,9, 'e','x','p',0, 0,10, 0,1, 0,8, 'g','t',0,0, 0,10, 0,2, 0,8, 'e','q',0,0, 0,10, 0,3, 0,8, 'g','e',0,0, 0,10, 0,4, 02LF@?93->82,=71+<60*;5/):4.('!& %$#"2q|vpoic]nhb\mga[lf`Zke_Yjd^XWQKEVPJDUOICTNHBSMGAR2{uztys~xr}w22  23D>82C=71B<60/)#.("-'!,& +%*$   2oictnhbsmgarlf`_YSM^XRL]WQK\VPJ[UOIZTNHGA;5F@:4E?92}|{zy~xwqkevpjdu2221+%60*$5/)#4.("3-'!2,&      2hga[Uf`ZTe_YSd^XRc]WQb\VPOIC=NHB<MGA;LF@:KE?9JD>872ysm~xrl}wqk|vpj{uoiztn22 2*;5/):4.('!& %$#"    2f`Zke_Yjd^XWQKEVPJDUOICTNHBSMGARLF@?93->82,=71+<602{uztys~xr}wq|vpoic]nhb\mga[l222("-'!,& +%*$     2M^XRL]WQK\VPJ[UOIZTNHGA;5F@:4E?93D>82C=71B<60/)#.2}|{zy~xwqkevpjduoictnhbsmgarlf`_YS222!2,&      2]WQb\VPOIC=NHB<MGA;LF@:KE?9JD>871+%60*$5/)#4.("3-'2ysm~xrl}wqk|vpj{uoiztnhga[Uf`ZTe_YSd^XRc222$#"     2DUOICTNHBSMGARLF@?93->82,=71+<60*;5/):4.('!& %2ztys~xr}wq|vpoic]nhb\mga[lf`Zke_Yjd^XWQKEVPJ2{u22     2TNHGA;5F@:4E?93D>82C=71B<60/)#.("-'!,& +%*$2y~xwqkevpjduoictnhbsmgarlf`_YSM^XRL]WQK\VPJ[UOIZ2}|{z22  2;LF@:KE?9JD>871+%60*$5/)#4.("3-'!2,&    2wqk|vpj{uoiztnhga[Uf`ZTe_YSd^XRc]WQb\VPOIC=NHB<MGA2ysm~xrl}22    293->82,=71+<60*;5/):4.('!& %$#" 2poic]nhb\mga[lf`Zke_Yjd^XWQKEVPJDUOICTNHBSMGARLF@?2{uztys~xr}wq|v22  22C=71B<60/)#.("-'!,& +%*$   2nhbsmgarlf`_YSM^XRL]WQK\VPJ[UOIZTNHGA;5F@:4E?93D>82}|{zy~xwqkevpjduoict2220*$5/)#4.("3-'!2,&      2Uf`ZTe_YSd^XRc]WQb\VPOIC=NHB<MGA;LF@:KE?9JD>871+%62ysm~xrl}wqk|vpj{uoiztnhga[222):4.('!& %$#"     2e_Yjd^XWQKEVPJDUOICTNHBSMGARLF@?93->82,=71+<60*;5/2{uztys~xr}wq|vpoic]nhb\mga[lf`Zk222'!,& +%*$     2L]WQK\VPJ[UOIZTNHGA;5F@:4E?93D>82C=71B<60/)#.("-2|{zy~xwqkevpjduoictnhbsmgarlf`_YSM^XR2}22      2\VPOIC=NHB<MGA;LF@:KE?9JD>871+%60*$5/)#4.("3-'!2,&2ysm~xrl}wqk|vpj{uoiztnhga[Uf`ZTe_YSd^XRc]WQb222#"     2CTNHBSMGARLF@?93->82,=71+<60*;5/):4.('!& %$2ys~xr}wq|vpoic]nhb\mga[lf`Zke_Yjd^XWQKEVPJDUOI2{uzt22    2A;5F@:4E?93D>82C=71B<60/)#.("-'!,& +%*$ 2xwqkevpjduoictnhbsmgarlf`_YSM^XRL]WQK\VPJ[UOIZTNHG2}|{zy~22 2:KE?9JD>871+%60*$5/)#4.("3-'!2,&     2vpj{uoiztnhga[Uf`ZTe_YSd^XRc]WQb\VPOIC=NHB<MGA;LF@2ysm~xrl}wqk|22      2 8 2 , = 7 1 + < 6 0 * ; 5 / ) : 4 . ( ' !   &   %    $    #    "        2 ] n h b \ m g a [ l f ` Z k e _ Y j d ^ X W Q K E V P J D U O I C T N H B S M G A R L F @ ? 9 3 - >2 { u z t  y s ~ x r } w q | v p o i c2 2! !! 2!1!B!<!6!0!/!)!#!!.!(!"!!-!'!!!!,!&! !!+!%!!!*!$!!!!! !!!! !!!! !!!!!!! !!!2!m!g!a!r!l!f!`!_!Y!S!M!^!X!R!L!]!W!Q!K!\!V!P!J![!U!O!I!Z!T!N!H!G!A!;!5!F!@!:!4!E!?!9!3!D!>!8!2!C!=!72!!!!!!!!!!!!!}!!!!|!!!!{!!!!z!!!!y!!!~!x!w!q!k!e!v!p!j!d!u!o!i!c!t!n!h!b!s2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2!"!!!"!!!"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!2"/")"#"4"."("""3"-"'"!"2","&" """" """" """" """" """" """"""!!""!!"!!2"T"e"_"Y"S"d"^"X"R"c"]"W"Q"b"\"V"P"O"I"C"="N"H"B"<"M"G"A";"L"F"@":"K"E"?"9"J"D">"8"7"1"+"%"6"0"*"$"52"""""""""""""""""""""y"s"m"~"x"r"l"}"w"q"k"|"v"p"j"{"u"o"i"z"t"n"h"g"a"["U"f"`"Z2""""""""""""""""""""""""""""""""""""""""""""""""""2""""""""""""""""""""""""""""""""""""""""""""""""""2#(#'#!###&# ###%####$#########"##### #"###"# ##"# ##"# #""# #"""2#d#^#X#W#Q#K#E#V#P#J#D#U#O#I#C#T#N#H#B#S#M#G#A#R#L#F#@#?#9#3#-#>#8#2#,#=#7#1#+#<#6#0#*#;#5#/#)#:#4#.2########{#u###z#t###y#s##~#x#r##}#w#q##|#v#p#o#i#c#]#n#h#b#\#m#g#a#[#l#f#`#Z#k#e#_#Y#j2##################################################2##################################################2$&$ $$+$%$$$*$$$$$$$ $$$$ $$$$ $$$$$$$ $$$$ $$###############2$K$\$V$P$J$[$U$O$I$Z$T$N$H$G$A$;$5$F$@$:$4$E$?$9$3$D$>$8$2$C$=$7$1$B$<$6$0$/$)$#$$.$($"$$-$'$!$$,2$$${$$$$z$$$$y$$$~$x$w$q$k$e$v$p$j$d$u$o$i$c$t$n$h$b$s$m$g$a$r$l$f$`$_$Y$S$M$^$X$R$L$]$W$Q2$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}$$$$|$2$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$2% %%%% %%%% %%%% %%%% %%%%%%$$%%$$%$$$%$$$%$$$%$$$$$$$$2%I%C%=%N%H%B%<%M%G%A%;%L%F%@%:%K%E%?%9%J%D%>%8%7%1%+%%%6%0%*%$%5%/%)%#%4%.%(%"%3%-%'%!%2%,%&% %%%2%%y%s%m%~%x%r%l%}%w%q%k%|%v%p%j%{%u%o%i%z%t%n%h%g%a%[%U%f%`%Z%T%e%_%Y%S%d%^%X%R%c%]%W%Q%b%\%V%P%O