/* UUENCODE REXX: Pipeline filter to uuencode */ Signal On Error Signal On Novalue Signal On Syntax Parse Arg file, /* File name to imbed. */ text . /* Keyword "TEXT" is allowed. */ /*-------------------------------------------------------------------*/ /* If the file is in text format, rather than binary, it will need */ /* to have its records delimited with line-feeds before the file is */ /* encoded, to preserve the record structure. It will also need to */ /* be converted from EBCDIC to ASCII before being encoded, so that */ /* the recipient gets ASCII when he decodes the file. */ /* */ /* Whether the file is binary or text, it needs to be blocked into */ /* 45-character chunks, each of which will become a 60-byte record */ /* after 3-to-4 expansion. */ /*-------------------------------------------------------------------*/ If Translate(text) == 'TEXT' /* ASCII translation wanted? */ Then blockit =, /* Yes, set up needed stages: */ 'xlate 1-* e2a |', /* Translate to ASCII. */ 'block 45 linend 0A |' /* Block with line-feed. */ Else blockit =, /* Translation not specified, */ 'fblock 45 |' /* so don't insert line-feed. */ /*-------------------------------------------------------------------*/ /* The uuencode process originated in the need to exchange binary */ /* files between UNIX systems. The technique it uses is to recode */ /* the records using only "printable" ASCII characters. Three 8-bit */ /* bytes are split into four 8-bit bytes, each with 2 high-order */ /* zero bits. Thus, each byte has a value between 00 and 3F. Then */ /* an ASCII space (x'20') is added to each byte to make it into a */ /* printable ASCII character between 20 and 5F. */ /* */ /* The following translate table is designed to add the ASCII space */ /* character, while allowing for subsequent translation from EBCDIC */ /* to ASCII. Thus, x'00' would be translated to x'40' which would */ /* become x'20' when the uuencoded file passes through an EBCDIC-to- */ /* ASCII gateway. Similarly, x'01' would be translated to x'5A', */ /* which becomes x'21' when it passes through such a gateway. This */ /* procedure is modified in the case of x'00', however, to prevent */ /* the loss of trailing blanks. Instead of being translated to */ /* blank, x'00' is translated to x'79', which the gateway translates */ /* to x'60'. As only the low-order 6 bits are used in decoding the */ /* encoded data, x'60' is equivalent to x'20'. */ /* */ /* I am indebted to John Fisher, of RPI, for many of the ideas used */ /* in this filter. */ /*-------------------------------------------------------------------*/ addspace = , /* Add ASCII space (x'20'). */ '00 40 01 5A 02 7F 03 7B 04 5B 05 6C 06 50 07 7D', '08 4D 09 5D 0A 5C 0B 4E 0C 6B 0D 60 0E 4B 0F 61', '10 F0 11 F1 12 F2 13 F3 14 F4 15 F5 16 F6 17 F7', '18 F8 19 F9 1A 7A 1B 5E 1C 4C 1D 7E 1E 6E 1F 6F', '20 7C 21 C1 22 C2 23 C3 24 C4 25 C5 26 C6 27 C7', '28 C8 29 C9 2A D1 2B D2 2C D3 2D D4 2E D5 2F D6', '30 D7 31 D8 32 D9 33 E2 34 E3 35 E4 36 E5 37 E6', '38 E7 39 E8 3A E9 3B AD 3C E0 3D BD 3E 5F 3F 6D', '00 79' /* Exception to the rule. */ /*-------------------------------------------------------------------*/ /* Each data record produced by uuencode (except for the last, which */ /* may be short) contains 45 characters from the input file. These */ /* are expanded to 60 printable characters. The first byte of each */ /* data record is a binary number specifying the number of input */ /* characters represented in the record. Thus, for 45-byte data */ /* records, the first character is (in EBCDIC) "M" (x'D4'), which */ /* will become x'2D' when it goes through an EBCDIC-to-ASCII gateway.*/ /*-------------------------------------------------------------------*/ beginline = 'begin 0600' file /* Canonical uuencode header. */ 'CALLPIPE (endchar ? name UUENCOD1)', '*: |', /* Read from pipeline. */ blockit, /* Reblock to 45-byte chunks. */ 'd: locate 45 |', /* Last record may be short. */ 'vchar 6 8 |', /* Recode, 3 bytes to 4. */ 'change //M/ |', /* Prepend data length (45). */ 'f: fanin |', /* Pick up last data record. */ 'xlate 1-*' addspace '|', /* Make data printable EBCDIC. */ 'preface var beginline |', /* Prepend canonical header. */ 'append literal `|', /* Indicate end of data. */ 'append literal end|', /* Indicate end of file. */ '*:', /* Write to pipeline. */ '?', 'd: |', /* Process last data record: */ 'c: count bytes |', /* Calculate its size. */ 'copy |', /* (To unblock "count".) */ 'spec 1-* 1 x0000 next |', /* Compensate for "vchar". */ 'vchar 6 8 |', /* Recode, 3 bytes to 4. */ 'vchar 32 32 |', /* Truncate compensation. */ 's: spec', /* Complete the formatting: */ 'select 1', /* get record size; */ '1-* d2c 1.1 right', /* make it one byte binary; */ 'select 0', /* get rest of record; */ '1-* 2 |', /* and put it next. */ 'f:', /* Send back to mainline. */ '? c: | s:' /* Count of bytes in last rec. */ Error: Exit RC*(RC<>12) /* RC = 0 if end-of-file. */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Error Subroutines */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ Novalue: Say 'Novalue condition for symbol' Condition('D') 'on line' , Sigl':' Sourceline(Sigl) Exit 20 /* Exit with error setting. */ Syntax: Say 'Syntax error on line' Sigl':' Sourceline(Sigl) Say 'Error was:' Errortext(RC) Exit 24 /* Exit with error setting. */