home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / C4PAS000.ZIP / C4PAS000.DOC next >
Encoding:
Text File  |  1990-05-04  |  22.6 KB  |  643 lines

  1.                               C4PAS000 
  2.  
  3.                  C routines for Turbo Pascal 5.5 
  4.  
  5.                         Copyright (C) 1990 
  6.  
  7.                              Bill Weaks 
  8.                             3303 37th St 
  9.                         Lubbock, TX   79413 
  10.  
  11. All rights reserved except as otherwise indicated in this 
  12. document. 
  13.  
  14. C4PAS000 is a collection of some useful C routines that don't
  15. have a direct counterpart in Turbo Pascal.  Having cut my
  16. programming teeth in Pascal, I still enjoy the language
  17. immensely, and use it as my language of choice.
  18.  
  19. I had to learn C for one of my clients, and found several useful
  20. functions in that language that I could have used in Turbo
  21. Pascal.  I have coded them in Pascal and/or assembly language and
  22. put them in this unit that can be used with version 5.5 of that
  23. compiler.  These are mostly string routines, but there are some
  24. others here to boot.
  25.  
  26. But before we examine these routines, we need to get some
  27. formalities out of the way in the front of this document:
  28.  
  29.  ************* LICENSING INFORMATION ************* 
  30.  
  31. This unit is intended as a demonstration package only:  NO
  32. LICENSE IS TRANSFERRED WITH IT!!!  If you intend to, or actually
  33. do use any of these routines in your own applications - personal,
  34. private, commercial or otherwise, you will need to obtain a
  35. legitimate license by doing the following:
  36.  
  37. Send $30.00 to:
  38.  
  39. Bill Weaks
  40. 3303 37th Street
  41. Lubbock, TX   79413
  42.  
  43. Upon receipt, you will be sent the latest version of this
  44. software along with full source in Turbo Pascal and assembly
  45. language and a license to use the software in any application you
  46. may compile and distribute.
  47.  
  48. There are several reasons to do this:  First, it's the only legal
  49. and moral way.  Second, Borland has been very good about
  50. upgrading it's compilers, but the units generally have to be
  51. re-compiled to work with the new versions.  Since you can't do
  52. this without the source, if you are going to use any of these
  53. routines in future versions, you will need either a new version,
  54. or the source.  
  55.  
  56. Texas residents will need to add sales tax (currently $1.95) to
  57. their orders.
  58.  
  59. Subject to those restrictions, anybody can copy this software and
  60. distribute it so long as they do not charge more than $10.00 for
  61. media, handling and operating profit charges.  In fact, you are
  62. encouraged to do so.
  63.  
  64. Turbo Pascal is a trademark of Borland International, the best
  65. software company on the face of the earth.
  66.  
  67.  ************* DISCLAIMER ************* 
  68.  
  69. The author disclaims any and all responsibility for the
  70. reliability of the software in this unit.  By using this
  71. software, User accepts all liability for performance, and
  72. indemnifies author against any and all claims.  It works as far
  73. as I know, but I've got to say that.
  74.  
  75. Registered users may report bugs by mailing a description of the
  76. problem, the version of the Unit and sample source to the above
  77. address.  If the bug is legitimate, the sender will receive a
  78. free updated version with the fix.
  79.  
  80. Non-registered users are encouraged to send in bug reports, also. 
  81. In the event that a non-registered user is the first to report a
  82. bug, he or she will automatically become a registered user, and a
  83. free copy of the program, with source, will me sent to them with
  84. my thanks.
  85.  
  86.  
  87.  **********  THE UNIT ********** 
  88.  
  89. The following is the unit header, excluding the actual
  90. declarations of the functions and procedures:
  91.  
  92. unit c4pas000;
  93.  
  94. interface
  95.  
  96. uses dos,crt;
  97.  
  98. type _dtstr=string[26];
  99.      str_ptr = ^string;
  100.      _pass_str=string[8];
  101.  
  102. const
  103. _days_o_week:array[0..6] of array[1..3] of char =
  104. {days of the week}
  105. ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
  106.  
  107. _mos_o_year:array[1..12] of array[1..3] of char =         
  108. {months of the year}
  109. ('Jan','Feb','Mar','Apr','May','Jun',
  110.  'Jul','Aug','Sep','Oct','Nov','Dec');
  111.  
  112.  
  113. dr_found :byte = $01;                { drive found in file spec }
  114. dir_found:byte = $02;            { directory found in file spec }
  115. nm_found :byte = $04;                 { name found in file spec }
  116. ext_found:byte = $08;            { extension found in file spec }
  117. wdc_name :byte = $10;            { wild card char found in name }
  118. wdc_ext  :byte = $20;            { wild card found in extension }
  119.  
  120. csense:boolean = true;                  {case sensitive searches}
  121. ncsense:boolean = false;            {non case sensitive searches}
  122.  
  123. var
  124.     NULL:str_ptr;
  125.     nullstr:string[1];
  126.  
  127. These constants, types and variables are available to any module
  128. that incorporates C4PAS000 with a "uses" statement.  They are
  129. used by the internal routines, and I made them public since they
  130. will take up space anyway; why not use them in your routines if
  131. they are helpful?  Unlike C, TP's linker will strip them out if
  132. you don't access them.  Pretty nice, eh?
  133.  
  134. Their utility and uses will be made clear as you peruse the
  135. routines below.  I have divided them by category, and hope that
  136. you will find them of interest.
  137.  
  138.  ********** ROUTINES INCLUDED IN C4PAS000 ********** 
  139.  
  140. First, I start all identifiers with an underscore to try and
  141. eliminate conflicts with other libraries, including your own.  If
  142. you tire of including them, then you should register, get the
  143. source code, and eliminate them!!  I know I would.  If you have
  144. conflicts regardless, you can always identify the one you are
  145. looking for by typing:
  146.  
  147.   c4pas000.<identifier>
  148.  
  149. where <identifier> is the function or procedure that you are
  150. looking for.
  151.  
  152. ****** 
  153.  
  154. The following routines I have found very useful, and should more
  155. than pay for the cost of this library if you use them even once!! 
  156. The first two aren't even TP implementations of C routines, just
  157. better versions of TP routines.  I put them in here anyway.
  158.  
  159. ******
  160.  
  161. >>> procedure _ffill(var dest; ccount:word; fillval:byte); <<<
  162. Assembly language.  This is a faster version of the Turbo Pascal
  163. FillChar procedure.  It is actually up to 48% faster.  There's no
  164. magic, but it does work that way.  Use this to fill arrays with a
  165. predetermined value, or to null out a series of variables with
  166. one call.
  167.  
  168. >>> procedure _fmove(var source,dest; ccount:word); <<<
  169. Assembly language.  This is a faster version of the Turbo Pascal
  170. Move procedure.  Again, no magic, but it is up to 24% faster than
  171. the normal version.  
  172.  
  173. You will find that you can save even more by using _fmove instead
  174. of assigning records.  For instance, you can assign one record's
  175. contents to another by simply using the ":=" assignment operator. 
  176. This merely moves the contents of one record into the other.  If
  177. you do a lot of this, using _fmove can really speed things up.
  178.  
  179. >>> procedure _strrev(var st:string); <<<
  180. Assembly language routine reverses all characters in the string
  181. passed up.
  182.  
  183. >>> procedure _strupr(var st:string); <<<
  184. Assembly language routine converts all characters in the string
  185. passed up to their uppercase equivalents if they exist.
  186.  
  187. >>> procedure _strlwr(var st:string); <<<
  188. Assembly language routine converts all characters in the string
  189. passed up to their lowercase equivalents if they exist.
  190.  
  191. >>> function _strrchr(var st:string;
  192.                targ:char;
  193.                   nocase:boolean):integer; <<<
  194.  
  195. Assembly language routine returns the index into the string
  196. passed up of the last occurrence of the char passed in targ.  If
  197. nocase is TRUE (use the const csense) then a strict case
  198. sensitive search is made.  If nocase is FALSE (use the const
  199. ncsense) then a non-case sensitive search is made of the string. 
  200. Returns a 0 if the char is not found.  
  201.  
  202. EXAMPLE:
  203.  
  204. var st:string;
  205.     i:integer;
  206.  
  207. begin
  208.   st:='D:\TURBO5\SOURCE\*.PAS';
  209.   writeln(_strrchr(st,'\',csense));
  210. end.
  211.  
  212. This would result in the number 17 being printed to the screen,
  213. as that is the index of the last occurrence of the backslash
  214. character.  Using non-case sensitive searches will be a tad
  215. faster, since the conversion doesn't have to take place with each
  216. character of the string.
  217.  
  218.  
  219. >>> function _stricmp(var st1,st2:string):integer; <<<
  220. Assembly language routine returns a value based upon a case
  221. insensitive comparison of the two strings passed up.  Returns a
  222. value of 0 if the strings are equal, a value greater than 0 if
  223. st1 is greater than st2, and a value less than 0 if st1 is less
  224. than st2.
  225.  
  226. _stricmp will not search more than the length of the shorter of
  227. the two, that is, if st1 has a length of 20, and st2 has a length
  228. of 30, the routine will only search 20 chars.  If the string were
  229. identical for the first 20 chars, the routine would return a
  230. negative number, since st2 still contained characters.
  231.  
  232. EXAMPLE:
  233.  
  234. var st1,st2:string;
  235.  
  236. begin
  237.   st1:='Hello There';
  238.   st2:="hello there yourself';
  239.   writeln(_stricmp(st1,st2));
  240. end.
  241.  
  242. This would result in a negative number being printed on the
  243. screen, since st1 was less than st2.  REMEMBER:  the comparison
  244. is not case sensitive!!!  Turbo Pascal already has the capability
  245. to perform case sensitive comparisons of strings.  This could
  246. speed up things since you don't need to uppercase the strings
  247. first to check for equality.
  248.  
  249. Those of you who get the source should find it easy to make a
  250. version of strnicmp, which will only search a maximum number of
  251. chars OR the shorter of the two strings.
  252.  
  253. >>> function _strcspn(var org,targ:string):integer; <<<
  254. Returns the length of the first part of string org that does not
  255. contain any of the characters found in string targ.  That is, it
  256. starts at character one of string org and checks to see if it is
  257. in targ.  If not, it checks the next char in string org.  If none
  258. of the chars are found in targ, returns the length of org.
  259.  
  260. EXAMPLE:
  261.  
  262. var st1,st2:string;
  263.  
  264. begin
  265.   st1:='Hello';
  266.   st2:='+-*/';
  267.   writeln(_strcspn(st1,st2));
  268. end.
  269.  
  270. This would result in the number 5 being printed on the screen,
  271. since st1 contains none of the letters found in st2.
  272.  
  273. >>> function _strspn(var org,targ:string):integer; <<<
  274. This is the reverse of _strcspn.  It returns the length of the
  275. inital part of string org that consists entirely of chars found
  276. in the string targ.  If none of the chars are found, it would
  277. return a 0.  
  278.  
  279. The source shown above would result in the number 0 being printed
  280. to the screen.
  281.  
  282. >>> function _strtok(var org,
  283.                  dest:string;
  284.               targ:string;
  285.               appendchar:boolean):char; <<<
  286.  
  287. This is probably my favorite of all of these routines.  It is a
  288. general purpose token parser that can be invoked numerous times
  289. and search for various tokens defined by many delimiters.  It is
  290. quite powerful and with some imagination I'm sure you will find
  291. many uses for it.
  292.  
  293. This routine takes the initial argument, string org, and then
  294. searches it for the first occurrence of any of the characters in
  295. the string targ.  The resultant string (that is, the initial part
  296. of org up to the char tagged) is placed into the string dest. 
  297. The parameter appendchar is TRUE or FALSE, based upon whether or
  298. not you wish the delimiter to be appended to the string dest.  
  299.  
  300. You may "whittle" the original string down, token by token, until
  301. the string is exhausted by using the variable "nullstr" (defined
  302. in the interface of the unit) instead of your original source
  303. string after the first call to _strtok.
  304.  
  305. The string org is not modified, as it is in the C version.  We
  306. keep an internal string that is used for subsequent calls to the
  307. routine.  Consider this example for counting words in a text
  308. file:
  309.  
  310. program wordcount;
  311.  
  312. uses crt,c4pas000;
  313.  
  314. var f1:text;
  315.     wcount:word;
  316.     st1,st2:string;
  317.     ch:char;
  318.  
  319. begin
  320.   assign(f1,'Myfile.txt');
  321.   reset(f1);
  322.   wcount:=0;
  323.   while not eof(f1) do
  324.     begin
  325.       readln(f1,st1);
  326.       ch:=_strtok(st1,st2,' ',false); {init and get first token}
  327.       repeat
  328.         { eliminate multiple spaces }
  329.         if ch = ' ' and st2 <> ' ' then inc(wcount);
  330.         ch:=_strtok(nullstr,st2,' ',false);
  331.       until ch = #0;
  332.       if (ch = #0) and (st2 <> '') then inc(wcount);{last token?}
  333.     end;
  334.   close(f1);
  335.   writeln(wcount);
  336. end.
  337.  
  338. Further, since the routine parses up to the first occurrence of
  339. any of the characters in targ, it makes a dandy equation parser,
  340. or a handy routine for reading in a comma delimited file from
  341. another program.  Take this code for an equation parser:
  342.  
  343. begin
  344.   write('Enter equation => ');
  345.   readln(st1);
  346.   ch:=_strtok(st1,st2,'()*+-/=',false);
  347.   repeat
  348.     case ch of
  349.       '(':;     {appropriate code here to evaluate}
  350.       ')':;
  351.       '*':;
  352.        etc,etc.
  353.     end; {case}
  354.     ch:=_strtok(nullstr,st2,'()*+-/=',false);
  355.   until ch = #0;
  356. end.
  357.  
  358. Of course, you could have assigned the string '()*+-/=' to a
  359. variable named "mathstr" or something and saved some complicated
  360. typing (and some .EXE size).  I really hope you like this
  361. function.
  362.  
  363. >>> function _fnsplit(pathh :string;
  364.                  ddrive:str_ptr;
  365.                  ddir  :str_ptr;
  366.                  nname :str_ptr;
  367.                  eext  :str_ptr
  368.                 ):integer; <<<
  369.  
  370. Turbo Pascal provides a similar routine, but I liked the C
  371. version better, and decided to include a spiffed up version of
  372. it.  _fnsplit takes a filename string (pathh) and breaks it up
  373. into it's various components.  It then deposits those components
  374. into the appropriate string passed up by reference.
  375.  
  376. There are a few quirks to this one, however:  If you pass up the
  377. value NULL (defined in the interface) then the routine will NOT
  378. attempt to deposit the token, but will just go on.  That way, if
  379. you are only interested in the drive, perhaps, or just the
  380. extension of a file name, you only need one string to pass up.  
  381.  
  382. The routine also returns an integer that is concocted of the
  383. following values (also defined in the interface):
  384.  
  385. dr_found :byte = $01;                { drive found in file spec }
  386. dir_found:byte = $02;            { directory found in file spec }
  387. nm_found :byte = $04;                 { name found in file spec }
  388. ext_found:byte = $08;            { extension found in file spec }
  389. wdc_name :byte = $10;            { wild card char found in name }
  390. wdc_ext  :byte = $20;            { wild card found in extension }
  391.  
  392. By 'and-ing' the result of _fnsplit with these values you can
  393. determine whether any or all of the various components were found
  394. in the string passed up.  I added the two wild card values so
  395. that if a '?' or '*' are present in either the file name or
  396. extension, these values will be present in the result of the
  397. function.  The values are just added into the result as each
  398. becomes true.  The maximum value that _fnsplit can currently
  399. return is, therefore, $3f.
  400.  
  401. EXAMPLE:
  402.  
  403. var i:integer;
  404.     xdrv,dir,name,ext:string; 
  405.  
  406.   i:=_fnsplit('D:\TURBO5\SRC\*.PAS',@drv,@dir,@name,@ext);
  407.  
  408. Would result in the value $1f being assigned to i.  The string
  409. drv would contain 'D:'; the string dir would contain
  410. '\TURBO5\SRC\'; the string name would contain '*', and the string
  411. ext would contain '.PAS'.  And-ing the variable i with "wdc_name"
  412. would result in "wdc_name", telling you that a wildcard was found
  413. in the file name.  If you were only interested in the extension,
  414. you could write something like this:
  415.  
  416.   i:=_fnsplit('D:\TURBO5\SRC\*.PAS',NULL,NULL,NULL,@@ext);
  417.  
  418. In this case, i would contain the value "ext_found", since the
  419. routine didn't check for anything else.  The ability to check for
  420. a particular component saves time and variable space.  This
  421. should be a useful function also.
  422.  
  423. >>> function getpass(llenn:byte;echo:char):string; <<<
  424. This function allows your application to get a hidden password
  425. from a user.  It returns a string with a maximum length of llenn. 
  426. You can pass up a character which will be echoed to the screen
  427. regardless of which key the user may press.  If the echo char is
  428. #0, the routine will print the number of the keypress mod 10. 
  429. this is useful for telling the user how many chars they have
  430. entered.  
  431.  
  432. The function ends when it encounters a carriage return or llenn
  433. chars have been read.  This routine takes anything, including
  434. backspaces, so be aware when entering the password that mistakes
  435. are not tolerated!
  436.  
  437. EXAMPLE:
  438.  
  439. program getpassword;
  440.  
  441. uses dos, c4pas000;
  442.  
  443. var st:_pass_str;  {defined in c4pas000}
  444. begin
  445.   clrscr;
  446.   gotoxy(1,12);
  447.   write('Enter your password, please => ');
  448.   st:=getpass(sizeof(st)-1,'*');
  449.   _strupr(st);
  450.   if st <> 'GORILLAS' then halt;
  451. end.
  452.  
  453. This would return a string with a maximum of 8 chars, printing an
  454. asterisk on the screen whenever a user touched the keyboard. The
  455. line would look like this:
  456.  
  457. Enter your password, please => ********
  458.  
  459. If you were to pass up a char #0 as echo, the screen would look
  460. like this:
  461.  
  462. Enter your password, please => 12345678
  463.  
  464.  
  465. >>> function _asctime:_dtstr; <<<
  466.  
  467. Converts current system date and time to 26 char ASCII string
  468. according to the template:
  469.  
  470. Wed Apr 10 13:45:48 1990
  471.  
  472. The appropriate information is obtained from DOS and then placed
  473. into the string that is returned.  By using a variable of type
  474. _dtstr, you will be assured that you will have the precise amount
  475. of room necessary to receive the information.
  476.  
  477. EXAMPLE:
  478.  
  479. var dstr:_ststr;
  480.     { get system date and time into string dstr }
  481. begin
  482.   dstr:=_asctime;
  483.   writeln(dstr);
  484. end;
  485.  
  486. You could also just have used a simple 
  487.  
  488.   writeln(_asctime);
  489.  
  490. if you only wanted to display the info.
  491.  
  492.  ******** 
  493.  
  494. Most of the following functions are performed via a table lookup
  495. for speed.  Those of you who obtain the source code could modify
  496. the table to suit specialized needs.
  497.  
  498.  ******** 
  499.  
  500. >>> function _isalnum(ch:char):boolean; <<<
  501. Returns TRUE if the char passed up is in the range '0'..'9',
  502. 'A'..'Z', 'a'..'z'.  Returns FALSE if any other char.
  503.  
  504. >>> function _isalpha(ch:char):boolean; <<<
  505. Returns TRUE if the char passed up is in the range 'A'..'Z',
  506. 'a'..'z'.  Returns FALSE if any other char.
  507.  
  508. >>> function _isascii(ch:char):boolean; <<<
  509. Returns  TRUE if the ordinal value of the char passed up is <
  510. 128.  Returns FALSE if 128 or greater.
  511.  
  512. >>> function _iscntrl(ch:char):boolean; <<<
  513. Returns TRUE if the ordinal value of the char passed up is in the
  514. range 0..31 ($00..$2f).  Returns FALSE if any other value.
  515.  
  516. >>> function _isdigit(ch:char):boolean; <<<
  517. Returns TRUE if the char passed up is in the range '0'..'9'. 
  518. Returns FALSE if any other char;
  519.  
  520. >>> function _isgraph(ch:char):boolean; <<<
  521. Returns TRUE if the char passed up will actually show up on when
  522. displayed.  That is, if the result of printing ch is visible.  It
  523. includes all characters from '!'..'~'($33..$7e).  Returns FALSE
  524. if any other char.  Note that the extended character set is not
  525. included, since it is not straight ASCII.  See _isextended for
  526. info on these chars.
  527.  
  528. >>> function _islower(ch:char):boolean; <<<
  529. Returns TRUE if char passed up is in range 'a'..'z'.  Returns
  530. FALSE for any other char.
  531.  
  532. >>> function _isprint(ch:char):boolean; <<<
  533. Similar to _isgraph, but returns TRUE for space char also.
  534.  
  535. >>> function _ispunct(ch:char):boolean; <<<
  536. Returns TRUE if the char passed up is one of the following
  537. punctuation marks:  !"',-.:;?`.  Returns FALSE if any other char;
  538.  
  539. >>> function _isspace(ch:char):boolean; <<<
  540. Returns TRUE if char passed up is a spacing char, that is, one
  541. that moves the cursor or print head without leaving any visible
  542. result.  These chars include the control chars tab, carriage
  543. return, newline, vertical tab, or formfeed ($09..$0d) and the
  544. space char itself ($20).  Returns FALSE if any other char.
  545.  
  546. >>> function _isupper(ch:char):boolean; <<<
  547. Returns TRUE if char passed up is in the range 'A'..'Z'.  Returns
  548. FALSE if any other char.
  549.  
  550. >>> function _isxdigit(ch:char):boolean; <<<
  551. Returns TRUE if char passed up is a hexadecimal character, that
  552. is, '0'..'9', 'A'..'F','a'..'f'.  Returns FALSE if any other
  553. char.
  554.  
  555. >>> function _isextended(ch:char):boolean; <<<
  556. Returns TRUE if the char passed up is one of the IBM extended
  557. characters, that is a char that normally wouldn't print if taken
  558. as straight ASCII.  This includes all chars outside the normal
  559. ASCII range ($00..$2f,$7f..$255).  Returns FALSE if any other
  560. char.  No C equivalent, but there should have been?
  561.  
  562. >>> function _tolower(ch:char):char; <<<
  563. Returns the lowercase equivalent of char passed up if
  564. appropriate.  If not, returns char.
  565.  
  566. >>> function _toupper(ch:char):char; <<<
  567. Returns the uppercase equivalent of char passed up if
  568. appropriate.  If not, returns char.
  569.  
  570.  ******** 
  571.  
  572. The following are some useful routines I incorporated to make
  573. your life a little easier.  The min routines (_bytemin.._realmin)
  574. all return the smaller of the two values passed up to them.  The
  575. max routines (_bytemax.._realmax) all return the larger of the
  576. two values passed up.  If they are equal the b value is returned
  577. in all cases.  Remember that reals are tricky when you are
  578. determining lesser or greater:  The difference may be minimal at
  579. best!
  580.  
  581. C is nice in that this is implemented as a macro that is
  582. type-independent.  Pascal isn't so flexible, so we need a
  583. separate routine for each type.
  584.  
  585.  ******** 
  586.  
  587. >>> function _bytemin(a,b:byte)     :byte;    <<<
  588. >>> function _intmin(a,b:integer)   :integer; <<<
  589. >>> function _wordmin(a,b:word)     :word;    <<<
  590. >>> function _longmin(a,b:longint)  :longint; <<<
  591. >>> function _charmin(a,b:char)     :char;    <<<
  592. >>> function _realmin(a,b:real)     :real;    <<<
  593.  
  594. >>> function _bytemax(a,b:byte)     :byte;    <<<
  595. >>> function _intmax(a,b:integer)   :integer; <<<
  596. >>> function _wordmax(a,b:word)     :word;    <<<
  597. >>> function _longmax(a,b:longint)  :longint; <<<
  598. >>> function _charmax(a,b:char)     :char;    <<<
  599. >>> function _realmax(a,b:real)     :real;    <<<
  600.  
  601.  ******** 
  602. These two are just inline procedures for disabling and enabling
  603. interrupts.  Useful when reading ports or changing program
  604. contexts.
  605.  ******** 
  606.  
  607. >>> procedure _disable;inline($fa); <<<
  608. >>> procedure _enable; inline($fb); <<<
  609.  
  610.  ******** 
  611. Peeks and pokes are useful at times, and I included these to peek
  612. and poke various types of integers.  Use the PTR function to
  613. provide an address.  You can also use the @ operator to cast
  614. values, but there are probably better ways of doing that.
  615.  ******** 
  616.  
  617. >>> function  _peek (p:pointer):word;    <<<
  618. >>> function  _peeki(p:pointer):integer; <<<
  619. >>> function  _peekb(p:pointer):byte;    <<<
  620. >>> function  _peekl(p:pointer):longint; <<<
  621.  
  622. >>> procedure _poke (p:pointer;w:word);    <<<
  623. >>> procedure _pokei(p:pointer;i:integer); <<<
  624. >>> procedure _pokeb(p:pointer;b:byte);    <<<
  625. >>> procedure _pokel(p:pointer;l:longint); <<<
  626.  
  627. EXAMPLE:
  628.  
  629. { DOS keeps the timer ticks since midnight in a longint at
  630.   $0000:$046c.Do a loop and count the ticks that it took }
  631.  
  632. var dosticks:pointer;
  633.     i:integer;
  634.     time1:longint;
  635.  
  636. begin
  637.   dosticks:=ptr($0000,$046c);
  638.   time1:=_peekl(dosticks);
  639.   for i:=1 to 10000 do;  {null loop}
  640.   writeln('It took ',_peekl(dosticks) - time1,
  641.           ' ticks to do that loop');
  642. end.
  643.