summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT')
-rw-r--r--v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT615
1 files changed, 615 insertions, 0 deletions
diff --git a/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT b/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT
new file mode 100644
index 0000000..b1cf286
--- /dev/null
+++ b/v4.0/src/CMD/FASTOPEN/FASTOPEN.TXT
@@ -0,0 +1,615 @@
1
2.*
3.pm 5
4:gdoc sec=''
5:frontm
6:titlep
7:title.FASTOPEN UTILITY HIGH LEVEL DESIGN
8:date.
9:author.J. K.
10:ETITLEP
11:toc
12:body
13.DH NUM
14.*.pa
15&SYSDATE.
16.*:H1.INTRODUCTION
17.*:H1.ARCHITECTURE OVERVIEW
18
19:H1.FASTOPEN DESIGN
20:H2.FASTOPEN UTILITY
21:H3.FASTOPEN Overview
22FASTOPEN is a utility that allows DOS to maintain the information about
23files that have been opened. The purpose is to reduce the number of times DOS
24has to look into the directory area of the disk for information on the file once
25the information is stored by FASTOPEN. In real life, many application
26programs, especially current database systems on the market, tend to open the
27same file repeatedly and every open operation needs an access to the disk if the
28information does not exist in the DOS buffer. The FASTOPEN utility will
29eliminate these disk accesses, and hence will increase the efficiency of DOS
30performance.
31
32
33:H3.FASTOPEN Operational Description
34Conceptually FASTOPEN itself is a database maintained by DOS. The data will
35be stored and maintained in the system RAM.
36
37FASTOPEN is a user-installable, stay resident utility loaded by entering a
38command
39.fo off
40 1). FASTOPEN D:{=L} ...
41
42where "..." means a possible repetition.
43
44 "D:" is a drive letter for a non_removable media.
45
46 "L" is the maxium number of files and subdirectories that can be
47 stored in the drive cache. The default value is 34, minimum
48 value, 10. The total number for all the drives is less
49 than 1000.
50
51.fo on
52
53:H4.Name Caching
54FASTOPEN will keep the history of the accessed subdirectory and file
55information in LRU fashion. The data are stored in a partial tree
56structure that represents all the recently accessed files and
57subdirectories of that drive. The number of entries entered by the
58user, or the default number of 34, represents the maximum number of
59nodes and leaves of the tree. As it suggests, the bigger the
60number is, the more the efficient it will be. Currently each additional
61increase of the entry will take 36 bytes, which is the fixed length of
62a node.
63
64The number entered by the user should be bigger than the deepest nesting
65of path entries in the drive.
66
67The operation on this name cache is similar to the operation on the
68physical drive.
69With the look up request, FASTOPEN will traverse the name cache tree from the
70root to the bottom to find the requested path, filename. If found, then the
71pointer to the file or subdirectory information packet will be returned, else FASTOPEN
72will return the string pointer that points up to the matching subdirectory name.
73In this case, if DOS wants to insert the rest of the subdirectory/file information
74an insert operation should be requested for every subdirectory/file. FASTOPEN
75will use the information from the previous Look_up operation for a sequence of Insert operations.
76
77At this moment, if there are any free entries left, then it will be used.
78Otherwise, FASTOPEN will delete the least recently used leaf. Any node cannot
79be deleted until the node becomes an empty leaf, i.e., without children.
80If a file or a directory has been removed, then DOS will update the name
81cache tree with the Delete request. The path, file will be looked up
82first, and if found, then the corresponding entries will be free to the
83free entry chain. If not found, then still it is O.K. since the matching file
84entries had been removed by the LRU scheme.
85
86
87:H3.Fastopen Interface
88When installed, by the nature of the functionality, FASTOPEN becomes
89a part of DOS and a private communication mechanism will be
90established.
91Inside DOS, vector pointers are established for FASTOPEN and will be
92initialized by the call "CALLinstall" macro by the FASTOPEN initialization.
93The structure of the FASTOPEN entry will look like;
94
95.fo off
96FASTOPEN_ENTRY struc
97FASTOPEN_ENTRY_SIZE dw 4 ;size of the following
98FASTOPEN_NAME_CACHING dd ?
99;FASTOPEN_FATCHAIN_CACHING dd ? ;not for DOS 3.3
100;NUMBER_OF_SFTS dw ? ;# of files - 3
101FASTOPEN_ENTRY ends
102.fo on
103
104The initial vector pointer for FASTOPEN_NAME_CACHING
105points to a dummy routine in DOS which simply set the carry flag and set AX to 0FFFFh.
106
107When FASTOPEN is installed, then this vectors table will be established to
108point to the matching procedures in FASTOPEN module.
109
110The register AL will contain subfunction value on entry to FASTOPEN.
111
112.fo off
113;FASTOPEN NAME CACHING Subfunctions
114fastopen_name_look_up equ 1
115fastopen_name_insert equ 2
116fastopen_name_delete equ 3
117;fastopen_name_purge equ 4 ;Not for DOS 3.3
118
119.fo off
1201. Name Caching
121
122 a. Look up
123 IN) DS:SI -> d:path
124 ES:DI -> DIR_INFO buffer in DOS to be filled by FASTOPEN
125 ES:CX -> Extended_Info buffer in DOS to be filled by FASTOPEN
126 OUT)
127 if found, DS:SI -> the last character of the path, i.e., 0.
128 ES:DI -> DIR INFO
129 ES:CX -> Extended INFO (explained in the data structure)
130 else if there exist the name cache for the drive, but could not
131 completely find the matching path,
132 DS:SI -> "\" following the directory that FASTOPEN can
133 find the match,
134 Will points to "\" after "d:" if no matching
135 root directory is found.
136 ES:DI -> Compct_Dir_Info of the subdirectory FASTOPEN
137 can find the match.
138 ES:CX -> the matching directory's Extended INFO
139 If cannot find the matching root directory entry, then
140 ES:DI, ES:CX are undetermined.
141 else carry flag set and AX = 0FFFFh.
142
143 b. Insert
144 IN) DS:DI -> DIR info
145 ES:BX -> Extended info
146
147 OUT)
148 If failed, then carry flag set and AX = 0FFFFh.
149 Insert operation handles only one file or subdirectory at a time.
150 So, usually insert operations are performed in a sequential manner.
151 A look up operation should be performed before any new sequential
152 insert operation.
153 FASTOPEN will keep the information of the pervious look up
154 operation in CURRENT_NODE. The CURRENT_NODE points to the matching
155 directory node of the previous Look up operation. The next insert
156 operation will use this CURRENT_NODE information to insert the
157 directory or file information. So, DOS will call only one Look_
158 up operation and possibly several Insert operation to insert the
159 path.
160
161 For example, suppose DOS wants to look up C:\DIR1\DIR2\FILE1 and
162 FASTOPEN only has the inforamtion up to C:DIR1. After the
163 look up operation, FASTOPEN will return with DS:SI points "\"
164 following C:\DIR1.
165 At this moment, if DOS decides to insert this information,then
166 it sets DS:DI to DIR_INFO, and ES:BX to EXTENDED_INFO of the
167 subdirectory DIR2, and will request an insert operation.
168 When control returned back to DOS, then it will set this time
169 DS:DI and ES:BX to those of FILE1, and will call an another
170 insert operation.
171 At the first insert operation, FASTOPEN automatically knows
172 that those informaton given by DOS belong to the child of
173 C:\DIR1, and will install it as a child. In the second operation,
174 again FASTOPEN knows that it is for the child of C:\DIR1\DIR2
175 and will accordingly install the information for FILE1.
176
177 c. Delete
178 IN) DS:SI -> d:path
179
180 OUT)
181 If failed, then carry flag set and AX = 0FFFFh.
182
183.fo on
184
185:H3.FASTOPEN Special Considerations
186FASTOPEN uses the following DOS function calls in its initialization
187rouitine. No DOS or BIOS function calls are allowed inside the
188main routine that is resident once installed.
189:ul
190:li.AH = 40h, Int 21h; Write to device for the messages,
191:li.AH = 31h, Int 21h; Terminate Process and Remain Resident,
192:li.AH = 48h, AH = 49h, AH = 4Ah, Int 21h; Allocate, free and
193modify memory block.
194:eul
195:p.
196
197To prevent the corruption of any DOS operation, once FASTOPEN is
198loaded it cannot be reloaded.
199
200
201:H4.FASTOPEN Top Level Design
202
203:H5.Data Structure
204
205The structures of the records in FASTOPEN are:
206
207.fo off
208NAME_record struc
209 LRU_pointer dw -1
210 Child_pointer dw -1
211 Sibling_pointer dw -1
212 MRU_pointer dw -1
213 Compct_Dir_info db 22 dup (?)
214 Extended_Info db 5 dup (?)
215NAME_record ends
216
217Extended_Info struc
218dirpos db 0
219dirsec dw 0
220clusnum dw 0
221Extended_Info ends
222
223Drive_cache_header struc
224LRU_ROOT dw 0 ;Start of LRU chain for this Name cache
225Child_ptr dw -1 ;points to the name cache
226Sibling_ptr dw -1 ;points to the next drive header
227MRU_ROOT dw 0 ;set to the end of LRU chain
228Drive_letter db 'C'
229Num_Entries dw 0
230Name_Cache_start dw 0 ;Start of name cache for this drive
231Drive_cache_header ends
232
233Cmpct_Dir_Info struc
234CD_File_name db 11 dup (0)
235CD_File_attr db ?
236CD_time dw ?
237CD_date dw ?
238CD_cluster dw ?
239CD_Filesize dd ?
240Cmpct_Dir_Info ends
241
242Dir_Info struc ;= full directory entry information.
243DI_head db 12 dup (?)
244DI_skip db 10 dup (0) ;reserved area. All the time 0.
245DI_tail db 10 dup (?)
246Dir_Info ends
247
248.fo
249
250
251:H5.FASTOPEN Hierarch
252:H6.FASTOPEN Components
253
254.fo off
255
256 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
257 ³ FASTOPEN ³
258 ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ
259 ³
260 ³
261 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
262 ³ ³
263 V V
264ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
265³ INIT ³ ³ MAIN ³
266ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ
267 ³
268 V
269 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
270 ³ ³
271 ³ LOOK_UP, INSERT, DELETE, INIT_TREE ³
272 ³ ³
273 ³ (SUPPORTING MODULES) ³
274 ³ ³
275 ³ GET_FREE_NODE, PRE_LRU_STACK, ³
276 ³ SET_LRU, MAKE_NAME_RECORD, ³
277 ³ UNFOLD_NAME_RECORD, PACK_DIR_NAME, ³
278 ³ REMOVEFROMLRUCHAIN ³
279 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
280
281.fo
282
283:H6.FASTOPEN Memory Structure
284
285.fo off
286 Lo_memory ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÄÂÄ
287 ³ LOOK_UP, ³ ³
288 ³ INSERT, ³ M
289 ³ DELETE, ³ A
290 ³ & Supporting Routines ³ I
291 ³ ³ N
292 ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ³
293 ³ INIT_TREE ³ ³
294 ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ ÄÅÄ
295 ³ DRIVE_CACHE_HEADER ³ I
296 ³ (After Init, this ³ N
297 ³ area will be used ³ I
298 ³ for name caches.) ³ T
299 ³ SHOW_ERR_MESSAGE ³ ³
300 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÄÁÄ
301
302 High_memory
303.fo
304
305.pa
306:H5.FASTOPEN Component Interfaces
307
308.fo off
309;*************************************************************************
310;
311;SUBROUTINE: INIT
312;
313;INPUT:
314;
315;OUTPUT:
316;
317;DESCRIPTION:
318;
319; 1:(Installation check)
320; { Get the entry pointer of FASTOPEN from DOS.
321; Check the signature ($FASTOPEN01$)
322; If already installed,
323; then Show 'FASTOPEN already installed'; Exit
324; }
325;
326; 2:(Parse the command line)
327; Input: User input
328;
329; Output: Total_Entry_Num.
330; Drive_Cache_Headers set.
331; End_Cache_Header.
332;
333; { For every drive entered
334; { Drive sanity check;
335; Get_Num;
336; if success and Total_Entry_Num < 1000, then
337; Set Drive_Cache_Header;
338; }
339; }
340;
341; 3:(Check the system memory) - Check if the system has enough
342; memory for the Name caches.
343; Name cache will start from the
344; End_Cache_Header.
345;
346; Input: Total_Entry_Num, End_Cache_Header, End_Init,
347; Output: End_Caches
348; {
349; Needed_space = size of (Name_Record) * Total_Entry_Num;
350; Needed_space = Needed_space - (End_Init - End_Cache_Header);
351; Free allocated memory from End_Init (AH = 4Ah);
352; Set memory block from End_Init to Needed_Space (AH = 48h);
353; if fail, Show 'Insufficient memory for FASTOPEN cache';
354; Set End_Caches;
355; }
356;
357; 4: jmp to INIT_TREE
358;
359;*************************************************************************
360
361
362.pa
363.fo off
364;*************************************************************************
365;
366;SUBROUTINE: INIT_TREE
367;
368;INPUT: Drive_cache_header, End_Caches
369;
370;OUTPUT:Name_cache entries installed for every drive requested.
371; LRU chain established for every drive.
372; FASTOPEN entry pointer set in DOS.
373; Terminate & stay resident. (Up to End_Caches)
374;
375;DESCRIPTION:
376;
377; 1:(Install_Name_Cache)
378; Input: Drive cache header, End_cache_header (= Name cache start)
379; Output:According to the information in the header,
380; the name cache entries will be established.
381; Also, LRU chain, MRU_pointer are established.
382;
383; { Buffer_start = End_cache_header;
384; For every drive header
385; { LRU_ROOT = Buffer_start;
386; For (i=1;i=Num_Entries;i++)
387; { MRU_pointer = Buffer_start;
388; Buffer_start= Buffer_start + size_of (Name_record);
389; if i = Num_Entries then LRU_pointer = -1
390; else LRU_pointer = Buffer_start;
391; }
392; }
393; }
394;
395; 2:(Set FASTOPEN entry pointer in DOS)
396; Use CALL INSTALL macro.
397;
398; 3: Terminate and stay resident up to Buffer_start;
399;
400;*************************************************************************
401
402
403.pa
404.fo off
405;*************************************************************************
406;
407;SUBROUTINE: MAIN
408;
409;INPUT: Called by DOS throught Look_up, Insert, Delete requests.
410;
411;OUTPUT:Request performed based on LRU scheme.
412; CX, DX, DS, ES, BP value saved. Other register are destroyed.
413;
414;DESCRIPTION:
415; Call Pack_Dir_Name ;get the drive letter in BL
416; Call Get_Drive_Cache_Header ;find the matching drive header
417; if not found, then AX = 0ffffh, Carry set
418; else if AL = Look_up then Call Look_up
419; else if AL = Insert then Call Insert
420; else if AL = Delete then Call Delete
421; else AX = 0ffffh, Carry set.
422;
423; MAJOR SUBROUTINES:
424; (Look_up) - Refer to Look_up subroutine.
425; (Delete) - Refer to Delete subroutine.
426; (Insert) - Refer to Insert subroutine.
427;
428; SUPPORTING SUBROUTINES:
429; 1:(Get_Free_Node) - Get the entry from the LRU_ROOT,
430; Set LRU_ROOT to the next entry of the
431; LRU chain
432; Input: none
433; Output:Entry address. LRU_ROOT updated to the next entry.
434;
435; 2:(Pre_LRU_Stack) - This is needed to implement LRU scheme in
436; a tree structure. Since the order of traversing a tree is
437; from the root to bottom and from left to right, the direct
438; implementation of LRU will result the parent the least mostly
439; used one instead of the child. This is exactly in the reverse
440; order to what had been expected. This procedure will
441; solve this problem without loss of any efficiency. In the
442; Look_up operation and found the match, the found entris will
443; be saved with each of its LRU, MRU pointer modified to reflect
444; the desired LRU order.
445; These created mini LRU chain will be attached to the
446; LRU chain again by SET_LRU. SET_LRU and PRE_LRU_STACK
447; should work in a synchronized fashion. SET_LRU routine
448; will be called in the beginning of every Look_up, Insert
449; operation. PRE_LRU_Stack will be called whenever a matching
450; entry is found in a Look_up operation, or whenever a new
451; entry is inserted by the Insert operation.
452; Input: Current_Drive,Target node.
453; Output:Depth, Top, Bottom set
454;
455; 3:(SET_LRU)
456; Input: Depth, Top, Bottom, Current_Drive
457; Output:Mini LRU chain created by Pre_LRU_Stack will be
458; placed at the end of LRU chain.
459;
460; 4:(MAKE_NAME_RECORD) - At Insert time, BOS will give
461; two types of information. DS:DI -> Dir_Info, ES:BX -> Extended_
462; Info. The Name_Record is composed of Cmpct_Dir_Info and
463; Extend_Info. MAKE_NAME_RECORD will simply make a Name_Record
464; from the informations from DOS.
465; Input: Dir_Info, Extended_Info
466; Output:Name_Record
467;
468; 5:(UNFOLD_NAME_RECORD) - Inverse function of above. When Look_up
469; operation finishes, then unfold the Name_Record of the current_
470; node for DOS. If the Current_Node is a drive_cache_header,
471; then will just return.
472; Input: CS:Current_Node, ES, DI, BX set for the buffer
473; Output:ES:DI->Dir_Info, ES:BX->Extended_Info buffer in DOS.
474;
475; 6:(PACK_DIR_NAME) - At Look_up or Delete operation, DS:SI points
476; to the requested full path, for ex., "C:\DIR1.EXT\DIR2\FILE.EXT",
477; 0. This routine is smart enough to recognize ":","\" and 0 as
478; a delimeter and will parse until the next delimeter and leave
479; SI to the next delimeter found. Also, if it is a drive name
480; it will set SI to the "\" after ":" for consistency and
481; it will set BL to the drive letter.
482; The main function of this routine is "pack" the given directory
483; name into 11 bytes format. PACKED_NAME will be filled with
484; the result. For example, when it is called the first time,
485; DL = "C" and SI will point to "\" before DIR1.EXT.
486; The second time, PACKED_NAME will be filled with
487; "DIR1 EXT" and SI will points to "\" before "DIR2".
488; Likewize, if this routine is called the fourth time,
489; FILE.EXT has been parsed and DS:SI will points to 0.
490; When this routine is called again, then it will return
491; with carry signaling that it has reached the end.
492; The user is required to call this routine consequtively
493; until it returns with carry.
494; Input:
495; Output:
496;
497;*************************************************************************
498
499
500.pa
501.fo off
502;*************************************************************************
503;
504;SUBROUTINE: LOOK_UP
505;
506;INPUT: DS:SI -> path
507; ES:DI -> DIR_INFO buffer in DOS to be filled by FASTOPEN
508; ES:CX -> Extended_Info buffer in DOS to be filled by FASTOPEN
509; CS:BP -> Matching Drive_cache_header
510;
511;OUTPUT:if found, DS:SI -> the last character of the path, i.e., 0.
512; ES:DI -> DIR_INFO
513; ES:CX -> Extended_INFO (explained in the data structure)
514; else if there exist the name cache for the drive, but could not
515; completely find the matching path,
516; DS:SI -> "\" following the directory that FASTOPEN can
517; find the match,
518; Will points to "\" after "d:" if no matching
519; root directory is found.
520; ES:DI -> Dir_Info of the subdirectory FASTOPEN
521; can find the match.
522; ES:CX -> the matching directory's Extended INFO
523; If cannot find the matching root directory entry, then
524; ES:DI, ES:BX are undetermined.
525; If the requested path is "D:\,0" then FASTOPEN will
526; return with carry flag set and, AX = 0ffffh.
527; else carry flag set and AX = 0FFFFh.
528;
529;GLOBAL VARIABLES:
530; CURRENT_NODE,
531; CURRENT_SIBLING,
532;
533;DESCRIPTION:
534; Save Dir_Info, Extended_Info buffer address in DOS.
535; Set ES to Name_Cache_Seg
536; SET_LRU;
537; 1:
538; Current_Node = BP
539; Current_Sibling = 0
540; PACK_DIR_NAME (from the path);
541; if CX = 0, then jmp to 3 /*Found*/;
542; Find_child (from the current_node);
543; if not found then jmp to 3
544; 2: Compare Packed_name with Child_pointer.CD_filename
545; if yes, then PRE_LRU_STACK; JMP to 1
546; else Find_Sibling;Current_sibling=Sibling_pointer
547; if found a sibling, then Current_Node = Current_Sibling
548; jmp to 2
549; else jmp to 3;
550; 3: UNFOLD_NAME_RECORD /*for the info packet to DOS */
551; Exit
552;
553;*************************************************************************
554
555
556.pa
557.fo off
558;*************************************************************************
559;
560;SUBROUTINE: INSERT
561;
562;INPUT: DS:DI -> DIR info
563; ES:BX -> Extended info
564;
565;OUTPUT:Automatic insertion based on CURRENT_NODE, CURRENT_SIBLING
566; If failed, then carry flag set and AX = 0FFFFh.
567; Insert operation handles only one file or subdirectory at a time.
568; So, usually insert operations are performed in a sequential manner.
569; A look up operation should be performed before any new sequential
570; insert operation.
571;
572;GLOBAL VARIABLES:
573; CURRENT_NODE,
574; CURRENT_SIBLING,
575;
576;DESCRIPTION:
577;
578; Make_Name_Record ;Make Name Record from the input
579; Get_Free_Node
580; Set_LRU ;(from TEMP_LRU_STACK)
581; if current_sibling <> 0 (or current_sibling=0FFh)
582; then Install as a sibling of Current_Node
583; else Install as a child under Current_Node;
584; Pre_LRU_stack ;(pre operation for LRU)
585; Exit
586;
587;*************************************************************************
588
589
590.pa
591.fo off
592;*************************************************************************
593;
594;SUBROUTINE: Delete
595;
596;INPUT: DS:SI -> d:path
597;
598;OUTPUT: If found, then remove the item from the Tree and from the
599; LRU chain. Move that slot to the Top of the LRU chain.
600;
601;GLOBAL VARIABLES:
602;
603;DESCRIPTION:
604; Look_Up
605; If ds:si -> 0, then Remove that entry from Tree, LRU chain,
606; Put that entry to the top of LRU chain
607; else AX = 0FFFFh, Carry set,
608; Exit
609;
610;*************************************************************************
611
612
613.fo
614:egdoc.
615