• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * \file       snapshot_parser.cpp
3  * \brief      OpenCSD : Snapshot Parser Library
4  *
5  * \copyright  Copyright (c) 2015, ARM Limited. All Rights Reserved.
6  */
7 
8 /*
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "snapshot_parser.h"
36 
37 #include <memory>
38 #include <algorithm>
39 #include <istream>
40 #include <iostream>
41 #include <string>
42 #include <utility>
43 using namespace std;
44 
45 #include "snapshot_parser_util.h"
46 #include "ini_section_names.h"
47 using namespace Util;
48 using namespace Parser;
49 
50 #include "opencsd.h"
51 
52 static ITraceErrorLog *s_pErrorLogger = 0;
53 static ocsd_hndl_err_log_t s_errlog_handle = 0;
54 static bool s_verbose_logging = true;
55 
56 /*************************************************************************
57  * Note, this file handles the parsring of the general (device specific)
58  * ini file and the (much smaller) device_list file
59  *************************************************************************/
60 
61 namespace ParserPrivate
62 {
63     //! Handle CRLF terminators and '#' and ';' comments
CleanLine(string & line)64     void CleanLine(string& line)
65     {
66         string::size_type endpos = line.find_first_of("\r;#");
67         if (endpos != string::npos)
68         {
69             line.erase(endpos);
70         }
71     }
72 
73     //! Split foo=bar into pair <foo, bar>
SplitKeyValue(const string & kv)74     pair<string, string> SplitKeyValue(const string& kv)
75     {
76         string::size_type eq(kv.find('='));
77         if (eq == string::npos)
78         {
79             throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Couldn't parse '" + kv + "' as key=value");
80         }
81         return make_pair(Trim(kv.substr(0, eq)), Trim(kv.substr(eq + 1)));
82     }
83 
84     //! Whether line is just tabs and spaces
IsEmpty(const string & line)85     bool IsEmpty(const string& line)
86     {
87         return TrimLeft(line) == "";
88     }
89 
90     /*! \brief Whether line is of form '[header]'
91      *  \param line the line
92      *  \param sectionName if function returns true, returns the text between the brackets
93      */
IsSectionHeader(const string & line,string & sectionName)94     bool IsSectionHeader(const string& line, string& sectionName)
95     {
96         string::size_type openBracket(line.find('['));
97         if (openBracket == string::npos)
98         {
99             return false;
100         }
101         string::size_type textStart(openBracket + 1);
102         string::size_type closeBracket(line.find(']', textStart));
103         if (closeBracket == string::npos)
104         {
105             return false;
106         }
107         sectionName.assign(Trim(line.substr(textStart, closeBracket - textStart)));
108         return true;
109     }
110 
111     template <class M, class K, class V>
AddUniqueKey(M & m,const K & key,const V & value,const std::string & keyStr)112     void AddUniqueKey(M& m, const K& key, const V& value, const std::string &keyStr )
113     {
114         if (!m.insert(make_pair(key, value)).second)
115         {
116             throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,  "Duplicate key: " + keyStr);
117         }
118     }
119 
PreventDupes(bool & store,const string & key,const string & section)120     void PreventDupes(bool& store, const string& key, const string& section)
121     {
122         if (store)
123         {
124             throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,
125                 "Duplicate " + key + " key found in "
126                 + section + " section");
127         }
128         store = true;
129     }
130 
131 
132     /*! \class Section
133      *  \brief Handle an ini file section begun with a section header ([header])
134      */
135     class Section
136     {
137     public:
~Section()138         virtual ~Section() {}
139 
140         //! Notify a key=value definition
141         virtual void Define(const string& k, const string& v) = 0;
142 
143         //! Notify end of section - we can't handle in dtor because misparses throw.
144         virtual void End() = 0;
145     };
146 
147     //! The initial state
148     class NullSection : public Section
149     {
150     public:
Define(const string & k,const string &)151         void Define(const string& k, const string&)
152         {
153             throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,  "Definition of '" + k + "' has no section header");
154         }
End()155         void End() {}
156     };
157 
158     //! Silently ignore sections that are undefined
159     class IgnoredSection : public Section
160     {
161     public:
Define(const string &,const string &)162         void Define(const string& , const string&)
163         {
164         }
End()165         void End() {}
166     };
167 
168     //! Handle a [global] section.
169     class GlobalSection : public Section
170     {
171     public:
GlobalSection(Parsed & result)172         GlobalSection(Parsed& result) : m_result(result), m_got_core()
173         {
174             if (m_result.foundGlobal)
175             {
176                 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,  string("Only one ") + GlobalSectionName + " section allowed");
177             }
178             m_result.foundGlobal = true;
179         }
180 
Define(const string & k,const string & v)181         void Define(const string& k, const string& v)
182         {
183             if (k == CoreKey)
184             {
185                 PreventDupes(m_got_core, CoreKey, GlobalSectionName);
186                 m_result.core.assign(v);
187             }
188             else
189             {
190                 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Unknown global option '" + k + '\'');
191             }
192         }
193 
End()194         void End() {}
195 
196     private:
197         Parsed&     m_result;
198         bool        m_got_core;
199     };
200 
201     //! Handle a [dump] section
202     class DumpSection : public Section
203     {
204     public:
DumpSection(Parsed & result)205         DumpSection(Parsed& result)
206           : m_result(result),
207             m_got_file(), m_got_address(), m_got_length(), m_got_offset(), m_got_space(),
208             m_address(), m_length(), m_offset(), m_file(), m_space()
209         {}
210 
Define(const string & k,const string & v)211         void Define(const string& k, const string& v)
212         {
213             if (k == DumpAddressKey)
214             {
215                 PreventDupes(m_got_address, DumpAddressKey, DumpFileSectionPrefix);
216                 m_address = DecodeUnsigned<uint64_t>(v);
217             }
218             else if (k == DumpLengthKey)
219             {
220                 PreventDupes(m_got_length, DumpLengthKey, DumpFileSectionPrefix);
221                 m_length = DecodeUnsigned<size_t>(v);
222             }
223             else if (k == DumpOffsetKey)
224             {
225                 PreventDupes(m_got_offset, DumpOffsetKey, DumpFileSectionPrefix);
226                 m_offset = DecodeUnsigned<size_t>(v);
227             }
228             else if (k == DumpFileKey)
229             {
230                 PreventDupes(m_got_file, DumpFileKey, DumpFileSectionPrefix);
231                 m_file = Trim(v, "\"'"); // strip quotes
232             }
233             else if (k == DumpSpaceKey)
234             {
235                 PreventDupes(m_got_space, DumpSpaceKey, DumpFileSectionPrefix);
236                 m_space = Trim(v, "\"'"); // strip quotes
237             }
238             else
239             {
240                 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,  "Unknown dump section key '" + k + '\'');
241             }
242         }
243 
End()244         void End()
245         {
246             if (!m_got_address)
247             {
248                 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,  "Dump section is missing mandatory address definition");
249             }
250             if (!m_got_file)
251             {
252                 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Dump section is missing mandatory file definition");
253             }
254 
255             struct DumpDef add = { m_address, m_file, m_length, m_offset, m_space};
256             m_result.dumpDefs.push_back(add);
257         }
258 
259     private:
260         Parsed&     m_result;
261         bool        m_got_file;
262         bool        m_got_address;
263         bool        m_got_length;
264         bool        m_got_offset;
265         bool        m_got_space;
266         uint64_t      m_address;
267         size_t      m_length;
268         size_t      m_offset;
269         string      m_file;
270         string      m_space;
271     };
272 
273     //! Handle an [extendregs] section.
274     class ExtendRegsSection : public Section
275     {
276     public:
ExtendRegsSection(Parsed & result)277         ExtendRegsSection(Parsed& result) : m_result(result)
278         {}
279 
Define(const string & k,const string & v)280         void Define(const string& k, const string& v)
281         {
282             AddUniqueKey(m_result.extendRegDefs, DecodeUnsigned<uint32_t>(k), DecodeUnsigned<uint32_t>(v),k);
283         }
284 
End()285         void End() {}
286 
287     private:
288         Parsed&     m_result;
289     };
290 
291     // Handle a [regs] section
292     class SymbolicRegsSection : public Section
293     {
294     public:
SymbolicRegsSection(Parsed & result)295         SymbolicRegsSection(Parsed& result) : m_result(result)
296         {}
297 
Define(const string & k,const string & v)298         void Define(const string& k, const string& v)
299         {
300             const string value = Trim(v, "\"'"); // strip quotes
301             AddUniqueKey(m_result.regDefs, k, value,k);
302         }
303 
End()304         void End() {}
305 
306     private:
307         Parsed&     m_result;
308     };
309 
310     // Handle a [device] section
311     class DeviceSection : public Section
312     {
313     public:
DeviceSection(Parsed & result)314         DeviceSection(Parsed& result) : m_result(result), gotName(false),  gotClass(false), gotType(false)
315         {}
316 
Define(const string & k,const string & v)317         void Define(const string& k, const string& v)
318         {
319             if (k == DeviceNameKey)
320             {
321                 PreventDupes(gotName, k, DeviceSectionName);
322                 m_result.deviceName = v;
323             }
324             else if(k == DeviceClassKey)
325             {
326                 PreventDupes(gotClass, k, DeviceSectionName);
327                 m_result.deviceClass = v;
328             }
329             else if(k == DeviceTypeKey)
330             {
331                 PreventDupes(gotType, k, DeviceSectionName);
332                 m_result.deviceTypeName = v;
333             }
334         }
335 
End()336         void End() {}
337 
338     private:
339         Parsed&     m_result;
340         bool        gotName;
341         bool        gotClass;
342         bool        gotType;
343     };
344 
345     //! Instantiate the appropriate handler for the section name
NewSection(const string & sectionName,Parsed & result)346     auto_ptr<Section> NewSection( const string& sectionName, Parsed& result)
347     {
348         LogInfoStr( "Start of " + sectionName + " section\n");
349 
350         if (sectionName == GlobalSectionName)
351         {
352             return auto_ptr<Section>(new GlobalSection(result));
353         }
354         if (sectionName.substr(0,DumpFileSectionLen) == DumpFileSectionPrefix)
355         {
356             return auto_ptr<Section>(new DumpSection(result));
357         }
358         else if (sectionName == ExtendedRegsSectionName)
359         {
360             return auto_ptr<Section>(new ExtendRegsSection(result));
361         }
362         else if (sectionName == SymbolicRegsSectionName)
363         {
364             return auto_ptr<Section>(new SymbolicRegsSection(result));
365         }
366         else if (sectionName == DeviceSectionName)
367         {
368             return auto_ptr<Section>(new DeviceSection(result));
369         }
370         else
371         {
372             LogInfoStr("Unknown section ignored: " + sectionName + "\n");
373             return auto_ptr<Section>(new IgnoredSection);
374         }
375     }
376 
377     /***** Device List file parsing *********************/
378     //! Handle a [device_list] section.
379     class DeviceListSection : public Section
380     {
381     public:
DeviceListSection(ParsedDevices & result)382         DeviceListSection(ParsedDevices& result) : m_result(result), nextId(1)
383         {}
384 
Define(const string &,const string & v)385         void Define(const string& , const string& v)
386         {
387             // throw away supplied key - DTSL wants them monotonically increasing from 1
388             std::ostringstream id;
389             id << nextId++;
390             m_result.deviceList[id.str()] = v;
391         }
392 
End()393         void End() {}
394 
395     private:
396         ParsedDevices&   m_result;
397         uint32_t           nextId;
398     };
399 
400     //! Instantiate the appropriate handler for the section name
NewDeviceList(const string & sectionName,ParsedDevices & result)401     auto_ptr<Section> NewDeviceList(const string& sectionName, ParsedDevices& result)
402     {
403         LogInfoStr("Start of " + sectionName + " section\n");
404 
405         if (sectionName == DeviceListSectionName)
406         {
407             return auto_ptr<Section>(new DeviceListSection(result));
408         }
409         else
410         {
411             // ignore unexpected sections, there may be others like [trace]
412             // which RDDI doesn't care about
413             return auto_ptr<Section>(new NullSection);
414         }
415     }
416 
417     // Handle a [snapshot] section
418     class SnapshotSection : public Section
419     {
420     public:
SnapshotSection(SnapshotInfo & result)421         SnapshotSection(SnapshotInfo& result) : m_result(result), m_gotDescription(false), m_gotVersion(false)
422         {}
423 
Define(const string & k,const string & v)424         void Define(const string& k, const string& v)
425         {
426             if (k == VersionKey)
427             {
428                 PreventDupes(m_gotVersion, k, SnapshotSectionName);
429                 m_result.version = v;
430                 // the only valid contents of this are 1.0, as this is the version that introduced the "snapshot" section
431                 if (v != "1.0" && v != "1")
432                     throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,  "Illegal snapshot file version: " + v);
433             }
434             else if (k == DescriptionKey)
435             {
436                 PreventDupes(m_gotDescription, k, SnapshotSectionName);
437                 m_result.description = v;
438             }
439         }
getSnapshotInfo()440         SnapshotInfo getSnapshotInfo() { return m_result; }
End()441         void End() {}
442 
443     private:
444         SnapshotInfo &m_result;
445         bool        m_gotDescription;
446         bool        m_gotVersion;
447 
448     };
449 
450     //! Instantiate the appropriate handler for the section name
NewSnapshotInfo(const string & sectionName,ParsedDevices & result)451     auto_ptr<Section> NewSnapshotInfo(const string& sectionName, ParsedDevices& result)
452     {
453         LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n");
454 
455         if (sectionName == SnapshotSectionName)
456         {
457             return auto_ptr<Section>(new SnapshotSection(result.snapshotInfo));
458         }
459         else
460         {
461             // ignore unexpected sections, there may be others like [trace]
462             // which RDDI doesn't care about
463             return auto_ptr<Section>(new NullSection);
464         }
465     };
466 
467     class TraceSection : public Section
468     {
469     public:
TraceSection(ParsedDevices & result)470         TraceSection(ParsedDevices& result) : m_result(result), gotName(false)
471         {}
472 
Define(const string & k,const string & v)473         void Define(const string& k, const string& v)
474         {
475             if (k == MetadataKey)
476             {
477                 PreventDupes(gotName, k, TraceSectionName);
478                 m_result.traceMetaDataName = v;
479             }
480         }
481 
End()482         void End() {}
483 
484     private:
485         ParsedDevices&     m_result;
486         bool               gotName;
487     };
488 
489     //! Instantiate the appropriate handler for the section name
NewTraceMetaData(const string & sectionName,ParsedDevices & result)490     auto_ptr<Section> NewTraceMetaData(const string& sectionName, ParsedDevices& result)
491     {
492         LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n");
493 
494         if (sectionName == TraceSectionName)
495         {
496             return auto_ptr<Section>(new TraceSection(result));
497         }
498         else
499         {
500             // ignore unexpected sections, there may be others like [trace]
501             // which RDDI doesn't care about
502             return auto_ptr<Section>(new NullSection);
503         }
504     };
505 
506     class TraceBufferListSection : public Section
507     {
508     public:
TraceBufferListSection(ParsedTrace & result)509         TraceBufferListSection(ParsedTrace& result) : m_result(result), gotList(false)
510         {}
511 
Define(const string & k,const string & v)512         void Define(const string& k, const string& v)
513         {
514             if (k == BufferListKey)
515             {
516                 PreventDupes(gotList, k, TraceBuffersSectionName);
517                 std::string nameList = v;
518                 std::string::size_type pos;
519                 while((pos = nameList.find_first_of(',')) != std::string::npos)
520                 {
521                     m_result.buffer_section_names.push_back(nameList.substr(0,pos));
522                     nameList=nameList.substr(pos+1,std::string::npos);
523                 }
524                 m_result.buffer_section_names.push_back(nameList);
525             }
526         }
527 
End()528         void End() {}
529 
530     private:
531         ParsedTrace&     m_result;
532         bool             gotList;
533     };
534 
535     //! Instantiate the appropriate handler for the section name
536 
537 
538     class TraceBufferSection : public Section
539     {
540     public:
TraceBufferSection(ParsedTrace & result,const std::string & sectionName)541         TraceBufferSection(ParsedTrace& result, const std::string &sectionName) : m_result(result), m_sectionName(sectionName),
542             name(""), file(""), format(""), gotName(false), gotFile(false), gotFormat(false)
543         {}
544 
Define(const string & k,const string & v)545         void Define(const string& k, const string& v)
546         {
547             if (k == BufferNameKey)
548             {
549                 PreventDupes(gotName, k, m_sectionName);
550                 name = v;
551             }
552             else if (k == BufferFileKey)
553             {
554                 PreventDupes(gotFile, k, m_sectionName);
555                 file = v;
556             }
557             else if (k == BufferFormatKey)
558             {
559                 PreventDupes(gotFormat, k, m_sectionName);
560                 format = v;
561             }
562         }
563 
End()564         void End()
565         {
566             if (!gotName)
567             {
568                 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE,  "Trace Buffer section missing required buffer name");
569             }
570             if (!gotFile)
571             {
572                 throw ocsdError(OCSD_ERR_SEV_ERROR, OCSD_ERR_TEST_SNAPSHOT_PARSE, "Trace Buffer section is missing mandatory file definition");
573             }
574 
575             struct TraceBufferInfo info = { name, file, format };
576             m_result.trace_buffers.push_back(info);
577         }
578 
579 
580     private:
581         ParsedTrace&     m_result;
582         std::string m_sectionName;
583         std::string name;
584         bool gotName;
585         std::string file;
586         bool gotFile;
587         std::string format;
588         bool gotFormat;
589 
590     };
591 
592     class TraceSourceBuffersSection : public Section
593     {
594     public:
TraceSourceBuffersSection(ParsedTrace & result)595         TraceSourceBuffersSection(ParsedTrace& result) : m_result(result)
596         {}
597 
Define(const string & k,const string & v)598         void Define(const string& k, const string& v)
599         {
600             // k is the source name, v is the buffer name
601             m_result.source_buffer_assoc[k] = v;
602         }
603 
End()604         void End() {}
605 
606     private:
607         ParsedTrace&     m_result;
608     };
609 
610     class TraceCpuSourceSection : public Section
611     {
612     public:
TraceCpuSourceSection(ParsedTrace & result)613         TraceCpuSourceSection(ParsedTrace& result) : m_result(result)
614         {}
615 
Define(const string & k,const string & v)616         void Define(const string& k, const string& v)
617         {
618             // k is the cpu name, v is the source name
619             m_result.cpu_source_assoc[v] = k;
620         }
621 
End()622         void End() {}
623 
624     private:
625         ParsedTrace&     m_result;
626     };
627 
NewTraceSection(const string & sectionName,ParsedTrace & result)628     auto_ptr<Section> NewTraceSection(const string& sectionName, ParsedTrace& result)
629     {
630         LogInfoStr((std::string)"Start of " + sectionName + (std::string)" section\n");
631 
632         if (sectionName == TraceBuffersSectionName)
633         {
634             return auto_ptr<Section>(new TraceBufferListSection(result));
635         }
636         else if(sectionName == SourceBuffersSectionName)
637         {
638             return auto_ptr<Section>(new TraceSourceBuffersSection(result));
639         }
640         else if(sectionName == CoreSourcesSectionName)
641         {
642             return auto_ptr<Section>(new  TraceCpuSourceSection(result));
643         }
644         else
645         {
646             // check the list of buffer sections
647             std::vector<std::string>::iterator it = result.buffer_section_names.begin();
648             bool matchedName = false;
649             while(it != result.buffer_section_names.end())
650             {
651                 if(sectionName == *it)
652                 {
653                     return auto_ptr<Section>(new TraceBufferSection(result, sectionName));
654                 }
655                 it++;
656             }
657             // ignore unexpected sections,
658             return auto_ptr<Section>(new IgnoredSection);
659         }
660     };
661 
662 
663 }
664 
665 using namespace ParserPrivate;
666 
ParseSingleDevice(istream & in)667 Parser::Parsed Parser::ParseSingleDevice(istream& in)
668 {
669     Parsed result;
670 
671     string line;
672     auto_ptr<Section> section(new NullSection);
673 
674     while (getline(in, line))
675     {
676         CleanLine(line); // remove LF, comments
677         string sectionName;
678 
679         if (IsSectionHeader(line, sectionName))
680         {
681             // Section ends with start of next section...
682             section->End();
683             section = NewSection(sectionName, result);
684         }
685         else if (!IsEmpty(line))
686         {
687             if (dynamic_cast<IgnoredSection *>(section.get()) == NULL)
688             { // NOT an ignored section, so process it
689                 pair<string, string> kv(SplitKeyValue(line));
690                 section->Define(kv.first, kv.second);
691             }
692         }
693     }
694     // ... or end of file
695     section->End();
696     return result;
697 }
698 
ParseDeviceList(istream & in)699 Parser::ParsedDevices Parser::ParseDeviceList(istream& in)
700 {
701     ParsedDevices result;
702     result.snapshotInfo.description = "";
703     // call the original format 0.0, the device_list format 0.1 and the flexible format (including version) 1.0
704     result.snapshotInfo.version = "0.1";
705     string line;
706     auto_ptr<Section> section(new NullSection);
707 
708     while (getline(in, line))
709     {
710         CleanLine(line); // remove LF, comments
711         string sectionName;
712 
713         if (IsSectionHeader(line, sectionName))
714         {
715             // Section ends with start of next section...
716             section->End();
717 
718             if (sectionName == SnapshotSectionName)
719                 section = NewSnapshotInfo(sectionName, result);
720             else if(sectionName == TraceSectionName)
721                 section = NewTraceMetaData(sectionName, result);
722             else // else rather than elseif for closer compatibility with old tests
723                 section = NewDeviceList(sectionName, result);
724         }
725         else if (!IsEmpty(line) &&
726                     ( dynamic_cast<DeviceListSection *>(section.get()) != NULL ||
727                       dynamic_cast<SnapshotSection *>(section.get()) != NULL ||
728                       dynamic_cast<TraceSection *>(section.get()) != NULL
729                     )
730                 )
731         {
732             pair<string, string> kv(SplitKeyValue(line));
733             section->Define(kv.first, kv.second);
734         }
735     }
736     // ... or end of file
737     section->End();
738 
739     return result;
740 }
741 
742 
743 // parse the trace metadata ini file.
ParseTraceMetaData(std::istream & in)744 ParsedTrace Parser::ParseTraceMetaData(std::istream& in)
745 {
746     ParsedTrace result;
747 
748     string line;
749     auto_ptr<Section> section(new NullSection);
750 
751     while (getline(in, line))
752     {
753         CleanLine(line); // remove LF, comments
754         string sectionName;
755 
756         if (IsSectionHeader(line, sectionName))
757         {
758             // Section ends with start of next section...
759             section->End();
760             section = NewTraceSection(sectionName, result);
761         }
762         else if (!IsEmpty(line))
763         {
764             if (dynamic_cast<IgnoredSection *>(section.get()) == NULL)
765             { // NOT an ignored section, so process it
766                 pair<string, string> kv(SplitKeyValue(line));
767                 section->Define(kv.first, kv.second);
768             }
769         }
770     }
771     // ... or end of file
772     section->End();
773     return result;
774 }
775 
776     // build a source tree for a single buffer
ExtractSourceTree(const std::string & buffer_name,ParsedTrace & metadata,TraceBufferSourceTree & buffer_data)777 bool Parser::ExtractSourceTree(const std::string &buffer_name, ParsedTrace &metadata, TraceBufferSourceTree &buffer_data)
778 {
779     bool bFoundbuffer = false;
780     std::vector<TraceBufferInfo>::iterator it = metadata.trace_buffers.begin();
781 
782     while((it != metadata.trace_buffers.end()) && !bFoundbuffer)
783     {
784         if(it->bufferName == buffer_name)
785         {
786             bFoundbuffer = true;
787             buffer_data.buffer_info = *it;
788         }
789         it++;
790     }
791 
792     if(bFoundbuffer)
793     {
794         std::map<std::string, std::string>::iterator sbit = metadata.source_buffer_assoc.begin();
795         while(sbit != metadata.source_buffer_assoc.end())
796         {
797             if(sbit->second == buffer_data.buffer_info.bufferName)
798             {
799                 // found a source in this buffer...
800                 buffer_data.source_core_assoc[sbit->first] = metadata.cpu_source_assoc[sbit->first];
801             }
802             sbit++;
803         }
804     }
805     return bFoundbuffer;
806 }
807 
GetBufferNameList(ParsedTrace & metadata)808 std::vector<std::string> Parser::GetBufferNameList(ParsedTrace &metadata)
809 {
810     std::vector<std::string> nameList;
811     std::vector<TraceBufferInfo>::iterator it = metadata.trace_buffers.begin();
812     while(it != metadata.trace_buffers.end())
813     {
814         nameList.push_back(it->bufferName);
815         it++;
816     }
817     return nameList;
818 }
819 
SetIErrorLogger(ITraceErrorLog * i_err_log)820 void Parser::SetIErrorLogger(ITraceErrorLog *i_err_log)
821 {
822     s_pErrorLogger = i_err_log;
823     if(s_pErrorLogger)
824     {
825         s_errlog_handle = s_pErrorLogger->RegisterErrorSource("snapshot_parser");
826     }
827 }
828 
GetIErrorLogger()829 ITraceErrorLog *Parser::GetIErrorLogger()
830 {
831     return s_pErrorLogger;
832 }
833 
LogInfoStr(const std::string & logMsg)834 void Parser::LogInfoStr(const std::string &logMsg)
835 {
836     if(GetIErrorLogger() && s_verbose_logging)
837         GetIErrorLogger()->LogMessage(s_errlog_handle,OCSD_ERR_SEV_INFO,logMsg);
838 }
839 
SetVerboseLogging(bool verbose)840 void Parser::SetVerboseLogging(bool verbose)
841 {
842     s_verbose_logging = verbose;
843 }
844 /* End of File snapshot_parser.cpp */
845