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