1 /*@z47.c:Environment Table:EnvReadRetrieve()@*********************************/
2 /* */
3 /* THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.39) */
4 /* COPYRIGHT (C) 1991, 2008 Jeffrey H. Kingston */
5 /* */
6 /* Jeffrey H. Kingston (jeff@it.usyd.edu.au) */
7 /* School of Information Technologies */
8 /* The University of Sydney 2006 */
9 /* AUSTRALIA */
10 /* */
11 /* This program is free software; you can redistribute it and/or modify */
12 /* it under the terms of the GNU General Public License as published by */
13 /* the Free Software Foundation; either Version 3, or (at your option) */
14 /* any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA */
24 /* */
25 /* FILE: z47.c */
26 /* MODULE: Environment Table */
27 /* EXTERNS: EnvInit(), EnvWriteRetrieve(), EnvWriteInsert(), */
28 /* EnvReadRetrieve(), EnvReadInsert() */
29 /* */
30 /*****************************************************************************/
31 #include "externs.h"
32 #define TAB_SIZE 211
33 #define MAX_CACHE 180
34
35 #define env_offset(x) back(x, ROWM)
36 #define env_lnum(x) line_num(fpos(x))
37 #define env_fnum(x) file_num(fpos(x))
38 #define env_read(x) sized(x)
39
40 static OBJECT env_cache; /* cache of envts in use */
41 static int cache_count; /* current size of cache */
42 static int stat_writes; /* calls to WriteRetrieve */
43 static int stat_write_hits; /* hits in WriteRetrieve */
44 static int stat_reads; /* calls to ReadRetrieve */
45 static int stat_read_hits; /* hits in ReadRetrieve */
46
47 static OBJECT tab[TAB_SIZE];
48
49 #define hash1(pos, env, fnum) \
50 { \
51 pos = ( (unsigned long) env + fnum ) % TAB_SIZE; \
52 }
53
54 #define hash2(pos, fnum, offset) \
55 { \
56 pos = ( offset + fnum ) % TAB_SIZE; \
57 }
58
59
60 /*****************************************************************************/
61 /* */
62 /* void EnvInit(void) */
63 /* */
64 /* Initialize this module. */
65 /* */
66 /*****************************************************************************/
67
EnvInit(void)68 void EnvInit(void)
69 { int i;
70 debug0(DET, DD, "EnvInit()");
71 stat_reads = 0;
72 stat_read_hits = 0;
73 stat_writes = 0;
74 stat_write_hits = 0;
75 New(env_cache, ACAT);
76 cache_count = 0;
77 for( i = 0; i < TAB_SIZE; i++ )
78 { tab[i] = nilobj;
79 }
80 debug0(DET, DD, "EnvInit returning");
81 } /* end EnvInit */
82
83
84 /*****************************************************************************/
85 /* */
86 /* BOOLEAN EnvWriteRetrieve(OBJECT env, FILE_NUM fnum, int *offset, *lnum) */
87 /* */
88 /* Return the offset in file fnum where environment env has been written, */
89 /* or FALSE if env has not been written to this file. */
90 /* */
91 /*****************************************************************************/
92
EnvWriteRetrieve(OBJECT env,FILE_NUM fnum,int * offset,int * lnum)93 BOOLEAN EnvWriteRetrieve(OBJECT env, FILE_NUM fnum, int *offset, int *lnum)
94 { unsigned int pos; OBJECT link, y, z;
95 debug2(DET, DD, "EnvWriteRetrieve(env %d, %s)", (int) env, FileName(fnum));
96 debug1(DET, DDD, " %s", EchoObject(env));
97 stat_writes++;
98 hash1(pos, env, fnum);
99 if( tab[pos] != nilobj )
100 {
101 for( link = Down(tab[pos]); link != tab[pos]; link = NextDown(link) )
102 { Child(y, link);
103 Child(z, Down(y));
104 if( env_fnum(y) == fnum && z == env && !env_read(y) )
105 { MoveLink(LastUp(y), env_cache, PARENT);
106 *offset = env_offset(y);
107 *lnum = env_lnum(y);
108 stat_write_hits++;
109 debug2(DET, DD, "EnvWriteRetrieve returning TRUE (offset %d, lnum %d)",
110 *offset, *lnum);
111 return TRUE;
112 }
113 }
114 }
115 debug0(DET, DD, "EnvWriteRetrieve returning FALSE");
116 return FALSE;
117 } /* end EnvWriteRetrieve */
118
119
120 /*****************************************************************************/
121 /* */
122 /* void EnvWriteInsert(OBJECT env, FILE_NUM fnum, int offset, int lnum) */
123 /* */
124 /* Record the fact that environment env has been written to file fnum */
125 /* at the given offset. */
126 /* */
127 /*****************************************************************************/
128
EnvWriteInsert(OBJECT env,FILE_NUM fnum,int offset,int lnum)129 void EnvWriteInsert(OBJECT env, FILE_NUM fnum, int offset, int lnum)
130 { unsigned int pos; OBJECT loser, x;
131 debug3(DET, DD, "EnvWriteInsert(env %d, %s, %d)", (int) env,
132 FileName(fnum), offset);
133
134 /* to limit the cache size, remove least recently used entry if full */
135 if( cache_count >= MAX_CACHE )
136 {
137 Child(loser, Down(env_cache));
138 DeleteLink(Up(loser));
139 DisposeChild(Up(loser));
140 cache_count--;
141 }
142
143 /* insert the new entry */
144 hash1(pos, env, fnum);
145 if( tab[pos] == nilobj ) New(tab[pos], ACAT);
146 New(x, ACAT);
147 env_fnum(x) = fnum;
148 env_offset(x) = offset;
149 env_lnum(x) = lnum;
150 env_read(x) = FALSE;
151 Link(tab[pos], x);
152 Link(env_cache, x);
153 Link(x, env);
154 cache_count++;
155
156 debug1(DET, DD, "EnvWriteInsert returning (cache_count = %d)", cache_count);
157 } /* end EnvWriteInsert */
158
159
160 /*****************************************************************************/
161 /* */
162 /* BOOLEAN EnvReadRetrieve(FILE_NUM fnum, int offset, OBJECT *env) */
163 /* */
164 /* Return the environment that appears in file fnum at the given offset, */
165 /* or FALSE if this is not currently known. */
166 /* */
167 /*****************************************************************************/
168
EnvReadRetrieve(FILE_NUM fnum,int offset,OBJECT * env)169 BOOLEAN EnvReadRetrieve(FILE_NUM fnum, int offset, OBJECT *env)
170 { int pos; OBJECT link, y, z;
171 debug2(DET, DD, "EnvReadRetrieve(%s, %d)", FileName(fnum), offset);
172 stat_reads++;
173
174 hash2(pos, fnum, offset);
175 if( tab[pos] != nilobj )
176 {
177 for( link = Down(tab[pos]); link != tab[pos]; link = NextDown(link) )
178 { Child(y, link);
179 Child(z, Down(y));
180 if( env_fnum(y) == fnum && env_offset(y) == offset && env_read(y) )
181 { MoveLink(LastUp(y), env_cache, PARENT);
182 Child(*env, Down(y));
183 stat_read_hits++;
184 debug1(DET, DD, "EnvReadRetrieve returning env %d", (int) *env);
185 return TRUE;
186 }
187 }
188 }
189 debug0(DET, DD, "EnvReadRetrieve returning FALSE");
190 return FALSE;
191 } /* end EnvReadRetrieve */
192
193
194 /*****************************************************************************/
195 /* */
196 /* void EnvReadInsert(FILE_NUM fnum, int offset, OBJECT env) */
197 /* */
198 /* Record the fact that environment env has just been read from file fnum */
199 /* at position offset. */
200 /* */
201 /*****************************************************************************/
202
EnvReadInsert(FILE_NUM fnum,int offset,OBJECT env)203 void EnvReadInsert(FILE_NUM fnum, int offset, OBJECT env)
204 { int pos; OBJECT x, loser;
205 debug3(DET, DD, "EnvReadInsert(%s, %d, env %d)",
206 FileName(fnum), offset, (int) env);
207
208 /* to limit the cache size, remove least recently used entry if full */
209 if( cache_count >= MAX_CACHE )
210 {
211 Child(loser, Down(env_cache));
212 DeleteLink(Up(loser));
213 DisposeChild(Up(loser));
214 cache_count--;
215 }
216
217 /* insert the new entry */
218 hash2(pos, fnum, offset);
219 if( tab[pos] == nilobj ) New(tab[pos], ACAT);
220 New(x, ACAT);
221 env_fnum(x) = fnum;
222 env_offset(x) = offset;
223 env_read(x) = TRUE;
224 Link(tab[pos], x);
225 Link(env_cache, x);
226 Link(x, env);
227 cache_count++;
228
229 debug1(DET, DD, "EnvReadInsert returning (cache_count = %d)", cache_count);
230 } /* end EnvReadInsert */
231
232
233 #if DEBUG_ON
234 /*****************************************************************************/
235 /* */
236 /* void EnvDebug() */
237 /* */
238 /* Debug statistics of this module's performance. */
239 /* */
240 /*****************************************************************************/
241
EnvDebug(void)242 void EnvDebug(void)
243 {
244 debug3(DET, D, "Env Table %6s %6s %6s", "calls", "hits", "% hits");
245 debug3(DET, D, "reading %6d %6d %6.1f", stat_reads, stat_read_hits,
246 stat_reads == 0 ? (float) 0 : (float) 100 * stat_read_hits / stat_reads);
247 debug3(DET, D, "writing %6d %6d %6.1f", stat_writes, stat_write_hits,
248 stat_writes == 0 ? (float) 0 : (float) 100 * stat_write_hits / stat_writes);
249 } /* end EnvDebug */
250 #endif
251