cfad47cfa3/tads3/vmsrcf.cpp

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#ifdef RCSID
2
static char RCSid[] =
3
"$Header$";
4
#endif
5
6
/* 
7
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
8
 *   
9
 *   Please see the accompanying license file, LICENSE.TXT, for information
10
 *   on using and copying this software.  
11
 */
12
/*
13
Name
14
  vmsrcf.cpp - T3 VM source file list
15
Function
16
  
17
Notes
18
  
19
Modified
20
  12/01/99 MJRoberts  - Creation
21
*/
22
23
#include "t3std.h"
24
#include "vmsrcf.h"
25
26
/* ------------------------------------------------------------------------ */
27
/*
28
 *   Source file table implementation 
29
 */
30
31
/*
32
 *   Initialize 
33
 */
34
CVmSrcfTable::CVmSrcfTable()
35
{
36
    /* no entries yet */
37
    list_ = 0;
38
    list_used_ = 0;
39
    list_alloc_ = 0;
40
}
41
42
/*
43
 *   Delete 
44
 */
45
CVmSrcfTable::~CVmSrcfTable()
46
{
47
    /* delete the list if we allocated one */
48
    if (list_ != 0)
49
    {
50
        /* clear the table */
51
        clear();
52
53
        /* delete the list */
54
        t3free(list_);
55
    }
56
}
57
58
/*
59
 *   Clear the table
60
 */
61
void CVmSrcfTable::clear()
62
{
63
    size_t i;
64
    
65
    /* delete each entry */
66
    for (i = 0 ; i < list_used_ ; ++i)
67
        delete(list_[i]);
68
69
    /* 
70
     *   we no longer have any entries, but leave the list allocated in
71
     *   case we add entries again 
72
     */
73
    list_used_ = 0;
74
}
75
76
/*
77
 *   Add a new entry to the table 
78
 */
79
CVmSrcfEntry *CVmSrcfTable::add_entry(int orig_index, size_t name_len)
80
{
81
    CVmSrcfEntry *entry;
82
    
83
    /* allocate the new entry */
84
    entry = new CVmSrcfEntry(orig_index, (uint)orig_index == list_used_,
85
                             name_len);
86
87
    /* 
88
     *   make sure we have room in our list for a new entry; if not,
89
     *   expand the list 
90
     */
91
    if (list_used_ >= list_alloc_)
92
    {
93
        size_t siz;
94
        
95
        /* calculate the expanded list size */
96
        list_alloc_ += 10;
97
        siz = list_alloc_ * sizeof(list_[0]);
98
99
        /* allocate or reallocate the list */
100
        if (list_ == 0)
101
            list_ = (CVmSrcfEntry **)t3malloc(siz);
102
        else
103
            list_ = (CVmSrcfEntry **)t3realloc(list_, siz);
104
    }
105
106
    /* add the new entry */
107
    list_[list_used_] = entry;
108
109
    /* count the new entry */
110
    ++list_used_;
111
112
    /* return the new entry */
113
    return entry;
114
}
115
116
/* ------------------------------------------------------------------------ */
117
/*
118
 *   Source file record implementation 
119
 */
120
121
/*
122
 *   Allocate or expand the line records array
123
 */
124
void CVmSrcfEntry::alloc_line_records(ulong cnt)
125
{
126
    ulong siz;
127
    
128
    /* 
129
     *   if the current array size is already big enough for the given
130
     *   count, there's nothing to do 
131
     */
132
    if (cnt <= lines_alo_)
133
        return;
134
135
    /* calculate the allocation size */
136
    siz = cnt * sizeof(lines_[0]);
137
138
    /* 
139
     *   if the new size exceeds the maximum local system's architectural
140
     *   limit for a single allocation, restrict the size to the maximum
141
     *   allocation 
142
     */
143
    if (siz > OSMALMAX)
144
    {
145
        /* recalculate the size for the maximum architectural allocation */
146
        cnt = OSMALMAX / sizeof(lines_[0]);
147
        siz = cnt * sizeof(lines_[0]);
148
149
        /* if we're already there, ignore the request */
150
        if (cnt <= lines_alo_)
151
            return;
152
    }
153
154
    /* allocate or reallocate the line record array */
155
    if (lines_ == 0)
156
        lines_ = (CVmSrcfLine *)t3malloc((size_t)siz);
157
    else
158
        lines_ = (CVmSrcfLine *)t3realloc(lines_, (size_t)siz);
159
160
    /* remember the new array size */
161
    lines_alo_ = cnt;
162
}
163
164
/*
165
 *   add a line record
166
 */
167
void CVmSrcfEntry::add_line_record(ulong linenum, ulong code_addr)
168
{
169
    /* make sure we have enough space */
170
    if (lines_cnt_ >= lines_alo_)
171
    {
172
        /* expand the line records array */
173
        alloc_line_records(lines_alo_ + 1024);
174
175
        /* if that didn't create enough space, ignore the new record */
176
        if (lines_cnt_ >= lines_alo_)
177
            return;
178
    }
179
180
    /* add the new record */
181
    lines_[lines_cnt_].linenum = linenum;
182
    lines_[lines_cnt_].code_addr = code_addr;
183
184
    /* count the new record */
185
    ++lines_cnt_;
186
}
187
188
/*
189
 *   Find a source line 
190
 */
191
ulong CVmSrcfEntry::find_src_addr(ulong *linenum, int exact)
192
{
193
    long hi, lo, cur;
194
195
    /* if there are no line records, return failure */
196
    if (lines_cnt_ == 0)
197
        return 0;
198
199
    /* perform a binary search of the line record array */
200
    lo = 0;
201
    hi =  (long)lines_cnt_ - 1;
202
    while (lo <= hi)
203
    {
204
        int match;
205
        
206
        /* split the difference */
207
        cur = lo + (hi - lo)/2;
208
209
        /* 
210
         *   Check for a match.  If they require an exact match, we must
211
         *   find the line number exactly.  Otherwise, check to see if
212
         *   this is the next executable line after the given line. 
213
         */
214
        if (exact)
215
        {
216
            /* exact match required */
217
            match = (lines_[cur].linenum == *linenum);
218
        }
219
        else
220
        {
221
            /* 
222
             *   exact match not required - match if this is the next
223
             *   executable line after the requested line, or this is the
224
             *   last executable line and the requested line is higher 
225
             */
226
            if (cur == 0)
227
            {
228
                /* 
229
                 *   this is the first executable line - if the requested
230
                 *   line is before this one, this is our match 
231
                 */
232
                match = (*linenum <= lines_[cur].linenum);
233
            }
234
            else if (cur == (long)lines_cnt_ - 1)
235
            {
236
                /* 
237
                 *   this is the last executable line - if the requested
238
                 *   line is after this one, this is our match 
239
                 */
240
                match = (*linenum >= lines_[cur].linenum);
241
            }
242
            else
243
            {
244
                /* 
245
                 *   we're somewhere in the middle of the file - if the
246
                 *   requested line is before this one, but after the
247
                 *   previous executable line, this is our match 
248
                 */
249
                match = (*linenum <= lines_[cur].linenum
250
                         && *linenum > lines_[cur - 1].linenum);
251
            }
252
        }
253
254
        /* if we have a match, return it; otherwise, keep searching */
255
        if (match)
256
        {
257
            /* 
258
             *   if this is a non-exact match, update the caller's line
259
             *   number with the actual line number we found 
260
             */
261
            *linenum = lines_[cur].linenum;
262
            
263
            /* return our code address */
264
            return lines_[cur].code_addr;
265
        }
266
        else if (*linenum > lines_[cur].linenum)
267
        {
268
            /* we need to go higher */
269
            lo = (cur == lo ? cur + 1 : cur);
270
        }
271
        else
272
        {
273
            /* we need to go lower */
274
            hi = (cur == hi ? hi - 1 : cur);
275
        }
276
    }
277
278
    /* failure */
279
    return 0;
280
}