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

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