home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / draco / draco-1.ark / UUDECODE.DRC < prev    next >
Internet Message Format  |  1986-11-12  |  7KB

  1. Received: from seismo.css.gov by AMSAA.ARPA id a013221; 15 Oct 86 18:28 EDT
  2. Received: from ubc-vision.UUCP by seismo.CSS.GOV (5.54/1.14)
  3.     id AA09297; Wed, 15 Oct 86 18:29:30 EDT
  4. Received: by ubc-vision.UUCP id AA09634; Wed, 15 Oct 86 12:50:40 pdt
  5. Received: by pembina.alberta.UUCP (4.12/3.14)
  6.     id AA10116; Wed, 15 Oct 86 11:59:50 mdt
  7. Received: by myrias.UUCP (4.12/4.7)
  8.     id AA10621; Wed, 15 Oct 86 11:46:15 mdt
  9. Date: Wed, 15 Oct 86 11:40:07 mdt
  10. From: ubc-vision!alberta!myrias!cg@seismo.CSS.GOV (Chris Gray)
  11. Message-Id: <8610151740.AA28641@myrias.UUCP>
  12. To: towson@amsaa.arpa
  13. Subject: UUDECODE.DRC
  14.  
  15. #util.g
  16.  
  17. /*
  18.  * uudecode.drc
  19.  *      Decode an ASCII representation into a binary file. This is the
  20.  *      reverse of uuencode. The single parameter is the name of the
  21.  *      uuencoded file to decode. The input file contains the name to use
  22.  *      for the binary file created. It can contain more than one file, even
  23.  *      though uuencode can't directly produce such a beast.
  24.  */
  25.  
  26. word
  27.     BUFF_SIZE = 10000,                  /* nice and big */
  28.     MAX_BYTES = 45,                     /* maximum bytes per encoded line */
  29.     MAX_LINE = 100;                     /* maximum input line we use */
  30.  
  31. channel input text Chin;
  32. channel output binary Chout;
  33. file(BUFF_SIZE) InputFile, OutputFile;
  34. [MAX_LINE] char LineBuff;               /* buffer for input line */
  35. word LineMax, LinePos;                  /* count/position in input line */
  36. bool Eof;
  37.  
  38. /*
  39.  * getLine -
  40.  *      Read an input line into LineBuff/LineMax.
  41.  */
  42.  
  43. proc getLine()void:
  44.    char ch;
  45.  
  46.    LineMax := 0;
  47.    while read(Chin; ch) do
  48.        if LineMax ~= MAX_LINE then
  49.            LineBuff[LineMax] := ch;
  50.            LineMax := LineMax + 1;
  51.        fi;
  52.    od;
  53.    if ioerror(Chin) = CH_MISSING then
  54.        readln(Chin;);
  55.    else
  56.        Eof := true;
  57.    fi;
  58.    LinePos := 0;
  59. corp;
  60.  
  61. /*
  62.  * getWord -
  63.  *      Peel an input word off of the input line.
  64.  */
  65.  
  66. proc getWord()*char:
  67.    *char p;
  68.  
  69.    p := &LineBuff[LinePos];
  70.    while LinePos < LineMax and LineBuff[LinePos] ~= ' ' do
  71.        LinePos := LinePos + 1;
  72.    od;
  73.    LineBuff[LinePos] := '\e';
  74.    LinePos := LinePos + 1;
  75.    p
  76. corp;
  77.  
  78. /*
  79.  * isWord -
  80.  *      Compare two words for equality.
  81.  */
  82.  
  83. proc isWord(*char p, q)bool:
  84.  
  85.    while p* = q* and p* ~= '\e' do
  86.        p := p + 1;
  87.        q := q + 1;
  88.    od;
  89.    p* = q*
  90. corp;
  91.  
  92. /*
  93.  * decodeChar -
  94.  *      Decode a single character to a six bit value.
  95.  */
  96.  
  97. proc decodeChar(char ch)byte:
  98.  
  99.    if ch >= ' ' + 1 and ch <= ' ' + ((1 << 6) - 1) then
  100.        ch - ' '
  101.    elif ch = '`' then
  102.        0
  103.    else
  104.        writeln("Bad encoded character: ", ch - '\e');
  105.        close(Chout);
  106.        close(Chin);
  107.        exit(1);
  108.        0
  109.    fi
  110. corp;
  111.  
  112. /*
  113.  * decodeFile -
  114.  *      Decode the file given already opened descriptors, etc.
  115.  */
  116.  
  117. proc decodeFile()void:
  118.    [MAX_BYTES] byte buff;
  119.    word count, i, j;
  120.    byte b1, b2, b3, b4;
  121.  
  122.    /* fetch and decode lines until we find one starting with "end" */
  123.    while
  124.        getLine();
  125.        not isWord(getWord(), "end")
  126.    do
  127.        /* check for a valid length line */
  128.        if LineMax < 1 or LineMax > MAX_BYTES * 4 / 3 + 1 or
  129.                (LineMax - 1) % 4 ~= 0 then
  130.            writeln("Invalid line length: ", LineMax);
  131.            close(Chout);
  132.            close(Chin);
  133.            exit(1);
  134.        fi;
  135.        /* get and check the actual count of encoded bytes on this line */
  136.        count := decodeChar(LineBuff[0]);
  137.        if (LineMax - 1) / 4 ~= (count + 2) / 3 then
  138.            writeln("Invalid record length: ", count, " : ", LineMax);
  139.            close(Chout);
  140.            close(Chin);
  141.            exit(1);
  142.        fi;
  143.        /* decode the line - groups of 4 characters yield three bytes */
  144.        j := 0;
  145.        i := 1;
  146.        while i ~= LineMax do
  147.            b1 := decodeChar(LineBuff[i + 0]);
  148.            b2 := decodeChar(LineBuff[i + 1]);
  149.            b3 := decodeChar(LineBuff[i + 2]);
  150.            b4 := decodeChar(LineBuff[i + 3]);
  151.            buff[j + 0] := b1 << 2 | b2 >> 4;
  152.            buff[j + 1] := b2 << 4 | b3 >> 2;
  153.            buff[j + 2] := b3 << 6 | b4;
  154.            j := j + 3;
  155.            i := i + 4;
  156.        od;
  157.        /* write out the correct number (1 - 45) of bytes */
  158.        i := 0;
  159.        while i ~= count do
  160.            write(Chout; buff[i]);
  161.            i := i + 1;
  162.        od;
  163.    od;
  164. corp;
  165.  
  166. /*
  167.  * decode -
  168.  *      Decode all of the encoded files in the already opened input file.
  169.  */
  170.  
  171. proc decode()void:
  172.    *char outFileName;
  173.    FILENAME fn;
  174.    bool gotBegin, doneFile;
  175.  
  176.    doneFile := false;
  177.    /* decode files until there are no more left */
  178.    while not Eof do
  179.        gotBegin := false;
  180.        /* skip lines until we find a 'begin' line or we hit end-of-file */
  181.        while not Eof and not gotBegin do
  182.            getLine();
  183.            outFileName := getWord();
  184.            if isWord(outFileName, "begin") then
  185.                outFileName := getWord();
  186.                while outFileName* >= '0' and outFileName* <= '7' do
  187.                    outFileName := outFileName + 1;
  188.                od;
  189.                if outFileName* = '\e' then
  190.                    outFileName := getWord();
  191.                    if outFileName* ~= '\e' then
  192.                        gotBegin := true;
  193.                    fi;
  194.                fi;
  195.            fi;
  196.        od;
  197.        /* if we just found a 'begin' line, go decode an encoded file */
  198.        if gotBegin then
  199.            writeln("Decoding file '", outFileName, "'");
  200.            /* open output file, etc. */
  201.            SetFileName(fn, outFileName);
  202.            pretend(FileDestroy(fn), void);
  203.            if not FileCreate(fn) then
  204.                writeln("Can't create output file '", outFileName, "'");
  205.                close(Chin);
  206.                exit(1);
  207.            fi;
  208.            if not open(Chout, OutputFile, outFileName) then
  209.                writeln("Can't open output file '", outFileName, "'");
  210.                close(Chin);
  211.                exit(1);
  212.            fi;
  213.            /* go decode the file */
  214.            decodeFile();
  215.            /* close file */
  216.            close(Chout);
  217.            doneFile := true;
  218.        fi;
  219.    od;
  220.    /* if we found no 'begin' line in the whole input file, then complain */
  221.    if not doneFile then
  222.        writeln("No 'begin' line found.");
  223.        close(Chin);
  224.        exit(1);
  225.    fi;
  226. corp;
  227.  
  228. /*
  229.  * main -
  230.  *      The main program. Get the command line parameters and open and decode
  231.  *      each one. Each input file is decoded into 1 or more output binary
  232.  *      files.
  233.  */
  234.  
  235. proc main()void:
  236.    *char par;
  237.  
  238.    par := GetPar();
  239.    if par = nil then
  240.        writeln("usage: uudecode file1.typ ... filen.typ");
  241.    else
  242.        while par ~= nil do
  243.            /* try to open the specified input file */
  244.            if not open(Chin, InputFile, par) then
  245.                writeln("Can't open input file '", par, "'");
  246.                exit(1);
  247.            fi;
  248.            /* initialize for reading the input line */
  249.            Eof := false;
  250.            decode();
  251.            close(Chin);
  252.            par := GetPar();
  253.        od;
  254.    fi;
  255. corp;
  256.