| | 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 | } |