copyleft: gplv3 added and set repo to public
[calu.git] / 3c_disasm / CInstrFactory.cpp
1 /*   `Deep Thought', a softcore CPU implemented on a FPGA
2
3     Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
4     Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
5     Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
6     Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
7     Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
8
9     This program is free software: you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation, either version 3 of the License, or
12     (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program.  If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "CInstrFactory.hpp"
23
24 using namespace std;
25
26 /**
27  * Name:    loadFromLib
28  * Purpose: loads a command from the given library file
29
30  * Parameter: std::string lib  location of the library file
31
32  * Preconditions:  lib references to a valid library
33  */
34 Iinstr* CInstrFactory::loadFromLib(string lib)
35 {
36         Iinstr* (*create_instruction)();
37
38         // load a Instruction from library
39         void* instruction = dlopen(lib.c_str(), RTLD_LAZY);
40         if (!instruction) {
41                 cerr << "Cannot load library: " << dlerror() << endl;
42                 exit(EXIT_FAILURE);
43         }
44
45         // load the symbols
46         void* create = dlsym(instruction, "create_instruction");
47         void* destroy = dlsym(instruction, "destroy_instruction");
48
49         if (!create || !destroy) {
50                 cerr << "Cannot load symbols: " << dlerror() << endl;
51                 dlclose(instruction);
52                 exit(EXIT_FAILURE);
53         }
54
55         memcpy(&create_instruction, &create, sizeof(create)); 
56
57         Iinstr* instructionPointer = create_instruction();
58
59         m_libStore.insert(make_pair(instruction, instructionPointer));
60
61         return instructionPointer;
62 }
63
64 /**
65  * Name:    getNextInstruction
66  * Purpose: returns a pointer to a command
67
68  * Returns: Pointer to the loaded command
69
70  * Throw:  string
71  * Preconditions:  a command is left to load
72  */
73 Iinstr* CInstrFactory::getNextInstr()
74 {
75         if(m_files.size() >= 1) {
76                 Iinstr* instruction;
77                 instruction = loadFromLib(m_files[0]);
78                 m_files.erase(m_files.begin());
79                 return instruction;
80         }
81         else {
82                 throw string("No more instruction left!");
83         }
84 }
85
86
87 /**
88  * Name:    searchLibsInDir
89  * Purpose: finds librarys in the given directory
90
91  * Returns: number of found librarays
92
93  * Parameters: std::string dir  Directory where the libraries are located
94  * Throw:  string
95  * Postconditions: all files with a trailing '.so' are ready to be used
96  */
97 size_t CInstrFactory::searchLibsInDir(string dir)
98 {
99         DIR *dp;
100
101         if((dp  = opendir(dir.c_str())) == NULL) {
102                 stringstream errmsg;
103                 errmsg << "Error(" << errno << ") opening " << dir << endl;
104                 throw errmsg.str();
105         }
106         struct dirent *dirp;
107         while ((dirp = readdir(dp)) != NULL) {
108                 string file = dirp->d_name;
109                 if(file.size() >= 3) {
110                         file = file.substr(file.size()-3);
111                         std::transform(file.begin(), file.end(), file.begin(), ::tolower);
112                         if(file == ".so") {
113                                 m_files.push_back(dir+"/"+string(dirp->d_name));
114                         }
115                 }
116         }
117         closedir(dp);
118         return m_files.size();
119 }
120
121 /**
122  * Name:    getNumFiles
123  * Purpose: returns the number of librarys left
124
125  * Returns: size_t number of files left
126  */
127 size_t CInstrFactory::getNumFiles()
128 {
129         return m_files.size();
130 }
131
132 void CInstrFactory::loadLibsIntoMap(map<short, Iinstr*>& instr, string dir)
133 {
134 #ifdef DEBUG
135                 cout << "Loaded " << this->searchLibsInDir(dir) << " Libraryfiles" << endl;
136 #else
137                 this->searchLibsInDir(dir);
138 #endif
139                 while(this->getNumFiles() >= 1) {
140                         Iinstr* pinstr = this->getNextInstr();
141                         instr.insert(make_pair(pinstr->getOpcode(),pinstr));
142 #ifdef DEBUG
143                         cout << "found: " << pinstr->getName() << " its opcode is : " << pinstr->getOpcode() << endl;
144 #endif
145                 }
146 }
147
148
149 /**
150  * Name:    ~CInstrFactory
151  * Purpose: Destructor of the Object
152  */
153 CInstrFactory::~CInstrFactory()
154 {
155         void (*destroy_instruction)(Iinstr*);
156
157         while(!m_libStore.empty()) {
158                 void* destroy = dlsym(m_libStore.begin()->first, "destroy_instruction");
159                 memcpy(&destroy_instruction, &destroy, sizeof(destroy)); 
160                 destroy_instruction(m_libStore.begin()->second);
161                 dlclose(m_libStore.begin()->first);
162                 m_libStore.erase(m_libStore.begin());
163         }
164 }