LoadCommand.cc Source File

Back to the index.

LoadCommand.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2010 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <fstream>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "commands/LoadCommand.h"
33 #include "FileLoader.h"
34 #include "GXemul.h"
35 
36 
38  : Command("load", "[filename [component-path]]")
39 {
40 }
41 
42 
44 {
45 }
46 
47 
48 static void ShowMsg(GXemul& gxemul, const string& msg)
49 {
50  gxemul.GetUI()->ShowDebugMessage(msg);
51 }
52 
53 
54 bool LoadCommand::IsComponentTree(GXemul& gxemul, const string& filename) const
55 {
56  std::ifstream file(filename.c_str());
57  if (file.fail())
58  return false;
59 
60  char buf[256];
61  file.read(buf, sizeof(buf));
62  if (file.gcount() < 10)
63  return false;
64 
65  // Saved component trees start with the string "component ".
66  return (strncmp(buf, "component ", 10) == 0);
67 }
68 
69 
70 bool LoadCommand::LoadComponentTree(GXemul& gxemul, const string&filename,
71  refcount_ptr<Component> specifiedComponent) const
72 {
73  const string extension = ".gxemul";
74  if (filename.length() < extension.length() || filename.substr(
75  filename.length() - extension.length()) != extension)
76  ShowMsg(gxemul, "Warning: the name " + filename +
77  " does not have a .gxemul extension. Continuing anyway.\n");
78 
79  refcount_ptr<Component> component;
80 
81  // Load from the file
82  std::ifstream file(filename.c_str());
83  if (file.fail()) {
84  ShowMsg(gxemul, "Unable to open " + filename + " for reading.\n");
85  return false;
86  }
87 
88  // Figure out the file's size:
89  file.seekg(0, std::ios::end);
90  std::streampos fileSize = file.tellg();
91  file.seekg(0, std::ios::beg);
92 
93  // Read the entire file into a string.
94  // TODO: This is wasteful, of course. It actually takes twice the
95  // size of the file, since the string constructor generates a _copy_.
96  // But string takes care of unicode and such (if compiled as ustring).
97  vector<char> buf;
98  buf.resize((size_t)fileSize + 1);
99 
100  memset(&buf[0], 0, fileSize);
101  file.read(&buf[0], fileSize);
102  if (file.gcount() != fileSize) {
103  ShowMsg(gxemul, "Loading from " + filename + " failed; "
104  "could not read all of the file?\n");
105  return false;
106  }
107 
108  string str(&buf[0], fileSize);
109 
110  file.close();
111 
112  size_t strPos = 0;
113  stringstream messages;
114  component = Component::Deserialize(messages, str, strPos);
115 
116  if (messages.str().length() > 0)
117  ShowMsg(gxemul, messages.str());
118 
119  if (component.IsNULL()) {
120  ShowMsg(gxemul, "Loading from " + filename + " failed; "
121  "no component found?\n");
122  return false;
123  }
124 
125  if (specifiedComponent.IsNULL()) {
126  const StateVariable* name = component->GetVariable("name");
127  if (name == NULL || name->ToString() != "root")
128  gxemul.GetRootComponent()->AddChild(component);
129  else
130  gxemul.SetRootComponent(component);
131 
132  gxemul.SetEmulationFilename(filename);
133 
134  ShowMsg(gxemul, filename + " loaded\n");
135  } else {
136  specifiedComponent->AddChild(component);
137 
138  ShowMsg(gxemul, filename + " loaded into " +
139  specifiedComponent->GenerateShortestPossiblePath() + "\n");
140  }
141 
142  return true;
143 }
144 
145 bool LoadCommand::Execute(GXemul& gxemul, const vector<string>& arguments)
146 {
147  string filename = gxemul.GetEmulationFilename();
148  string path = "";
149 
150  if (arguments.size() > 2) {
151  ShowMsg(gxemul, "Too many arguments.\n");
152  return false;
153  }
154 
155  if (arguments.size() > 0)
156  filename = arguments[0];
157 
158  if (filename == "") {
159  ShowMsg(gxemul, "No filename given.\n");
160  return false;
161  }
162 
163  if (arguments.size() > 1)
164  path = arguments[1];
165 
166  // Figure out the component path, if it was specified.
167  refcount_ptr<Component> specifiedComponent;
168  if (path != "") {
169  vector<string> matches = gxemul.GetRootComponent()->
170  FindPathByPartialMatch(path);
171  if (matches.size() == 0) {
172  ShowMsg(gxemul, path +
173  " is not a path to a known component.\n");
174  return false;
175  }
176  if (matches.size() > 1) {
177  ShowMsg(gxemul, path +
178  " matches multiple components:\n");
179  for (size_t i=0; i<matches.size(); i++)
180  ShowMsg(gxemul, " " + matches[i] + "\n");
181  return false;
182  }
183 
184  specifiedComponent =
185  gxemul.GetRootComponent()->LookupPath(matches[0]);
186  if (specifiedComponent.IsNULL()) {
187  ShowMsg(gxemul, "Lookup of " + path + " failed.\n");
188  return false;
189  }
190  }
191 
192  // 1. Is it a component tree?
193  if (IsComponentTree(gxemul, filename)) {
194  if (specifiedComponent.IsNULL())
195  gxemul.ClearEmulation();
196 
197  return LoadComponentTree(gxemul, filename, specifiedComponent);
198  }
199 
200  if (specifiedComponent.IsNULL()) {
201  ShowMsg(gxemul, "The specified file to load (" + filename +
202  ") is not a configuration tree. If it is a binary to load,"
203  " you need to specify a component path where to load the"
204  " binary.\n");
205  return false;
206  }
207 
208  // 2. Is it a binary (ELF, a.out, ...)?
209  FileLoader fileLoader(filename);
210  stringstream messages;
211  if (fileLoader.Load(specifiedComponent, messages)) {
212  gxemul.GetUI()->ShowDebugMessage(specifiedComponent,
213  filename + " loaded\n" + messages.str());
214  return true;
215  } else {
216  gxemul.GetUI()->ShowDebugMessage(specifiedComponent,
217  "FAILED to load " + filename + "\n" + messages.str());
218  return false;
219  }
220 }
221 
222 
224 {
225  return "Loads a file.";
226 }
227 
228 
230 {
231  return
232  "Loads a file into a location in the component tree. There are two different\n"
233  "uses, which all share the same general syntax but differ in meaning.\n"
234  "\n"
235  "1. Loads an emulation setup (.gxemul) which was previously saved with the\n"
236  " 'save' command. For example, if a machine was previously saved into\n"
237  " myMachine.gxemul, then\n"
238  "\n"
239  " load myMachine.gxemul root\n"
240  "\n"
241  " will add the machine to the current emulation tree, next to any other\n"
242  " machines.\n"
243  "\n"
244  " load myMachine.gxemul\n"
245  "\n"
246  " will instead replace the whole configuration tree with what's in\n"
247  " myMachine.gxemul. The filename may be omitted, if it is known from an\n"
248  " earlier save or load command.\n"
249  "\n"
250  "2. Loads a binary (ELF, a.out, ...) into a CPU or data bus. E.g.:\n"
251  "\n"
252  " load netbsd-RAMDISK cpu0\n"
253  "\n"
254  " will load a NetBSD kernel into cpu0 (assuming that cpu0 is not ambiguous).\n"
255  " The reason why files should be loaded into CPUs and not into RAM components\n"
256  " is that binaries are often linked to virtual addresses, and the CPU does\n"
257  " virtual to physical address translation.\n"
258  "\n"
259  "See also: save (to save an emulation to a file)\n";
260 }
261 
refcount_ptr::IsNULL
bool IsNULL() const
Checks whether or not an object is referenced by the reference counted pointer.
Definition: refcount_ptr.h:218
Component::AddChild
void AddChild(refcount_ptr< Component > childComponent, size_t insertPosition=(size_t) -1)
Adds a reference to a child component.
Definition: Component.cc:595
GXemul
The main emulator class.
Definition: GXemul.h:55
GXemul::ClearEmulation
void ClearEmulation()
Discards the current emulation, and starts anew with just an empty root component.
Definition: GXemul.cc:192
Component::Deserialize
static refcount_ptr< Component > Deserialize(ostream &messages, const string &str, size_t &pos)
Deserializes a string into a component tree.
Definition: Component.cc:1130
StateVariable
StateVariables make up the persistent state of Component objects.
Definition: StateVariable.h:69
LoadCommand::~LoadCommand
virtual ~LoadCommand()
Definition: LoadCommand.cc:43
refcount_ptr< Component >
Command
A Command is a named function, executed by the CommandInterpreter.
Definition: Command.h:51
FileLoader::Load
bool Load(refcount_ptr< Component > component, ostream &messages) const
Loads the file into a CPU or an AddressDataBus.
Definition: FileLoader.cc:97
GXemul::GetRootComponent
refcount_ptr< Component > GetRootComponent()
Gets a pointer to the root configuration component.
Definition: GXemul.cc:659
GXemul::SetEmulationFilename
void SetEmulationFilename(const string &filename)
Sets the current emulation setup's filename.
Definition: GXemul.cc:615
UI::ShowDebugMessage
virtual void ShowDebugMessage(const string &msg)=0
Shows a debug message.
LoadCommand::Execute
virtual bool Execute(GXemul &gxemul, const vector< string > &arguments)
Executes the command on a given GXemul instance.
Definition: LoadCommand.cc:145
Component::LookupPath
const refcount_ptr< Component > LookupPath(string path) const
Looks up a path from this Component, and returns a pointer to the found Component,...
Definition: Component.cc:778
FileLoader
A class used to load binary files into emulated memory.
Definition: FileLoader.h:55
StateVariable::ToString
string ToString() const
Returns the variable as a readable string.
Definition: StateVariable.cc:229
Component::GenerateShortestPossiblePath
string GenerateShortestPossiblePath() const
Generates a short string representation of the path to the Component.
Definition: Component.cc:721
LoadCommand.h
LoadCommand::GetLongDescription
virtual string GetLongDescription() const
Returns a long description/help message for the command.
Definition: LoadCommand.cc:229
GXemul::GetUI
UI * GetUI()
Gets a pointer to the GXemul instance' active UI.
Definition: GXemul.cc:653
FileLoader.h
LoadCommand::GetShortDescription
virtual string GetShortDescription() const
Returns a short (one-line) description of the command.
Definition: LoadCommand.cc:223
Component::GetVariable
StateVariable * GetVariable(const string &name)
Gets a pointer to a state variable.
Definition: Component.cc:949
GXemul::GetEmulationFilename
const string & GetEmulationFilename() const
Gets the current emulation setup's filename.
Definition: GXemul.cc:609
LoadCommand::LoadCommand
LoadCommand()
Constructs an LoadCommand.
Definition: LoadCommand.cc:37
GXemul::SetRootComponent
void SetRootComponent(refcount_ptr< Component > newRootComponent)
Sets the root component, discarding the previous one.
Definition: GXemul.cc:671
GXemul.h

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18