\ uudecode V1.1 A Forth version of the Unix utility \ @(#)uudecode.seq 1.1 21:55:29 11/15/94 EFC \ Typical usage: \ s" file.uu" uudecode \ This program ignores the file mode number that follows the word begin. \ This is an ANS Forth program requiring: \ 1. The File word set \ 2. The word COMPARE in the String word set. \ (c) Copyright 1994 Everett F. Carter. Permission is granted by the \ author to use this software for any application provided this \ copyright notice is preserved. \ (c) Copyright 1997,2008 HanSoft & Partners - 4tH version INCLUDE lib/compare.4th \ buffers and I/O handles 82 string inbuf 82 string outbuf VARIABLE obp 0 obp ! \ write, putb : write ( n -- ) \ write n bytes out out-handle outbuf swap type ; : putb ( b -- ) \ put a byte to the output buffer outbuf obp @ + C! \ write if its nearly full obp @ 1+ DUP OBP ! DUP 74 > IF write 0 obp ! ELSE DROP THEN ; : flushb ( -- ) obp @ DUP 0> IF write 0 obp ! ELSE DROP THEN ; [HEX] \ dec, outdec : dec ( c -- c ) \ single character decode 20 - 3F AND ; [DECIMAL] : outdec ( bp n -- ) \ output group of 3 bytes from bp OVER DUP C@ DEC 4 * SWAP 1+ C@ DEC 16 / OR putb DUP 1 > IF OVER 1+ DUP C@ dec 16 * SWAP 1+ C@ dec 4 / OR putb THEN 2 > IF 2 + DUP C@ dec 64 * SWAP 1+ C@ dec OR putb ELSE DROP THEN ; \ out-loop : out-loop ( n -- ) \ output until n is zero DUP 0> IF inbuf 1+ SWAP BEGIN OVER OVER outdec 3 - SWAP 4 + SWAP DUP 0 <= UNTIL DROP THEN DROP ; \ Find the header line : find_head ( -- ) BEGIN REFILL 0= ABORT" No begin line" 0 PARSE-WORD inbuf PLACE S" begin" inbuf COUNT 5 MIN COMPARE 0= UNTIL ; \ Parse the header line : $<< ( addr n1 n2) \ shift string left by indicated amount swap over - ( a n c-n) >r over swap ( a a n) chars + r> ( a a+n c-n) rot place ( --) ; : parse_head inbuf count -trailing over over 6 $<< \ next 3 chars are octal number 4 $<< \ now inbuf is the output file name ; : (disk) ( m a n -- ) rot ( a n m) open error? abort" Cannot open file" \ issue message if error use ; \ ====== everything above here could be made private ========================= : uudecode ( -- ) find_head parse_head output inbuf count (disk) BEGIN 0 REFILL 0 PARSE-WORD inbuf PLACE DUP IF DROP DROP inbuf C@ dec DUP 0> THEN WHILE out-loop REPEAT DROP flushb ; : Convert argn 2 <> \ check arguments abort" Usage: UUDECODE [file]" input 1 args (disk) \ open input file uudecode \ read file ; Convert