windows build fixes and some more work on symtab serialization
[dyninst.git] / symtabAPI / src / LineInformation.C
1 /*
2  * Copyright (c) 1996-2004 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #include "symtabAPI/h/LineInformation.h"
43 #include <assert.h>
44 #include <list>
45 #include <cstring>
46 #include "boost/functional/hash.hpp"
47 #include "common/h/headers.h"
48
49 using namespace Dyninst;
50 using namespace Dyninst::SymtabAPI;
51 using namespace std;
52
53 #include "RangeLookup.t"
54
55 #if ! defined(os_windows)      
56 struct SourceLineCompare 
57 {
58    bool operator () ( const char * lhs, const char * rhs ) const;
59 };
60
61 typedef dyn_hash_set< const char *, boost::hash< const char * >, SourceLineCompare > SourceLineInternTable;
62
63 #else
64
65 struct SourceLineLess 
66 {
67    bool operator () ( const char * lhs, const char * rhs ) const;
68 };
69
70 typedef std::set< const char *, SourceLineLess > SourceLineInternTable;
71
72 #endif 
73
74 namespace Dyninst {
75 namespace SymtabAPI {
76 class SourceLineInternalTableWrapper {
77    public:
78       SourceLineInternTable source_line_names;
79       SourceLineInternalTableWrapper() {}
80       ~SourceLineInternalTableWrapper(){}
81       SourceLineInternTable &getTable() {return source_line_names;}
82 };
83 }}
84
85 SourceLineInternalTableWrapper *LineInformation::getSourceLineNamesW()
86 {
87    if (sourceLineNamesPtr)
88       return sourceLineNamesPtr;
89
90    sourceLineNamesPtr = new SourceLineInternalTableWrapper();
91
92    if (!sourceLineNamesPtr) 
93       fprintf(stderr, "%s[%d]:  alloc failure here\n", FILE__, __LINE__);
94
95    return sourceLineNamesPtr;
96 }
97
98 SourceLineInternTable &getSourceLineNames(LineInformation *li)
99 {
100    if (!li->sourceLineNamesPtr)
101       li->sourceLineNamesPtr = new SourceLineInternalTableWrapper();
102
103    if (!li->sourceLineNamesPtr)
104    {
105       fprintf(stderr, "%s[%d]:  alloc prob\n", FILE__, __LINE__);
106       abort();
107    }
108
109    return li->sourceLineNamesPtr->getTable();
110 }
111
112 LineInformation::LineInformation() : 
113    Dyninst::SymtabAPI::RangeLookup< LineNoTuple, LineNoTuple::LineNoTupleLess >(),
114    sourceLineNamesPtr(NULL) 
115 {
116    size_ = 0;
117 } /* end LineInformation constructor */
118
119 bool LineInformation::addLine( const char * lineSource, 
120       unsigned int lineNo, 
121       unsigned int lineOffset, 
122       Offset lowInclusiveAddr, 
123       Offset highExclusiveAddr ) 
124 {
125
126    /* If we haven't already, intern the lineSource. */
127    if ( lineSource == NULL ) 
128    { 
129       return false; 
130    }
131
132    const char * lineSourceInternal = NULL;
133    typedef SourceLineInternTable::const_iterator IteratorType;
134    SourceLineInternTable &sourceLineNames = getSourceLineNames(this);
135    IteratorType found = sourceLineNames.find( lineSource );
136
137    if ( found == sourceLineNames.end() ) 
138    {
139       lineSourceInternal = P_strdup( lineSource );
140       assert( lineSourceInternal != NULL );
141       sourceLineNames.insert( lineSourceInternal );
142    }
143    else 
144    {
145       lineSourceInternal = * found;
146    }
147
148    assert( lineSourceInternal != NULL );
149    size_++;
150
151    bool ret = addValue( LineNoTuple(lineSourceInternal, lineNo, lineOffset), 
152          lowInclusiveAddr, highExclusiveAddr );
153
154    return ret;
155 } /* end setLineToAddressRangeMapping() */
156
157 void LineInformation::addLineInfo(LineInformation *lineInfo)
158 {
159    const_iterator iter = lineInfo->begin();
160
161    for (; iter != lineInfo->end(); iter++)
162    {
163       addLine(iter->second.first, iter->second.second, iter->second.column, 
164             iter->first.first, iter->first.second);
165    }
166 }
167
168 bool LineInformation::addAddressRange( Offset lowInclusiveAddr, 
169       Offset highExclusiveAddr, 
170       const char * lineSource, 
171       unsigned int lineNo, 
172       unsigned int lineOffset ) 
173 {
174    return addLine( lineSource, lineNo, lineOffset, lowInclusiveAddr, highExclusiveAddr );
175 } /* end setAddressRangeToLineMapping() */
176
177 bool LineInformation::getSourceLines( Offset addressInRange, 
178       vector< LineNoTuple > & lines ) 
179 {
180    return getValues( addressInRange, lines );
181 } /* end getLinesFromAddress() */
182
183 bool LineInformation::getAddressRanges( const char * lineSource, 
184       unsigned int lineNo, vector< AddressRange > & ranges ) 
185 {
186    bool ret = Dyninst::SymtabAPI::RangeLookup< LineNoTuple, LineNoTuple::LineNoTupleLess >::getAddressRanges( LineNoTuple( lineSource, lineNo ), ranges );
187
188    return ret;
189 } /* end getAddressRangesFromLine() */
190
191 LineInformation::const_iterator LineInformation::begin() const 
192 {
193    return Dyninst::SymtabAPI::RangeLookup< LineNoTuple, LineNoTuple::LineNoTupleLess >::begin();
194 } /* end begin() */
195
196 LineInformation::const_iterator LineInformation::end() const 
197 {
198    return Dyninst::SymtabAPI::RangeLookup< LineNoTuple, LineNoTuple::LineNoTupleLess >::end();
199 } /* end begin() */
200
201 unsigned LineInformation::getSize() const
202 {
203    return size_;
204 }
205
206 bool LineNoTuple::LineNoTupleLess::operator () ( LineNoTuple lhs, LineNoTuple rhs ) const 
207 {
208    //  dont bother with ordering by column information yet.
209
210    int strcmp_res = strcmp( lhs.first, rhs.first);
211
212    if (strcmp_res < 0 ) 
213       return true; 
214
215    if ( strcmp_res == 0 ) 
216    {
217       if ( lhs.second < rhs.second )  
218          return true; 
219    }
220
221    return false; 
222 } /* end LineNoTupleLess() */
223
224 #if ! defined( os_windows )
225 bool SourceLineCompare::operator () ( const char * lhs, const char * rhs ) const 
226 {
227    return strcmp( lhs, rhs ) == 0;
228 } /* end SourceLineCompare() */
229 #else
230 bool SourceLineLess::operator () ( const char * lhs, const char * rhs ) const 
231 {
232    return strcmp( lhs, rhs ) < 0;
233 } /* end SourceLineLess() */
234 #endif
235
236 /* We free the strings we allocated, and let the compiler clean up everything else:
237
238    Section 10.4.6 [Stroustroup's C++]: "When a class object containing class
239    objects is destroyed, the body of that object's own destructor is executed first,
240    and then the members' destructors are executed in the reverse order of declaration." */
241
242 LineInformation::~LineInformation() 
243 {
244    /* Apparently, the iterator depends on the hash of its current key
245       to continue.  This should probably be cached, to allow me to free
246       the current key if it's a pointer (and the hash over the pointed-to
247       data), but I guess it's not strictly a bug. */
248
249    const char * internedString = NULL;
250    typedef SourceLineInternTable::const_iterator IteratorType;
251    SourceLineInternTable &sourceLineNames = getSourceLineNames(this);
252    SourceLineInternTable::iterator iterator = sourceLineNames.begin();
253
254    while ( iterator != sourceLineNames.end() ) 
255    {
256       internedString = * iterator;
257       ++iterator;
258       free( const_cast< char * >( internedString ) );
259    }    
260
261 } /* end LineInformation destructor */
262
263 LineNoTuple::LineNoTuple(const char *file_, unsigned int line_, unsigned int col_) :
264    first(file_),
265    second(line_),
266    column(col_) 
267 {
268 }
269
270 bool LineNoTuple::operator==(const LineNoTuple &cmp) const 
271 {
272    if (second != cmp.second) return false;
273    if (column != cmp.column) return false;
274
275    //  is compare-by-pointer OK here, or do we really have to really strcmp?
276    return (!strcmp(first,cmp.first)); 
277 }
278
279 void LineInformation::serialize(SerializerBase *sb, const char *) THROW_SPEC (SerializerError)
280 {
281    fprintf(stderr, "%s[%d]:  LineInformation::serialize -- IMPLEMENT ME sb = %p\n", 
282          FILE__, __LINE__, sb);
283 }