home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol021 / strlib.lib < prev    next >
Text File  |  1984-04-29  |  12KB  |  512 lines

  1.  
  2.  
  3.  
  4. Donated to the PASCAL/Z USERS GROUP, July 1980
  5.   by Ray Penley
  6.  
  7.     {---------------------------------------}
  8.     {        STRLIB LIBRARY        }
  9.     {---------------------------------------}
  10.  
  11.  
  12. {
  13.     Functions in this library
  14.  
  15.  
  16.     Concat        -Concatenate two strings.
  17.     Copy        -Copy to a substring from a source string
  18.     Delay        -Pause for a requested number of seconds.
  19.     Draw        -Draws/Prints a pattern string.
  20.     GetLine        -Input a string into users buffer.
  21.     Quiry        -True/False plus literal message.
  22.     Print        -Prints a string to the console.
  23.     RDR        -Alphanumeric to real number.
  24.     Replace        -Replace a substring within a source string.
  25.     Skip        -Skips X lines.
  26.     STR        -Integer to alphanumeric.
  27.     Ucase        -Translates lowercase letter to uppercase.
  28.     VAL        -Single character to integer value.
  29.  
  30. }
  31.  
  32.   (*********************************************)
  33.  
  34.  
  35.  
  36. PROCEDURE PRINT( A : MString);
  37. VAR
  38.   I : 1..StrMax;
  39. begin
  40.   If (LENGTH(A) > 0) and (LENGTH(A) <= StrMax) then
  41.     For I:= 1 to LENGTH(A) do
  42.     write(A[ I ])
  43.   Else
  44.     Write(space)
  45. end;
  46.  
  47.   (*********************************************)
  48.  
  49.  
  50. PROCEDURE COPY( {    TO     } VAR dest : string80 ;
  51.         {   FROM    } THIS : MSTRING ;
  52.         {STARTING AT} POSN : INTEGER ;
  53.         {# OF CHARS } LEN  : INTEGER ) ;
  54. {  COPY(NEW_NAME, NBUF, NAME_ADDR, NAME_LEN);    }
  55. {  COPY(A_STRING, A_STRING, 5, 5);        }
  56. {GLOBAL
  57.   StrMax = 255;
  58.   MSTRING = STRING StrMax;            }
  59. LABEL    99;
  60. CONST    line_length = 80 ;
  61. VAR    ix   : 1..StrMax;
  62. begin
  63.   SETLENGTH(dest,0);  {length returned string=0}
  64.   If (len + posn) > line_length then{exit}goto 99;
  65.   IF ((len+posn-1) <= LENGTH(this)) and
  66.      (len > 0) and (posn > 0) then
  67.      FOR ix:=1 to len do
  68.          APPEND(dest, this[posn+ix-1]);
  69. 99: {Any error returns dest with a length of ZERO.}
  70. End{of COPY};
  71.  
  72.   (*********************************************)
  73.  
  74.  
  75. PROCEDURE CONCAT({New_String} VAR C : string80 ;
  76.          {Arg1_str  }     A : Mstring ;
  77.          {Arg2_str  }     B : Mstring );
  78. CONST
  79.   line_length = 80;
  80. VAR
  81.   ix : 1..StrMax;
  82. begin
  83.   SETLENGTH(C,0);
  84.   If (LENGTH(A) + LENGTH(B)) <= line_length then
  85.     begin
  86.     APPEND(C,A);
  87.         APPEND(C,B);
  88.     end;
  89.   {If error then returns length of new_string=0}
  90. End{of CONCAT};
  91.  
  92.   (*********************************************)
  93.  
  94.  
  95. PROCEDURE REPLACE(VAR source    : string80;
  96.           VAR dest    : string80;
  97.               K1    : Integer);
  98. (*
  99.  *    REPLACE(Source, Destination, Index);
  100.  *)
  101. CONST    line_length = 80;
  102. VAR    temp1,temp2 : Mstring;
  103.     pos, k      : 1..StrMax;
  104. begin
  105.   If (K1 > 0) and (K1 <= LENGTH(dest)) and (K1 <= line_length) then
  106.     begin (* Position 'K1' is within STRING 'dest'    *)
  107.       (* but not longer than line_length        *)
  108.       SETLENGTH(temp1,0);
  109.       SETLENGTH(temp2,0);
  110.       COPY(temp1,dest,1,K1-1);
  111.       APPEND(temp1,source);(* concatenate temp1 and A *)
  112.       k := K1 + LENGTH(source);(* extract remaining chars from dest *)
  113.       COPY(temp2,dest,k,(LENGTH(dest)-k+1));
  114.       CONCAT(dest,temp1,temp2)
  115.     end(*If*)
  116.   Else(* Issue error message and do nothing *)
  117.     Writeln('Index out of range')
  118. end(* of REPLACE *);
  119.  
  120.   (*********************************************)
  121.  
  122.  
  123.  
  124. Function VAL(ch: char): integer;
  125. { Returns the integer value of
  126.   the single char passed }
  127. const    z = 48; {  ORD('0')  }
  128. begin
  129.   VAL := ORD(ch) - z
  130. end;
  131.  
  132.   (*********************************************)
  133.  
  134.  
  135.  
  136. Function RDR(var f: Dstring  ): real;
  137. { read real numbers in free format.
  138.   author: Niklaus Wirth
  139.   book:   Pascal User Manual & Report
  140.       pg 122-123
  141.   ENTER WITH:
  142.     f = a string containing ONLY the alphanumeric number
  143.         to be converted to a real number.
  144.   RETURNS:
  145.     A real number.
  146.     Any error returns RDR := 0.0
  147. *}
  148. label    9;{ error exit }
  149. const
  150.     t48 = 281474976710656.0 ;
  151.     limit = 56294995342131.0 ;
  152.     lim1 = 322;        { maximum exponent }
  153.     lim2 = -292;        { minimum exponent }
  154.     space = ' ';
  155.     emsg1 = '**digit expected';
  156.     emsg2 = '**number too large';
  157. type
  158.     posint = 0..323;
  159. var
  160.   ch    : char;
  161.   y    : real;
  162.   posn,
  163.   a,i,e    : integer;
  164.   fatal,
  165.   s,ss    : boolean; { signs }
  166.  
  167. procedure Getc(var ch: char);
  168. begin
  169.   posn := posn + 1;
  170.   ch := f[posn];
  171. end;
  172.  
  173. function TEN(e: posint): real; {  = 10**e,  0<e<322  }
  174. var    i: integer;
  175.     t: real;
  176. begin
  177.   i := 0;
  178.   t := 1.0;
  179.   repeat
  180.     If ODD(e) then
  181.       case i of
  182.     0: t := t * 1.0E1;
  183.     1: t := t * 1.0E2;
  184.     2: t := t * 1.0E4;
  185.     3: t := t * 1.0E8;
  186.     4: t := t * 1.0E16;
  187.     5: t := t * 1.0E32    { that's all! }
  188.     6,7,8:
  189.        begin
  190.        writeln('**Floating point overflow');
  191.        fatal := true;
  192.        e := 2;{ sets e to zero on next division }
  193.        end;
  194.     {*===================*
  195.     --- can not use ---
  196.      6: t := t * 1.0E64;
  197.      7: t := t * 1.0E128;
  198.      8: t := t * 1.0E256
  199.      *===================*}
  200.       end{ case };
  201.     e := e DIV 2;
  202.     i := i + 1;
  203.   until e=0;
  204.   TEN := t;
  205. end{of TEN};
  206.  
  207. begin
  208.   fatal := false;
  209.   posn := length(f);
  210.   setlength(f,posn+1);
  211.   f[posn+1] := space;
  212.   posn := 0;
  213.   getc(ch);
  214.   { skip leading blanks }
  215.   While ch=space do getc(ch);
  216.   If ch='-' then
  217.     begin
  218.     s := true;
  219.     getc(ch)
  220.     end
  221.   Else
  222.     begin
  223.     s := false;
  224.     If ch='+' then getc(ch)
  225.     end;
  226.   If not(ch IN ['0'..'9']) then
  227.     begin
  228.     writeln(emsg1);
  229.     {HALT} fatal := true; goto 9;
  230.     end;
  231.   a := 0;
  232.   e := 0;
  233.   repeat
  234.     If a<limit then
  235.       a := 10 * a + VAL(ch)
  236.     Else
  237.       e := e+1;
  238.     getc(ch);
  239.   until not(ch IN ['0'..'9']);
  240.   If ch='.' then
  241.     begin { read fraction }
  242.     getc(ch);
  243.     while ch IN ['0'..'9'] do
  244.       begin
  245.       If a<limit then
  246.     begin
  247.     a := 10 * a + VAL(ch);
  248.     e := e - 1
  249.     end;
  250.       getc(ch);
  251.       end{ while };
  252.     end{ read fraction };
  253.   If (ch='E') or (CH='e') then
  254.     begin { read scale factor }
  255.       getc(ch);
  256.       i := 0;
  257.       If ch='-' then
  258.         begin ss := true; getc(ch) end
  259.       Else
  260.         begin
  261.         ss := false;
  262.         If ch='+' then getc(ch)
  263.         end;
  264.       If ch IN ['0'..'9'] then
  265.         begin
  266.         i := VAL(ch);
  267.         getc(ch);
  268.         while ch IN ['0'..'9'] do
  269.       begin
  270.       If i<limit then i := 10 * i + VAL(ch);
  271.       getc(ch)
  272.       end{ while}
  273.         end{ If }
  274.       Else
  275.         begin
  276.         writeln(emsg1);
  277.         {HALT} fatal := true; goto 9;
  278.         end;
  279.       If ss
  280.      then e := e - i
  281.      Else e := e + i;
  282.     end{ read scale factor };
  283.   If e < lim2 then
  284.     begin
  285.     a := 0;
  286.     e := 0;
  287.     end
  288.   Else
  289.     If e > lim1 then
  290.       begin
  291.       writeln(emsg2);
  292.       {HALT} fatal := true; goto 9;
  293.       end;
  294.   {  0 < a < 2**49  }
  295.   If a >= t48 then
  296.     y := ((a+1) DIV 2) * 2.0
  297.   Else
  298.     y := a;
  299.   If s then y := -y;
  300.   If e < 0 then
  301.     RDR := y/TEN(-e)
  302.   Else
  303.     If e<>0 then
  304.       RDR := y*TEN(e)
  305.     Else
  306.       RDR := y;
  307. 9: If fatal then RDR := 0.0;
  308. End{of RDR};
  309.  
  310.   (*********************************************)
  311.  
  312.  
  313.  
  314. Procedure STR( var S: Dstring;
  315.         tval: integer );
  316. { ENTER WITH:
  317.     tval = INTEGER to be converted to an alphanumeric
  318.            string.
  319.   RETURNS:
  320.     An alphanumeric equal of tval in S.
  321. }
  322. const
  323.     size = 15; { number of digits in the number }
  324. var
  325.     cix : char;
  326.     digits : packed array[1..10] of char;
  327.     i,        { length of number }
  328.     d,t,j: integer;
  329. begin
  330.   digits := '0123456789';
  331.   t := ABS(tval);
  332.   setlength(S,0);    { null string }
  333.   i := 0;
  334.   repeat { generate digits }
  335.     i := i + 1;
  336.     d := t MOD 10;
  337.     append(S,digits[d+1]);
  338.     t := t DIV 10
  339.   until (t=0) OR (i>=size);
  340.   If (tval<0) AND (i<size) then
  341.     begin { sign }
  342.     i := i + 1;
  343.     append(S,'-')
  344.     end;
  345.   j := 1;
  346.   while j<i do
  347.     begin{ reverse }
  348.     cix := S[i]; S[i] := S[j]; S[j] := cix;
  349.     i := i - 1;
  350.     j := j + 1
  351.     end{ revese }
  352. End{of STR};
  353.  
  354.   (*********************************************)
  355.  
  356.  
  357.  
  358. Procedure GetLine( VAR Agr_string : string80 ;
  359.                 count : integer );
  360. (*----------------------------------------------*)
  361. (* version: 31 MAY 80 by R.E.Penley        *)
  362. (* Valid Alphanumeric chars are:        *)
  363. (* from the ASCII space - CHR(32) to the    *)
  364. (*        ASCII tilde - CHR(126)        *)
  365. (* In order to get this to work with        *)
  366. (* Pascal/Z v 3.0 I have defined a line        *)
  367. (* as a string[80]                *)
  368. (*----------------------------------------------*)
  369. (*
  370. GLOBAL    StrMax = 255;
  371.     Mstring = STRING 255;
  372.     error  : boolean; <<to be returned to caller>>
  373. *)
  374. CONST    SPACE = ' ';
  375.     a_error = 'Alphanumerics only - ';
  376.     line_length = 80;
  377. VAR    InChar : char;
  378.     CHAR_COUNT : INTEGER;
  379.     ix : 1..StrMax;
  380. begin
  381.   error := false;
  382.   SETLENGTH( Agr_string, 0 );
  383.   CHAR_COUNT := 0;
  384.   REPEAT
  385.   If (count <= line_length) AND (CHAR_COUNT < count) then
  386.     begin{start accepting chars}
  387.     READ( InChar );
  388.     If InChar IN [' ' .. '~'] then{valid char}
  389.       begin{increment CHAR_COUNT and store InChar}
  390.     CHAR_COUNT := char_count + 1 ;
  391.     APPEND( Agr_string, InChar );
  392.       end(* If *)
  393.     Else (* we have a non-acceptable character *)
  394.       begin
  395.     WRITELN(a_error);
  396.     error:=TRUE
  397.       end(* else *)
  398.     end(* If *)
  399.   Else    (*   ERROR   *)
  400.     begin (* RESET EndOfLine <EOLN> *)
  401. {}    READLN( Agr_string[ CHAR_COUNT ] );
  402.       WRITELN('Maximum of', count:4, ' characters please!');
  403.       error:=TRUE
  404.     end(* else *)
  405.   UNTIL EOLN(INPUT) or error;
  406.   If error then{return a length of zero}
  407.     SETLENGTH( Agr_string, 0 );
  408. End{of GetLine};
  409.  
  410.  
  411.     {---------------------------------------}
  412.     {        UTILITY ROUTINES        }
  413.     {---------------------------------------}
  414.  
  415.  
  416.  
  417. Function UCase(ch : char) : char;
  418. (*---Returns an uppercase ASCII character---*)
  419. begin
  420.   If ch IN ['a'..'z'] then
  421.     UCase := CHR(ORD(ch) -32)
  422.   Else
  423.     UCase := ch
  424. end;
  425.  
  426.  
  427. Procedure DRAW(picture : Mstring ; count : integer);
  428. VAR    ix : integer;
  429. begin
  430.   For ix:=1 to count do
  431.     WRITE(picture);
  432. end;
  433.  
  434. Procedure DELAY(timer:integer);
  435. {  DELAY(10);    will give about 1 second delay }
  436. {  DELAY(5);    will give about 0.5 second delay }
  437. {  DELAY(30);    will give about 3 second delay }
  438. CONST    factor = 172;
  439. var    ix,jx : integer;
  440. begin
  441.   for ix:=1 to factor do
  442.     for jx:=1 to timer do {dummy};
  443. end;
  444.  
  445. Function QUIRY(message : string80) : boolean ;
  446. {    Try to write a general purpose        }
  447. {    routine that gets a 'YES' or 'NO'    }
  448. {    response from the user.            }
  449. VAR    ans : string 2;
  450.     valid : boolean;
  451. begin
  452.   Repeat
  453.     valid := false;
  454.     Write(message);
  455.     readln(ans);
  456.     If ans='OK' then
  457.       begin valid := true; QUIRY := true end
  458.     Else
  459.     If ans[1] IN ['Y','y','N','n'] then
  460.       begin
  461.         valid := true;
  462.         QUIRY := ( (ans='Y') or (ans='y') )
  463.       end
  464.   Until valid{response}
  465. end{of Quiry};
  466.  
  467. Procedure CLEAR;
  468. var    ix :1..25;
  469. begin
  470.   for ix:=1 to 25 do writeln
  471. end;
  472.  
  473. Procedure SKIP(n : integer);
  474. var    ix : 0..255;
  475. begin
  476.   for ix:=1 to n do writeln
  477. end;
  478.  
  479. Procedure PAUSE;
  480. CONST    sign = 'Enter return to continue ';
  481. var    ch : char;
  482. begin
  483.   write(sign);
  484.   readln(CH)
  485. end;
  486.  
  487. Procedure HEADER( title : string80 );
  488. CONST    left_margin  = 11;
  489.     right_margin = 51;
  490.     center         = 31;
  491.     dashes         = '{---------------------------------------}';
  492. VAR    F1,    {filler left side}
  493.     F2,    {filler right side}
  494.     CL,    {center line of title}
  495.     len    {length of title}
  496.          : integer;
  497. begin
  498.   len := LENGTH(title);
  499.   CL := len DIV 2;
  500.   {If length of title is odd then increase CL by one}
  501.   If ODD(len) then CL := CL +1;
  502.   F1 := (center - CL) - left_margin;
  503.   {If length of title is even then reduce F1 by 1   }
  504.   If not ODD(len) then F1 := F1 - 1;
  505.   F2 := right_margin - (center + CL);
  506.   writeln(' ':left_margin,dashes);
  507.   writeln(' ':left_margin,'{',' ':F1,title,' ':F2,'}');
  508.   writeln(' ':left_margin,dashes);
  509. end;
  510.  
  511.     {---------------------------------------}
  512.