home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / lpunch.zoo / lpunch.txt
Text File  |  1990-09-22  |  35KB  |  1,036 lines

  1.  
  2.          Revised LISTSERV System Reference Library, Release 1.5m
  3.           -----------------------------------------------------
  4.             (c) Eric Thomas 1986,1987  Ecole Centrale de Paris
  5.  
  6.  
  7.  
  8.       +-----------------------------------------------------------+
  9.       |   Revised LISTSERV: LISTSERV-Punch Implementation Guide   |
  10.       +-----------------------------------------------------------+
  11.       |                                                           |
  12.       |       Document number: R01-007-0 (October 4th, 1987)      |
  13.       |                                                           |
  14.       |         Author: Eric Thomas <ERIC@FRECP11.BITNET>         |
  15.       |                                                           |
  16.       |   Document fileid: "LISTLPUN MEMO"  (from "Info LPunch")  |
  17.       +-----------------------------------------------------------+
  18.  
  19.  
  20.  
  21.   Preface
  22.  
  23.  
  24.  
  25.   This  manual is a Reference Guide for application programmers who have
  26.   to implement the LISTSERV-Punch file transfer format  on  their  oper-
  27.   ating  system.    It  provides a complete technical description of the
  28.   LISTSERV-Punch format, along with a brief  summary  of  some  relevant
  29.   information about the CMS file system.  In addition, sample conversion
  30.   programs  in  PASCAL  and  C  are  provided  to assist the application
  31.   programmer in implementing a  satisfactory  LISTSERV-Punch  conversion
  32.   program on his system.
  33.  
  34.   NOTE: The  LISTSERV-Punch  file  transfer  format  was introduced with
  35.   release 1.4 of Revised LISTSERV.  Although the  LISTSERV-Punch  format
  36.   might  be expanded in the future to provide additional functions, full
  37.   upwards compatibility is warrantied  provided  that  the  user-written
  38.   conversion  program  strictly conforms to the standard defined in this
  39.   document.  Deviations from the norm (e.g. not ignoring  the  remainder
  40.   of the ID control card) might lead to problems with future releases of
  41.   LISTSERV.
  42.  
  43.  
  44.  
  45.   Conventions
  46.   -----------
  47.  
  48.   The  following  typographical conventions have been made in this docu-
  49.   ment to improve its readability:
  50.  
  51. | o   Recent changes in the publication are indicated by a vertical  bar
  52. |     in the left margin.
  53.  
  54. ! o   Intermediate  changes  between two releases of the document ("Pre-
  55. !     releases") are flagged with  an  exclamation  point  in  the  left
  56. !     margin.    Features described in this fashion should be considered
  57. !     as not documented and not officially supported until the  exclama-
  58. !     tion point is removed.
  59.  
  60. > o   Temporary   restrictions  or  circumventions  are  marked  with  a
  61. >     "greater than" sign in the left margin. This sign may also be used
  62. >     to signal obsolete features for which support will be  dropped  in
  63. >     the next release.
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.   LISTSERV-PUNCH FORMAT DESCRIPTION
  73.   _________________________________
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.   ****************
  81.   * Introduction *
  82.   ****************
  83.  
  84.  
  85.   The term "LISTSERV-Punch" refers to a "file transmission format" which
  86.   is  used  by LISTSERV when sending files larger than 80 characters per
  87.   record to computing systems which do not have the ability  to  process
  88.   Netdata, CARD DUMP or DISK DUMP format.  It was designed to accomodate
  89.   file  transmission  through mail-only gateways.   Its primary features
  90.   are:
  91.  
  92.   o   Ability to transfer files of any record length up to 65535 charac-
  93.       ters per record.  This limit is arbitrary and corresponds  to  the
  94.       longest string a high-level language compiler can usually handle.
  95.  
  96.   o   Ability  to transfer files without automatically padding or strip-
  97.       ping records of trailing blanks.   That is,  leading  or  trailing
  98.       blanks are not removed by the file transfer process itself.
  99.  
  100.   o   Simplicity of the decoding program.  Sample conversion programs in
  101.       PASCAL and C are provided at the end of this document.  The PASCAL
  102.       program was written and tested in about 45 minutes, and any PASCAL
  103.       programmer  should be able to adapt it very quickly to work on his
  104.       own system.
  105.       The C program should  work  unmodified  under  any  standard  UNIX
  106.       system,  but  might need to be improved to allow the specification
  107.       of input and output parameters  and/or  system-dependent  switches
  108.       for the various filing system calls.
  109.  
  110.   o   Acceptable  network efficiency: very little extra lines are gener-
  111.       ated, and trailing blanks are stripped before transmission.
  112.  
  113.   o   Possibility for a human reader  to  get  a  general  idea  of  the
  114.       contents  of  the  file  without  having to resort to a conversion
  115.       program.
  116.  
  117.  
  118.  
  119.  
  120.   ****************************
  121.   * Format of the INPUT file *
  122.   ****************************
  123.  
  124.  
  125.   A LISTSERV-Punch formatted file (also called  "card  deck",  with  the
  126.   term  "card"  being  used to refer to a 80-characters file record) has
  127.   the following outer aspect:
  128.  
  129.   +--------------------------------------------------------------------+
  130.   |    junk line                                                       |
  131.   |        .                                                           |
  132.   |        .                                                           |
  133.   |    junk line                                                       |
  134.   |                                                                    |
  135.   |   ID/ control card                                                 |
  136.   |                                                                    |
  137.   |    data line #1                                                    |
  138.   |        .                                                           |
  139.   |        .                                                           |
  140.   |    data line #n                                                    |
  141.   |                                                                    |
  142.   |   END/ control card                                                |
  143.   |                                                                    |
  144.   |    junk line                                                       |
  145.   |        .                                                           |
  146.   |        .                                                           |
  147.   |    junk line                                                       |
  148.   |                                                                    |
  149.   | Figure 1.  Input card deck format                                  |
  150.   +--------------------------------------------------------------------+
  151.  
  152.  
  153.  
  154.   Junk lines
  155.   ----------
  156.  
  157.  
  158.   Anything before  the  "ID/"  card  (e.g.  mail  header,  comments)  is
  159.   ignored.    Similarly,  anything  after  the  "END/" card (e.g. mailer
  160.   keywords, "Acknowledge-To:" field) is discarded.  Encountering the end
  161.   of the file without any ID or END card is an error.  However, encount-
  162.   ering an END card before any ID card is not an  error  since  anything
  163.   before the first ID card must be ignored without even being parsed.
  164.  
  165.  
  166.  
  167.   Control lines
  168.   -------------
  169.  
  170.  
  171.   The  ID card contains information about the file being sent, while the
  172.   END card is merely an end-of-stream indicator.   The format  of  these
  173.   two cards is:
  174.  
  175.   +--------------------------------------------------------------------+
  176.   |                 ID/filename filetype recfm lrecl reserved          |
  177.   |                 |  |        |        |     |    |                  |
  178.   |                 V  V        V        V     V    V                  |
  179.   | Column numbers: 1  4        13       22    24   29                 |
  180.   |                                                                    |
  181.   |                 END/reserved                                       |
  182.   |                 |   |                                              |
  183.   |                 V   V                                              |
  184.   | Column numbers: 1   5                                              |
  185.   |                                                                    |
  186.   | Blanks  shown  between  keywords are real.   See later on for more |
  187.   | information on the meaning of "filename", "recfm", etc.            |
  188.   |                                                                    |
  189.   | Figure 2.  Control cards format                                    |
  190.   +--------------------------------------------------------------------+
  191.  
  192.   NOTE: The end of the ID card (from column 30 onwards,  inclusive)  and
  193.   the  end  of  the  END  card  (from  column  5 onwards, inclusive) are
  194.   reserved fields which should be ignored  by  the  conversion  program.
  195.   Failure  to  observe  this  rule  might result in severe compatibility
  196.   problems with future releases of LISTSERV.
  197.  
  198.  
  199.  
  200.   Data lines
  201.   ----------
  202.  
  203.  
  204.  
  205.  
  206.   Folding algorithm
  207.  
  208.  
  209.   Each record of the source file is broken into  one  or  more  physical
  210.   "cards"  before  being transmitted.  The first card of each such group
  211.   will indicate the number of cards in the group, counting itself as one
  212.   card (i.e. this is not the number of continuation cards but the  total
  213.   number  of  cards),  and possibly the length of the source record line
  214.   (only if "recfm" is 'V' - see below).   The  remainder  of  the  first
  215.   card, as well as the second and following cards in the group, are pure
  216.   data  bytes.  The resulting concatenated record will have to be padded
  217.   with blanks as determined by the record length indication, if needed.
  218.  
  219.  
  220.  
  221.   Description of the format of a data line
  222.  
  223.  
  224.  
  225.   Fixed-length records
  226.  
  227.  
  228.  
  229.   +--------------------------------------------------------------------+
  230.   | recfm = F                                                          |
  231.   |                 ncards/data                                        |
  232.   |                 |      |                                           |
  233.   |                 V      V                                           |
  234.   | Column numbers: 1      2+Length(ncards)                            |
  235.   |                                                                    |
  236.   | Figure 3.  Data line format, fixed-length records                  |
  237.   +--------------------------------------------------------------------+
  238.  
  239.  
  240.  
  241.   Variable-length records
  242.  
  243.  
  244.  
  245.   +--------------------------------------------------------------------+
  246.   | recfm = V                                                          |
  247.   |                 lrecl/ncards/data                                  |
  248.   |                 |     |      |                                     |
  249.   |                 V     |      V                                     |
  250.   | Column numbers: 1     |      3+Length(lrecl)+Length(ncards)        |
  251.   |                       V                                            |
  252.   |                       2+Length(lrecl)                              |
  253.   |                                                                    |
  254.   | Figure 4.  Data line format, variable-length records               |
  255.   +--------------------------------------------------------------------+
  256.  
  257.   NCARDS    is the total number of cards in the group (ncards >= 1).
  258.  
  259.   LRECL     is the logical record length of the source file record asso-
  260.             ciated with the group; it does not appear in recfm  F  files
  261.             for which the record length is defined in the ID card.
  262.  
  263.  
  264.  
  265.  
  266.   ***************************************
  267.   * Summary of CMS file characteristics *
  268.   ***************************************
  269.  
  270.  
  271.   Since  LISTSERV  operates in an IBM VM/SP CMS environment and the file
  272.   will have to be received on a different operating system, a very short
  273.   description of the CMS file system has been included here.
  274.  
  275.  
  276.  
  277.   CMS file names
  278.   --------------
  279.  
  280.  
  281.   Under CMS, each file is identified by a "filename" and  a  "filetype",
  282.   both  of  them  being  strings  of  1 to 8 characters taken out of the
  283.   following set:
  284.  
  285.        A-Z   a-z   0-9   #$@-+:_
  286.  
  287.  
  288.   However, LISTSERV will never send a file containing a lowercase  char-
  289.   acter  in  its  filename or filetype, because a lot of systems have to
  290.   convert them to uppercase or will convert network interactive messages
  291.   to uppercase, thus making it impossible for users to enter mixed  case
  292.   file names in the commands they send to LISTSERV.
  293.  
  294.  
  295.  
  296.   CMS file structure
  297.   ------------------
  298.  
  299.  
  300.   CMS  files  consist  in  a  series of "records", as opposed to UNIX or
  301.   MS-DOS files which consist in a series of bytes.    When  calling  the
  302.   filing  system  to  perform a write operation, you must provide a full
  303.   record.  It is not possible to write "byte by byte" since this has  no
  304.   meaning  (you  could  of course write a series of one-byte records but
  305.   this would not create the file you  expected).    Each  CMS  file  has
  306.   therefore, among other attributes:
  307.  
  308.   o   A "number of records" field.
  309.  
  310.   o   A  "logical  record  length" (which is called lrecl).  This is the
  311.       size of the longest record  in  the  file,  and  consequently  the
  312.       minimum  size  of  the  storage  buffer  required to read the file
  313.       record by record.
  314.  
  315.   o   A "record format" (which is called recfm).   This "record  format"
  316.       is  a single character, F for FIXED or V for VARIABLE.  A recfm of
  317.       "F" indicates that all the records in the file  have  exactly  the
  318.       same  lrecl,  while "V" indicates the opposite.  The filing system
  319.       uses more efficient algorithms when handling recfm  F  files,  but
  320.       they require more disk space of course.
  321.  
  322.  
  323.  
  324.   Implementation considerations
  325.   -----------------------------
  326.  
  327.  
  328.   Before  you  start writing the conversion program, you must answer the
  329.   following set of questions:
  330.  
  331.   1.  Which name will I use on my system for the newly converted file?
  332.  
  333.       The sample C program reads from  standard  input  and  writes  the
  334.       converted  file  to  standard output, leaving the user responsible
  335.       for providing adequate redirection on the command line.
  336.       The sample PASCAL program, which is written for MS-DOS,  uses  the
  337.       filename  field as file name and the three first characters of the
  338.       filetype as file extension, i.e. filename+'.'+Left(filetype,3).
  339.       You may use a similar algorithm or select a constant  output  file
  340.       name such as "LISTSERV.PUN".
  341.  
  342.   2.  How should recfm F files be written on my system?
  343.  
  344.       The  sample  program treats a recfm F file as a recfm V file which
  345.       just happens to  have  records  of  identical  length.    A  CR+LF
  346.       sequence  is therefore output at the end of each record, regarless
  347.       of the recfm.  Alternatively, the program could have been designed
  348.       to write recfm F files "as is", i.e. without any CR+LF sequence at
  349.       the end of the record.  It all depends on the capabilities of your
  350.       system and (above all) of your system's editor.
  351.  
  352.  
  353.  
  354.  
  355.   SAMPLE PASCAL PROGRAM
  356.   _____________________
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363.   *********************
  364.   * Preliminary notes *
  365.   *********************
  366.  
  367.  
  368.   This sample PASCAL program was written for Turbo-PASCAL  (a  trademark
  369.   of  Borland  International).    It is provided only as an example - no
  370.   warranty of any kind is made that the program will  function  properly
  371.   on  your  operating system.   Detailed comments have been provided for
  372.   all the "system dependent" procedures.  The program was  designed  for
  373.   transportability,  not  efficiency  -  there are a lot of places where
  374.   some optimization would greatly improve execution speed, but that  was
  375.   not  the  objective  of the program.  All the functions and procedures
  376.   which are not part of the  standard  library  have  been  Capitalized,
  377.   while standard functions have been entered in lower case.  These func-
  378.   tions might exist on some of the compilers, possibly under a different
  379.   name.  The compiler is assumed to be able to handle the "string" type;
  380.   if  it  doesn't,  you will have to write a few "string-handling" func-
  381.   tions which emulate strings from an array of char.
  382.  
  383.   Finally, since not all terminals accept the special characters used by
  384.   PASCAL, the following conversion has been made:
  385.  
  386.     opening bracket     --> (.
  387.     closing bracket     --> .)
  388.     opening curly brace --> (*
  389.     closing curly brace --> *)
  390.  
  391.  
  392.  
  393.   NOTE: in Turbo-PASCAL, string concatenation  is  done  using  the  "+"
  394.   sign.
  395.  
  396.  
  397.  
  398.  
  399.  
  400.   *----------------------------- Cut here --------------------------------*
  401.  
  402.      (*
  403.      * LISTSERV-Punch PASCAL conversion program, version number 03
  404.      *
  405.      *    Written by Eric Thomas <ERIC@FRECP11.BITNET>
  406.      *
  407.      *
  408.      * This public domain program has  been tested on an IBM PC-compatible
  409.      * system on several  small files that had to be  keyed-in manually on
  410.      * the PC since no PC-to-mainframe connection was available.
  411.      *
  412.      * The working version  of the program had to be  printed and re-keyed
  413.      * in manually into the document  you are reading. There can therefore
  414.      * be several  keying errors --  proofreading programs is  very tiring
  415.      * and consequently very difficult.
  416.      *
  417.      *
  418.      * Synopsis:
  419.      *
  420.      *   The input file from LISTSERV is assumed to be CARDS.DAT
  421.      *
  422.      *   Output is  directed to  file "filename.filetype", with filetype
  423.      *   being truncated to 3 characters of course.
  424.      *
  425.      *
  426.      * Problems:
  427.      *
  428.      *   Send   problem   or   bug   reports   to   <ERIC@FRECP11.BITNET>.
  429.      *   Metaphysical complaints about the Rules of Structured Programming
  430.      *   and their relationship to  this blasphemous program should better
  431.      *   stay in their author's own warm, safe and cosy mailbox.
  432.      *
  433.      *)
  434.     program LPUNCH(input,cardfile,output,outfile);
  435.  
  436.     (* Note: Turbo-PASCAL requires square brackets for the "string" type,
  437.              while other compilers require parenthesis. Since some terminals
  438.              cannot display square brackets, parenthesis will be used. *)
  439.  
  440.     type cards=string(80);
  441.          string5=string(5); (* This is because Turbo is not a very power-  *)
  442.          string8=string(8); (* ful compiler                                *)
  443.          anystring=string(255); (* Substitute the maximum length of a
  444.                                    "string" var on your compiler *)
  445.  
  446.     var cardfile:text; (* Input file -- compiler dependent declaration *)
  447.         outfile:file of char;        (* compiler dependent declaration *)
  448.         card:cards;
  449.         filename,filetype:string8;
  450.         recfm:char;
  451.         i,ncards,lrecl,xlrecl:integer;
  452.  
  453.     function Substr(s:anystring;start,size:integer):anystring;
  454.     (* This function must return the substring of "s" starting at character
  455.        number "start" and of length "size". The resulting string must NOT be
  456.        padded with blanks if start+size-1 > length of the string. *)
  457.  
  458.       begin
  459.         Substr:=Copy(s,start,size)  (* Turbo has it under another name *)
  460.       end;
  461.  
  462.     function Length(s:anystring):integer;
  463.     (* This return the length of the string, with 0 for a null string *)
  464.  
  465.       begin
  466.         Length:=ord(s(.0.)) (* Same as the built-in Turbo function *)
  467.       end;
  468.  
  469.     procedure Opencards;
  470.     (* This procedure must open the input file, wherever it may be or your
  471.        system, and display an error message and exit it there is an error *)
  472.  
  473.       begin
  474.         assign(cardfile,'CARDS.DAT');
  475.         (*$i-*)
  476.         reset(cardfile);
  477.         (*$i+*)
  478.         if ioresult <> 0 then
  479.          begin
  480.            writeln('Error opening input file');
  481.            halt (* HALT is a GOTO just before the END. statement *)
  482.          end
  483.       end;
  484.  
  485.     procedure Closecards;
  486.     (* This procedure must close the input file. You may wish to have it
  487.        delete the input file too *)
  488.  
  489.       begin
  490.         (*$i-*)
  491.         close(cardfile);
  492.         if ioresult = 0 then; (* just reset turbo's hang... *)
  493.         (*$i+*)
  494.       end;
  495.  
  496.     function Getcard:cards;
  497.      var result:cards;
  498.     (* This function must read one 80-chars line (one "card") from input
  499.        and return it as result. A premature EOF is an error and must cause
  500.        termination of the program. The result must be EXACTLY 80 characters
  501.        in length *)
  502.  
  503.       begin
  504.         (*$i-*)
  505.         readln(cardfile,result);
  506.         (*$i+*)
  507.         if ioresult <> 0 then
  508.          begin
  509.            writeln('Premature EOF on input');
  510.            halt
  511.          end;
  512.         while Length(result) <> 80 do result:=result+' ';
  513.         Getcard:=result
  514.       end;
  515.  
  516.     function Dec2bin(s:string5):integer;
  517.      var n,error:integer;
  518.     (* This function converts a string of numeric characters into its
  519.        binary representation ("integer"). An error should cause termination*)
  520.  
  521.       begin
  522.         val(s,n,error);
  523.         if error = 0 then Dec2bin:=n
  524.                      else begin
  525.                             writeln('Invalid decimal argument');
  526.                             halt
  527.                           end
  528.       end;
  529.  
  530.     procedure Openout(fn,ft:string8);
  531.     (* This procedure must open the output file under whatever file-id you
  532.        may choose *)
  533.  
  534.       begin
  535.         assign(outfile,fn+'.'+Substr(ft,1,3));
  536.         (*$i-*)
  537.         rewrite(outfile);
  538.         (*$i+*)
  539.         if ioresult <> 0 then
  540.          begin
  541.            writeln('Error opening output file');
  542.            halt
  543.          end
  544.       end;
  545.  
  546.     procedure Closeout;
  547.     (* This procedure must close the output file. Errors should be detected
  548.        since they can mean a disk-full condition while writing the last
  549.        buffer, or suchlike *)
  550.  
  551.       begin
  552.         (*$i-*)
  553.         close(outfile);
  554.         if ioresult <> 0 then
  555.          begin
  556.            writeln('Error occured while closing output file');
  557.            halt
  558.          end
  559.         (*$i+*)
  560.       end;
  561.  
  562.     function Gobbleword(var card:cards):string5;
  563.      var s:string5;
  564.     (* This function should be left "as is" *)
  565.  
  566.       begin
  567.         s:='';
  568.         repeat
  569.           s:=s+card(.1.);
  570.           card:=Substr(card,2,80)
  571.         until card(.1.) = '/';
  572.         card:=Substr(card,2,80); (* Delete the "/" sign too *)
  573.         Gobbleword:=s
  574.       end;
  575.  
  576.     procedure Outchar(c:char);
  577.     (* This outputs a character to "outfile". On byte-based file systems such
  578.        as UNIX or MS-DOS, the character is just sent to standard output. On
  579.        record-based systems it must be appended to a buffer (string(65535) or
  580.        array of char) before the actual write is performed (see below) *)
  581.  
  582.       begin
  583.         (*$i-*)
  584.         write(outfile,c);
  585.         (*$i+*)
  586.         if ioresult <> 0 then
  587.          begin
  588.            writeln('Error writing to output file');
  589.            halt
  590.          end
  591.       end;
  592.  
  593.     procedure Endofrecord;
  594.     (* This procedure is called when the end of a record is reached. On
  595.        record-based file systems, the buffer must be written; on byte-based
  596.        systems a CR+LF (or similar) must be output for recfm V files, and
  597.        possibly for recfm F files (your option) *)
  598.  
  599.       begin
  600.         Outchar(chr(13));  (* CR *)
  601.         Outchar(chr(10))   (* LF *)
  602.       end;
  603.  
  604.     procedure Writeout(s:cards;var l:integer);
  605.      var i:integer;
  606.     (* This one must be left "as is" *)
  607.  
  608.       begin
  609.         if Length(s) > l then s:=Substr(s,1,l);
  610.         for i:=1 to Length(s) do Outchar(Substr(s,i,1));
  611.         l:=l-Length(s)
  612.       end;
  613.  
  614.     (* Main program -- nothing needs to be changed *)
  615.  
  616.     begin
  617.       Opencards;
  618.       repeat
  619.         card:=Getcard
  620.       until Substr(card,1,3) = 'ID/';
  621.  
  622.       filename:=Substr(card,4,8);
  623.       filetype:=Substr(card,13,8);
  624.       recfm:=Substr(card,22,1);
  625.       lrecl:=Dec2bin(Substr(card,24,5));
  626.  
  627.       Openout(filename,filetype);
  628.  
  629.       repeat
  630.         card:=Getcard;
  631.         if Substr(card,1,4) <> 'END/' then
  632.          begin
  633.            if recfm = 'V' then xlrecl:=Dec2bin(Gobbleword(card))
  634.                           else xlrecl:=lrecl;
  635.            ncards:=Dec2bin(Gobbleword(card));
  636.  
  637.            repeat
  638.              Writeout(card,xlrecl);
  639.              ncards:=ncards-1;
  640.              if ncards <> 0 then card:=Getcard
  641.            until ncards = 0;
  642.            for i:=1 to xlrecl do Outchar(' ');
  643.            Endofrecord
  644.          end
  645.       until Substr(card,1,4) = 'END/';
  646.  
  647.       Closecards;
  648.       Closeout;
  649.       writeln('File "',filename,' ',filetype,
  650.                    '" has been successfully converted.')
  651.     end.
  652.  
  653.     *----------------------------- Cut here --------------------------------*
  654.  
  655.  
  656.  
  657.  
  658.   SAMPLE C PROGRAM
  659.   ________________
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.   *********************
  667.   * Preliminary notes *
  668.   *********************
  669.  
  670.  
  671.   This  sample C program is provided only as an example - no warranty of
  672.   any kind is made that the program will function properly on your oper-
  673.   ating system.   Detailed comments  have  been  provided  for  all  the
  674.   "system dependent" procedures.  All the functions and procedures which
  675.   are  not  part  of  the  standard library have been Capitalized, while
  676.   standard functions have been entered in lower case.
  677.  
  678.   The program should operate properly as is on any standard UNIX system,
  679.   although some system-dependent additions might be  necessary  in  some
  680.   cases (e.g. special options on the output file fopen call, or addition
  681.   of command-line switches).
  682.  
  683.   Finally, since not all terminals accept the special characters used by
  684.   C, the following conversion has been made:
  685.  
  686.     opening bracket     --> (:
  687.     closing bracket     --> :)
  688.     opening curly brace --> (*
  689.     closing curly brace --> *)
  690.     backslash           --> <bs>
  691.  
  692.   You  should  be  able  to  reverse  this  conversion  easily with your
  693.   favourite text editor before compiling the program.
  694.  
  695.  
  696.  
  697.   *----------------------------- Cut here --------------------------------*
  698.  
  699.     /*
  700.      * LISTSERV-Punch C conversion program, version number 02
  701.      *
  702.      *    Written by Eric Thomas <ERIC@FRECP11.BITNET>
  703.      *
  704.      *
  705.      * This public domain program has been  tested on a VM system with the
  706.      * huge BITEARN NODES file as input (over 23,000 LISTSERV-Punch format
  707.      * records), as  well as several  other smaller files. No  problem has
  708.      * been encountered in the testing phase.
  709.      *
  710.      * The working version  of the program has  been electronically copied
  711.      * into the document  you are reading, untouched.  There can therefore
  712.      * be no keying error, or then it  was in the original program too and
  713.      * was not detected during the testing period.
  714.      *
  715.      *
  716.      * Synopsis:
  717.      *
  718.      *   The input file from LISTSERV is assumed to be the standard input.
  719.      *
  720.      *   Output is  directed to  the standard output,  but the  program is
  721.      *   structured in such a way that this can be easily changed.
  722.      *
  723.      *
  724.      * Problems:
  725.      *
  726.      *   Send   problem   or   bug   reports   to   <ERIC@FRECP11.BITNET>.
  727.      *   Philosophical lectures about the  grandiose organization of C and
  728.      *   how  it has  been violated  in  this program  should be  directly
  729.      *   forwarded to /dev/null for a prompt answer.
  730.      *
  731.      */
  732.     #include <stdio.h>
  733.  
  734.     char card(:81:),     /* Input record image */
  735.          filename(:9:),
  736.          filetype(:9:),
  737.          number(:6:),    /* Scratch string to hold a number */
  738.          recfm;
  739.  
  740.     int  i,ncards,lrecl,xlrecl;
  741.  
  742.     FILE *outfile;
  743.  
  744.  
  745.     /* This function does not have to be tailored */
  746.     Substr(outstring,instring,start,length)
  747.      char *outstring,*instring;
  748.      int  start,length;
  749.     (*
  750.       register int rd=0,wr=0;
  751.       register char c;
  752.  
  753.      --start;
  754.      while(rd < start) (*
  755.        if (instring(:rd++:)=='<bs>0') (*
  756.          outstring="";
  757.          return;
  758.        *)
  759.      *)
  760.  
  761.      while(length-- > 0) (*
  762.        if ((c=instring(:rd++:)) != '<bs>0')
  763.         outstring(:wr++:)=c;
  764.        else break;
  765.      *)
  766.      outstring(:wr:)='<bs>0';
  767.      return;
  768.     *)
  769.  
  770.  
  771.     /* This function  must read one  80-chars line (one "card")  from input
  772.        and return it as result. A premature  EOF is an error and must cause
  773.        termination of the program. The result must be EXACTLY 80 characters
  774.        in length */
  775.     Getcard(string)
  776.     char *string;
  777.     (*
  778.       register int i=0,c;
  779.  
  780.       while(i < 80) (*
  781.         if (((c=getchar()) != EOF) && (c != '<bs>n'))
  782.           string(:i++:)=c;
  783.         else
  784.           break;
  785.       *)
  786.       if (c == EOF) (*
  787.         fprintf(stderr,"Premature EOF on input.<bs>n");
  788.         exit(100); *)
  789.  
  790.       if (i==80) (*
  791.         if (getchar() != '<bs>n') (*
  792.           fprintf(stderr,"Input file contains records larger than 80.<bs>n");
  793.           exit(100);
  794.         *)
  795.       *)
  796.       while (i < 80) (*
  797.         string(:i++:)=' ';
  798.       *)
  799.       string(:i:)='<bs>0';
  800.       return;
  801.     *)
  802.  
  803.  
  804.     /* This function does not have to be tailored */
  805.     Dec2bin(result,string)
  806.     char *string;
  807.     int  *result;
  808.     (*
  809.       if (sscanf(string,"%d",result) != 0) return;
  810.       fprintf(stderr,"Invalid decimal argument -- '%s'.<bs>n",string);
  811.       exit(100);
  812.     *)
  813.  
  814.  
  815.     /* This procedure must open the output file under whatever file-id you
  816.        may choose */
  817.     Openout(fn,ft)
  818.     char *fn,*ft;
  819.     (*
  820.       /* Our implementation uses standard output as file pointer */
  821.       outfile=stdout;
  822.  
  823.       /* The following instruction must be uncommented for use under
  824.          most VM C's if the output file is to have a lrecl > 80 */
  825.       /* outfile=fopen("LPUNCH OUTPUT A (recfm v lrecl 65535","w"); */
  826.       return;
  827.     *)
  828.  
  829.  
  830.     /* This procedure must close the output file. Errors should be detected
  831.        since they  can mean  a disk-full condition  while writing  the last
  832.        buffer, or suchlike */
  833.     Closeout()
  834.     (* /* The chosen implementation does nothing and relies on the operating
  835.          system  to  close the  standard  output  file.  This is  not  good
  836.          programming practice but at least it's transportable. */
  837.       return;
  838.     *)
  839.  
  840.  
  841.     /* This function should be left "as is" */
  842.     Gobbleword(inpstring,outstring)
  843.     char *inpstring,*outstring;
  844.     (*
  845.       register int rd=0,wr=0;
  846.  
  847.       while (inpstring(:rd:) != '/') (*
  848.         outstring(:wr++:)=inpstring(:rd++:);
  849.       *)
  850.       outstring(:wr:)='<bs>0';
  851.  
  852.       for(wr=0;inpstring(:++rd:) != '<bs>0';) (*
  853.         inpstring(:wr++:)=inpstring(:rd:);
  854.       *)
  855.       inpstring(:wr:)='<bs>0';
  856.       return;
  857.     *)
  858.  
  859.  
  860.     /* This function does not have to be tailored */
  861.     Writeout(string,lenptr)
  862.     char *string;
  863.     int  *lenptr;
  864.     (*
  865.       int i=0;
  866.       while((string(:i:) != '<bs>0') && ( *lenptr > 0)) (*
  867.         putc(string(:i++:),outfile);
  868.         --( *lenptr);
  869.       *)
  870.     *)
  871.  
  872.  
  873.     /* Main program -- nothing needs to be changed */
  874.     main() (*
  875.  
  876.       do (* /* Read up to and including 'ID/' card */
  877.         Getcard(card);
  878.     *) while ((card(:0:)!='I') || (card(:1:)!='D') || (card(:2:)!='/'));
  879.  
  880.       Substr(filename,card,4,8);
  881.       Substr(filetype,card,13,8);
  882.       recfm=card(:21:);
  883.       Substr(number,card,24,5);
  884.       Dec2bin(&lrecl,number);
  885.  
  886.       Openout(filename,filetype);
  887.  
  888.       for (;;) (*
  889.         Getcard(card);
  890.         if ((card(:0:)=='E') && (card(:1:)=='N') &&
  891.             (card(:2:)=='D') && (card(:3:)=='/'))
  892.           break;
  893.  
  894.         if (recfm=='V') (*
  895.           Gobbleword(card,number);
  896.           Dec2bin(&xlrecl,number); *)
  897.         else
  898.           xlrecl=lrecl;
  899.  
  900.         Gobbleword(card,number);
  901.         Dec2bin(&ncards,number);
  902.  
  903.         do (*
  904.           Writeout(card,&xlrecl);
  905.           if (--ncards != 0)
  906.             Getcard(card);
  907.       *) while(ncards!=0);
  908.  
  909.         for(i=1;i <= xlrecl;i++) (*
  910.           putc(' ',outfile);
  911.         *)
  912.         putc('<bs>n',outfile);
  913.       *)
  914.       Closeout();
  915.     *)
  916.  
  917.     *----------------------------- Cut here --------------------------------*
  918.  
  919.  
  920.  
  921.  
  922.  
  923.   *************************************
  924.   * Appendix A.  The LISTSERV Library *
  925.   *************************************
  926.  
  927.       o User's guide  . . . . . . . . . . . . . . . . . . . .  (U01-001)
  928.  
  929.       o List Manager's guide  . . . . . . . . . . . . . . . .  (M01-002)
  930.  
  931.       o Installation guide  . . . . . . . . . . . . . . . . .  (S01-003)
  932.  
  933.       o Application Programmer's guide  . . . . . . . . . . .  (A01-004)
  934.  
  935.       o Maintenance guide . . . . . . . . . . . . . . . . . .  (S01-005)
  936.  
  937.       o File Server Functions . . . . . . . . . . . . . . . .  (U01-006)
  938.  
  939.   --> o Listserv-Punch Implementation . . . . . . . . . . . .  (R01-007)
  940.  
  941.       o File Maintainer's guide . . . . . . . . . . . . . . .  (M01-008)
  942.  
  943.       o BITNET-Oriented Presentation  . . . . . . . . . . . .  (P01-009)
  944.  
  945.       o Public Utilities Reference  . . . . . . . . . . . . .  (A01-010)
  946.  
  947.       o Licensed Utilities Reference  . . . . . . . . . . . .  (S01-011)
  948.  
  949.       o Database Functions  . . . . . . . . . . . . . . . . .  (U01-012)
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.   LISTSERV Document Numbers
  960.   -------------------------
  961.  
  962.                                 U 01 - 006 - 0
  963.                                 _ __   ___   _
  964.                                 |  |    |    |
  965.   Document Class     -----------+  |    |    |
  966.                                    |    |    |
  967.                                    |    |    |
  968.                                    |    |    |
  969.   Product Number     --------------+    |    |
  970.                                         |    |
  971.                                         |    |
  972.                                         |    |
  973.   Publication Number -------------------+    |
  974.                                              |
  975.                                              |
  976.                                              |
  977.   Revision Number    ------------------------+
  978.  
  979.  
  980.  
  981.   Document Class
  982.  
  983.  
  984.   The Document Class indicates for which category of persons the  publi-
  985.   cation was written.  The current classes are:
  986.  
  987.   A    Documents  intended  for Application Programmers.  These publica-
  988.        tions are usually very technical.
  989.  
  990.   M    Documents intended for Software Managers, i.e.  operators,  "list
  991.        owners", "file maintainers", et al.
  992.  
  993.   P    General  Presentation  documents  intended for persons who do not
  994.        have any particular knowledge in the product.   These are  gener-
  995.        ally non-technical documents.
  996.  
  997.   R    Reference  documents  defining  protocols  used  by  the product.
  998.        These documents are very technical and are  intended  for  people
  999.        who  have  to write interfaces for the product or attempt to port
  1000.        it to an operating system or environment for  which  it  was  not
  1001.        originally written.
  1002.  
  1003.   S    Documents  intended  for  Systems Programmers, i.e.   the persons
  1004.        responsible for the installation and operation of the product.
  1005.  
  1006.   U    Documents intended for General Users.
  1007.  
  1008.  
  1009.  
  1010.  
  1011.   Product Number
  1012.  
  1013.  
  1014.   The Product Number is a unique number associated with the  product  to
  1015.   which  the  publication relates.  Number 01 refers to LISTSERV, number
  1016.   02 corresponds to the NETINFO sub-product, etc.
  1017.  
  1018.  
  1019.  
  1020.   Publication Number
  1021.  
  1022.  
  1023.   This is a unique number associated with the publication.   Publication
  1024.   Numbers  are  assigned  sequentially, disregarding the Document Class.
  1025.   There is a different set of Publication Numbers for each product.
  1026.  
  1027.  
  1028.  
  1029.   Revision Number
  1030.  
  1031.  
  1032.   This number is incremented at every release change in the publication.
  1033.   Fractional numbers indicate intermediate changes between two releases.
  1034.  
  1035.  
  1036.