sysatari.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Carl Eric Codere
  5. member of the Free Pascal development team
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$define ATARI}
  13. unit sysatari;
  14. {--------------------------------------------------------------------}
  15. { LEFT TO DO: }
  16. {--------------------------------------------------------------------}
  17. { o SBrk }
  18. { o Implement truncate }
  19. { o Implement paramstr(0) }
  20. {--------------------------------------------------------------------}
  21. {$I os.inc}
  22. interface
  23. { used for single computations }
  24. const BIAS4 = $7f-1;
  25. {$I systemh.inc}
  26. {$I heaph.inc}
  27. const
  28. UnusedHandle = $ffff;
  29. StdInputHandle = 0;
  30. StdOutputHandle = 1;
  31. StdErrorHandle = $ffff;
  32. implementation
  33. {$I system.inc}
  34. {$I lowmath.inc}
  35. const
  36. argc : longint = 0;
  37. var
  38. errno : integer;
  39. {$S-}
  40. procedure Stack_Check; assembler;
  41. { Check for local variable allocation }
  42. { On Entry -> d0 : size of local stack we are trying to allocate }
  43. asm
  44. XDEF STACKCHECK
  45. move.l sp,d1 { get value of stack pointer }
  46. sub.l d0,d1 { sp - stack_size }
  47. sub.l #2048,d1
  48. cmp.l __BREAK,d1
  49. bgt @st1nosweat
  50. move.l #202,d0
  51. jsr HALT_ERROR
  52. @st1nosweat:
  53. end;
  54. Procedure Error2InOut;
  55. Begin
  56. if (errno <= -2) and (errno >= -11) then
  57. InOutRes:=150-errno { 150+errno }
  58. else
  59. Begin
  60. case errno of
  61. -32 : InOutRes:=1;
  62. -33 : InOutRes:=2;
  63. -34 : InOutRes:=3;
  64. -35 : InOutRes:=4;
  65. -36 : InOutRes:=5;
  66. -37 : InOutRes:=8;
  67. -39 : InOutRes:=8;
  68. -40 : InOutRes:=9;
  69. -46 : InOutRes:=15;
  70. -67..-64 : InOutRes:=153;
  71. -15 : InOutRes:=151;
  72. -13 : InOutRes:=150;
  73. else
  74. InOutres := word(errno);
  75. end;
  76. end;
  77. errno:=0;
  78. end;
  79. procedure halt(errnum : byte);
  80. begin
  81. do_exit;
  82. flush(stderr);
  83. asm
  84. clr.l d0
  85. move.b errnum,d0
  86. move.w d0,-(sp)
  87. move.w #$4c,-(sp)
  88. trap #1
  89. end;
  90. end;
  91. function args : pointer; assembler;
  92. asm
  93. move.l __ARGS,d0
  94. end;
  95. Function GetParamCount(const p: pchar): longint;
  96. var
  97. i: word;
  98. count: word;
  99. Begin
  100. i:=0;
  101. count:=0;
  102. while p[count] <> #0 do
  103. Begin
  104. if (p[count] <> ' ') and (p[count] <> #9) and (p[count] <> #0) then
  105. Begin
  106. i:=i+1;
  107. while (p[count] <> ' ') and (p[count] <> #9) and (p[count] <> #0) do
  108. count:=count+1;
  109. end;
  110. if p[count] = #0 then break;
  111. count:=count+1;
  112. end;
  113. GetParamCount:=longint(i);
  114. end;
  115. Function GetParam(index: word; const p : pchar): string;
  116. { On Entry: index = string index to correct parameter }
  117. { On exit: = correct character index into pchar array }
  118. { Returns correct index to command line argument }
  119. var
  120. count: word;
  121. localindex: word;
  122. l: byte;
  123. temp: string;
  124. Begin
  125. temp:='';
  126. count := 0;
  127. { first index is one }
  128. localindex := 1;
  129. l:=0;
  130. While p[count] <> #0 do
  131. Begin
  132. if (p[count] <> ' ') and (p[count] <> #9) then
  133. Begin
  134. if localindex = index then
  135. Begin
  136. while (p[count] <> #0) and (p[count] <> ' ') and (p[count] <> #9) and (l < 256) do
  137. Begin
  138. temp:=temp+p[count];
  139. l:=l+1;
  140. count:=count+1;
  141. end;
  142. temp[0]:=char(l);
  143. GetParam:=temp;
  144. exit;
  145. end;
  146. { Point to next argument in list }
  147. while (p[count] <> #0) and (p[count] <> ' ') and (p[count] <> #9) do
  148. Begin
  149. count:=count+1;
  150. end;
  151. localindex:=localindex+1;
  152. end;
  153. if p[count] = #0 then break;
  154. count:=count+1;
  155. end;
  156. GetParam:=temp;
  157. end;
  158. function paramstr(l : longint) : string;
  159. var
  160. p : pchar;
  161. s1 : string;
  162. begin
  163. if l = 0 then
  164. Begin
  165. s1 := '';
  166. end
  167. else
  168. if (l>0) and (l<=paramcount) then
  169. begin
  170. p:=args;
  171. paramstr:=GetParam(word(l),p);
  172. end
  173. else paramstr:='';
  174. end;
  175. function paramcount : longint;
  176. Begin
  177. paramcount := argc;
  178. end;
  179. procedure randomize;
  180. var
  181. hl : longint;
  182. begin
  183. asm
  184. movem.l d2/d3/a2/a3, -(sp) { save OS registers }
  185. move.w #17,-(sp)
  186. trap #14 { call xbios - random number }
  187. add.l #2,sp
  188. movem.l (sp)+,d2/d3/a2/a3
  189. move.l d0,hl { result in d0 }
  190. end;
  191. randseed:=hl;
  192. end;
  193. function getheapstart:pointer;assembler;
  194. asm
  195. lea.l HEAP,a0
  196. move.l a0,d0
  197. end;
  198. function getheapsize:longint;assembler;
  199. asm
  200. move.l HEAP_SIZE,d0
  201. end ['D0'];
  202. { This routine is used to grow the heap. }
  203. { But here we do a trick, we say that the }
  204. { heap cannot be regrown! }
  205. function sbrk( size: longint): longint;
  206. { on exit -1 = if fails. }
  207. Begin
  208. sbrk:=-1;
  209. end;
  210. {$I heap.inc}
  211. {****************************************************************************
  212. Low Level File Routines
  213. ****************************************************************************}
  214. procedure AllowSlash(p:pchar);
  215. var
  216. i : longint;
  217. begin
  218. { allow slash as backslash }
  219. for i:=0 to strlen(p) do
  220. if p[i]='/' then p[i]:='\';
  221. end;
  222. procedure do_close(h : longint);
  223. begin
  224. asm
  225. movem.l d2/d3/a2/a3,-(sp)
  226. move.l h,d0
  227. move.w d0,-(sp)
  228. move.w #$3e,-(sp)
  229. trap #1
  230. add.l #4,sp { restore stack ... }
  231. movem.l (sp)+,d2/d3/a2/a3
  232. end;
  233. end;
  234. procedure do_erase(p : pchar);
  235. begin
  236. AllowSlash(p);
  237. asm
  238. move.l d2,d6 { save d2 }
  239. movem.l d3/a2/a3,-(sp) { save regs }
  240. move.l p,-(sp)
  241. move.w #$41,-(sp)
  242. trap #1
  243. add.l #6,sp
  244. move.l d6,d2 { restore d2 }
  245. movem.l (sp)+,d3/a2/a3
  246. tst.w d0
  247. beq @doserend
  248. move.w d0,errno
  249. @doserend:
  250. end;
  251. if errno <> 0 then
  252. Error2InOut;
  253. end;
  254. procedure do_rename(p1,p2 : pchar);
  255. begin
  256. AllowSlash(p1);
  257. AllowSlash(p2);
  258. asm
  259. move.l d2,d6 { save d2 }
  260. movem.l d3/a2/a3,-(sp)
  261. move.l p1,-(sp)
  262. move.l p2,-(sp)
  263. clr.w -(sp)
  264. move.w #$56,-(sp)
  265. trap #1
  266. lea 12(sp),sp
  267. move.l d6,d2 { restore d2 }
  268. movem.l (sp)+,d3/a2/a3
  269. tst.w d0
  270. beq @dosreend
  271. move.w d0,errno { error ... }
  272. @dosreend:
  273. end;
  274. if errno <> 0 then
  275. Error2InOut;
  276. end;
  277. function do_isdevice(handle:word):boolean;
  278. begin
  279. if (handle=stdoutputhandle) or (handle=stdinputhandle) or
  280. (handle=stderrorhandle) then
  281. do_isdevice:=FALSE
  282. else
  283. do_isdevice:=TRUE;
  284. end;
  285. function do_write(h,addr,len : longint) : longint;
  286. begin
  287. asm
  288. move.l d2,d6 { save d2 }
  289. movem.l d3/a2/a3,-(sp)
  290. move.l addr,-(sp)
  291. move.l len,-(sp)
  292. move.l h,d0
  293. move.w d0,-(sp)
  294. move.w #$40,-(sp)
  295. trap #1
  296. lea 12(sp),sp
  297. move.l d6,d2 { restore d2 }
  298. movem.l (sp)+,d3/a2/a3
  299. tst.l d0
  300. bpl @doswrend
  301. move.w d0,errno { error ... }
  302. @doswrend:
  303. move.l d0,@RESULT
  304. end;
  305. if errno <> 0 then
  306. Error2InOut;
  307. end;
  308. function do_read(h,addr,len : longint) : longint;
  309. begin
  310. asm
  311. move.l d2,d6 { save d2 }
  312. movem.l d3/a2/a3,-(sp)
  313. move.l addr,-(sp)
  314. move.l len,-(sp)
  315. move.l h,d0
  316. move.w d0,-(sp)
  317. move.w #$3f,-(sp)
  318. trap #1
  319. lea 12(sp),sp
  320. move.l d6,d2 { restore d2 }
  321. movem.l (sp)+,d3/a2/a3
  322. tst.l d0
  323. bpl @dosrdend
  324. move.w d0,errno { error ... }
  325. @dosrdend:
  326. move.l d0,@Result
  327. end;
  328. if errno <> 0 then
  329. Error2InOut;
  330. end;
  331. function do_filepos(handle : longint) : longint;
  332. begin
  333. asm
  334. move.l d2,d6 { save d2 }
  335. movem.l d3/a2/a3,-(sp)
  336. move.w #1,-(sp) { seek from current position }
  337. move.l handle,d0
  338. move.w d0,-(sp)
  339. move.l #0,-(sp) { with a seek offset of zero }
  340. move.w #$42,-(sp)
  341. trap #1
  342. lea 10(sp),sp
  343. move.l d6,d2 { restore d2 }
  344. movem.l (sp)+,d3/a2/a3
  345. move.l d0,@Result
  346. end;
  347. end;
  348. procedure do_seek(handle,pos : longint);
  349. begin
  350. asm
  351. move.l d2,d6 { save d2 }
  352. movem.l d3/a2/a3,-(sp)
  353. move.w #0,-(sp) { seek from start of file }
  354. move.l handle,d0
  355. move.w d0,-(sp)
  356. move.l pos,-(sp)
  357. move.w #$42,-(sp)
  358. trap #1
  359. lea 10(sp),sp
  360. move.l d6,d2 { restore d2 }
  361. movem.l (sp)+,d3/a2/a3
  362. end;
  363. end;
  364. function do_seekend(handle:longint):longint;
  365. var
  366. t: longint;
  367. begin
  368. asm
  369. move.l d2,d6 { save d2 }
  370. movem.l d3/a2/a3,-(sp)
  371. move.w #2,-(sp) { seek from end of file }
  372. move.l handle,d0
  373. move.w d0,-(sp)
  374. move.l #0,-(sp) { with an offset of 0 from end }
  375. move.w #$42,-(sp)
  376. trap #1
  377. lea 10(sp),sp
  378. move.l d6,d2 { restore d2 }
  379. movem.l (sp)+,d3/a2/a3
  380. move.l d0,t
  381. end;
  382. do_seekend:=t;
  383. end;
  384. function do_filesize(handle : longint) : longint;
  385. var
  386. aktfilepos : longint;
  387. begin
  388. aktfilepos:=do_filepos(handle);
  389. do_filesize:=do_seekend(handle);
  390. do_seek(handle,aktfilepos);
  391. end;
  392. procedure do_truncate (handle,pos:longint);
  393. begin
  394. do_seek(handle,pos);
  395. {!!!!!!!!!!!!}
  396. end;
  397. procedure do_open(var f;p:pchar;flags:longint);
  398. {
  399. filerec and textrec have both handle and mode as the first items so
  400. they could use the same routine for opening/creating.
  401. when (flags and $100) the file will be append
  402. when (flags and $1000) the file will be truncate/rewritten
  403. when (flags and $10000) there is no check for close (needed for textfiles)
  404. }
  405. var
  406. i : word;
  407. oflags: longint;
  408. begin
  409. AllowSlash(p);
  410. { close first if opened }
  411. if ((flags and $10000)=0) then
  412. begin
  413. case filerec(f).mode of
  414. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  415. fmclosed : ;
  416. else
  417. begin
  418. inoutres:=102; {not assigned}
  419. exit;
  420. end;
  421. end;
  422. end;
  423. { reset file handle }
  424. filerec(f).handle:=UnusedHandle;
  425. oflags:=$02; { read/write mode }
  426. { convert filemode to filerec modes }
  427. case (flags and 3) of
  428. 0 : begin
  429. filerec(f).mode:=fminput;
  430. oflags:=$00; { read mode only }
  431. end;
  432. 1 : filerec(f).mode:=fmoutput;
  433. 2 : filerec(f).mode:=fminout;
  434. end;
  435. if (flags and $1000)<>0 then
  436. begin
  437. filerec(f).mode:=fmoutput;
  438. oflags:=$04; { read/write with create }
  439. end
  440. else
  441. if (flags and $100)<>0 then
  442. begin
  443. filerec(f).mode:=fmoutput;
  444. oflags:=$02; { read/write }
  445. end;
  446. { empty name is special }
  447. if p[0]=#0 then
  448. begin
  449. case filerec(f).mode of
  450. fminput : filerec(f).handle:=StdInputHandle;
  451. fmappend,
  452. fmoutput : begin
  453. filerec(f).handle:=StdOutputHandle;
  454. filerec(f).mode:=fmoutput; {fool fmappend}
  455. end;
  456. end;
  457. exit;
  458. end;
  459. asm
  460. movem.l d2/d3/a2/a3,-(sp) { save used registers }
  461. cmp.l #4,oflags { check if rewrite mode ... }
  462. bne @opencont2
  463. { rewrite mode - create new file }
  464. move.w #0,-(sp)
  465. move.l p,-(sp)
  466. move.w #$3c,-(sp)
  467. trap #1
  468. add.l #8,sp { restore stack of os call }
  469. bra @end
  470. { reset - open existing files }
  471. @opencont2:
  472. move.l oflags,d0 { use flag as source ... }
  473. @opencont1:
  474. move.w d0,-(sp)
  475. move.l p,-(sp)
  476. move.w #$3d,-(sp)
  477. trap #1
  478. add.l #8,sp { restore stack of os call }
  479. @end:
  480. movem.l (sp)+,d2/d3/a2/a3
  481. tst.w d0
  482. bpl @opennoerr { if positive return values then ok }
  483. cmp.w #-1,d0 { if handle is -1 CON: }
  484. beq @opennoerr
  485. cmp.w #-2,d0 { if handle is -2 AUX: }
  486. beq @opennoerr
  487. cmp.w #-3,d0 { if handle is -3 PRN: }
  488. beq @opennoerr
  489. move.w d0,errno { otherwise normal error }
  490. @opennoerr:
  491. move.w d0,i { get handle as SIGNED VALUE... }
  492. end;
  493. if errno <> 0 then
  494. Error2InOut;
  495. filerec(f).handle:=i;
  496. if (flags and $100)<>0 then
  497. do_seekend(filerec(f).handle);
  498. end;
  499. {*****************************************************************************
  500. UnTyped File Handling
  501. *****************************************************************************}
  502. {$i file.inc}
  503. {*****************************************************************************
  504. Typed File Handling
  505. *****************************************************************************}
  506. {$i typefile.inc}
  507. {*****************************************************************************
  508. Text File Handling
  509. *****************************************************************************}
  510. {$i text.inc}
  511. {*****************************************************************************
  512. Directory Handling
  513. *****************************************************************************}
  514. procedure DosDir(func:byte;const s:string);
  515. var
  516. buffer : array[0..255] of char;
  517. c : word;
  518. begin
  519. move(s[1],buffer,length(s));
  520. buffer[length(s)]:=#0;
  521. AllowSlash(pchar(@buffer));
  522. c:=word(func);
  523. asm
  524. move.l d2,d6 { save d2 }
  525. movem.l d3/a2/a3,-(sp)
  526. pea buffer
  527. move.w c,-(sp)
  528. trap #1
  529. add.l #6,sp
  530. move.l d6,d2 { restore d2 }
  531. movem.l (sp)+,d3/a2/a3
  532. tst.w d0
  533. beq @dosdirend
  534. move.w d0,errno
  535. @dosdirend:
  536. end;
  537. if errno <> 0 then
  538. Error2InOut;
  539. end;
  540. procedure mkdir(const s : string);[IOCheck];
  541. begin
  542. If InOutRes <> 0 then exit;
  543. DosDir($39,s);
  544. end;
  545. procedure rmdir(const s : string);[IOCheck];
  546. begin
  547. If InOutRes <> 0 then exit;
  548. DosDir($3a,s);
  549. end;
  550. procedure chdir(const s : string);[IOCheck];
  551. begin
  552. If InOutRes <> 0 then exit;
  553. DosDir($3b,s);
  554. end;
  555. procedure getdir(drivenr : byte;var dir : string);
  556. var
  557. temp : array[0..255] of char;
  558. i : longint;
  559. j: byte;
  560. drv: word;
  561. begin
  562. drv:=word(drivenr);
  563. asm
  564. move.l d2,d6 { save d2 }
  565. movem.l d3/a2/a3,-(sp)
  566. { Get dir from drivenr : 0=default, 1=A etc... }
  567. move.w drv,-(sp)
  568. { put (previously saved) offset in si }
  569. { move.l temp,-(sp)}
  570. pea temp
  571. { call attos function 47H : Get dir }
  572. move.w #$47,-(sp)
  573. { make the call }
  574. trap #1
  575. add.l #8,sp
  576. move.l d6,d2 { restore d2 }
  577. movem.l (sp)+,d3/a2/a3
  578. end;
  579. { conversion to pascal string }
  580. i:=0;
  581. while (temp[i]<>#0) do
  582. begin
  583. if temp[i]='/' then
  584. temp[i]:='\';
  585. dir[i+3]:=temp[i];
  586. inc(i);
  587. end;
  588. dir[2]:=':';
  589. dir[3]:='\';
  590. dir[0]:=char(i+2);
  591. { upcase the string (FPC Pascal function) }
  592. dir:=upcase(dir);
  593. if drivenr<>0 then { Drive was supplied. We know it }
  594. dir[1]:=chr(65+drivenr-1)
  595. else
  596. begin
  597. asm
  598. move.l d2,d6 { save d2 }
  599. movem.l d3/a2/a3,-(sp)
  600. move.w #$19,-(sp)
  601. trap #1
  602. add.l #2,sp
  603. move.w d0,drv
  604. move.l d6,d2 { restore d2 }
  605. movem.l (sp)+,d3/a2/a3
  606. end;
  607. dir[1]:=chr(byte(drv)+ord('A'));
  608. end;
  609. end;
  610. {*****************************************************************************
  611. System Dependent Exit code
  612. *****************************************************************************}
  613. Procedure system_exit;
  614. begin
  615. end;
  616. {*****************************************************************************
  617. SystemUnit Initialization
  618. *****************************************************************************}
  619. begin
  620. { Initialize ExitProc }
  621. ExitProc:=Nil;
  622. { to test stack depth }
  623. loweststack:=maxlongint;
  624. { Setup heap }
  625. InitHeap;
  626. { Setup stdin, stdout and stderr }
  627. OpenStdIO(Input,fmInput,StdInputHandle);
  628. OpenStdIO(Output,fmOutput,StdOutputHandle);
  629. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  630. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  631. { Reset IO Error }
  632. InOutRes:=0;
  633. errno := 0;
  634. { Setup command line arguments }
  635. argc:=GetParamCount(args);
  636. end.
  637. {
  638. $Log$
  639. Revision 1.2 2000-07-14 10:30:58 michael
  640. +
  641. Revision 1.1 2000/07/13 06:30:30 michael
  642. + Initial import
  643. Revision 1.14 2000/01/07 16:41:29 daniel
  644. * copyright 2000
  645. Revision 1.13 2000/01/07 16:32:23 daniel
  646. * copyright 2000 added
  647. Revision 1.12 1999/09/10 15:40:33 peter
  648. * fixed do_open flags to be > $100, becuase filemode can be upto 255
  649. Revision 1.11 1999/01/18 10:05:48 pierre
  650. + system_exit procedure added
  651. Revision 1.10 1998/12/28 15:50:43 peter
  652. + stdout, which is needed when you write something in the system unit
  653. to the screen. Like the runtime error
  654. Revision 1.9 1998/09/14 10:48:02 peter
  655. * FPC_ names
  656. * Heap manager is now system independent
  657. Revision 1.8 1998/07/15 12:11:59 carl
  658. * hmmm... can't remember! :(...
  659. Revision 1.5 1998/07/13 12:34:13 carl
  660. + Error2InoutRes implemented
  661. * do_read was doing a wrong os call!
  662. * do_open was not pushing the right values
  663. * DosDir was pushing the wrong params on the stack
  664. * do_close would never works, was pushing a longint instead of word
  665. Revision 1.4 1998/07/02 12:39:27 carl
  666. * IOCheck for mkdir,chdir and rmdir, just like in TP
  667. Revision 1.3 1998/07/01 14:40:20 carl
  668. + new stack checking implemented
  669. + IOCheck for chdir , getdir , mkdir and rmdir
  670. Revision 1.1.1.1 1998/03/25 11:18:47 root
  671. * Restored version
  672. Revision 1.8 1998/02/23 02:27:39 carl
  673. * make it link correctly
  674. Revision 1.7 1998/02/06 16:33:02 carl
  675. * oops... commited wrong file
  676. + do_open is now standard with other platforms
  677. Revision 1.5 1998/01/31 19:32:51 carl
  678. - removed incorrect $define
  679. Revision 1.4 1998/01/27 10:55:45 peter
  680. * Word Handles from -1 -> $ffff
  681. Revision 1.3 1998/01/25 22:44:14 peter
  682. * Using uniform layout
  683. }