1 /*-
2 * Copyright (c) 2006, 2007 CTPP Team
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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 * 4. Neither the name of the CTPP Team nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * VMEmulator.cpp
29 *
30 * $CTPP$
31 */
32
33 #include <CTPP2JSONParser.hpp>
34 #include <CTPP2FileOutputCollector.hpp>
35 #include <CTPP2FileLogger.hpp>
36 #include <CTPP2SyscallFactory.hpp>
37 #include <CTPP2VMDebugInfo.hpp>
38 #include <CTPP2VM.hpp>
39 #include <CTPP2VMFileLoader.hpp>
40 #include <CTPP2VMSTDLib.hpp>
41 #include <CTPP2VMStackException.hpp>
42 #include <CTPP2GetText.hpp>
43
44 #include <sys/stat.h>
45
46 #ifdef HAVE_SYS_TIME_H
47 #include <sys/time.h>
48 #endif
49
50 #ifdef WIN32
51 #include <CTPP2Time.h>
52 #endif
53
54 #include <stdio.h>
55 #include <string.h>
56
57 #include <memory>
58
59 using namespace CTPP;
60
main(int argc,char ** argv)61 int main(int argc, char ** argv)
62 {
63 INT_32 iRetCode = EX_SOFTWARE;
64
65 if (argc != 2 && argc != 3 && argc != 4 && argc != 5)
66 {
67 fprintf(stdout, "CTPP2 virtual machine v" CTPP_VERSION " (" CTPP_IDENT "). Copyright (c) 2004-2011 CTPP Dev. Team.\n\n");
68 fprintf(stderr, "usage: %s file.name [data.json] [output.txt | 0] [translation.mo | 0] [limit of steps]\n", argv[0]);
69 return EX_USAGE;
70 }
71
72 // Initialize Standard CTPP library
73 SyscallFactory oSyscallFactory(100);
74 // Load standard library
75 STDLibInitializer::InitLibrary(oSyscallFactory);
76 // Output
77 std::auto_ptr<FileOutputCollector> pOutputCollector(new FileOutputCollector(stdout));
78
79 if (argc >= 4 && strncmp(argv[3], "0", sizeof(argv[3])) != 0) { pOutputCollector.reset(new FileOutputCollector(argv[3], "w+")); }
80
81
82 CTPP2GetText oGetText;
83 if (argc >= 5 && strncmp(argv[4], "0", sizeof(argv[4])) != 0) { oGetText.AddTranslation(argv[4], "test", "unknown"); }
84 oGetText.InitSTDLibFunction(oSyscallFactory);
85 oGetText.SetLanguage(oSyscallFactory, "unknown");
86 oGetText.SetDefaultDomain("test");
87
88 UINT_32 iStepsLimit = 10240;
89 if(argc == 6) { iStepsLimit = atoi(argv[5]); }
90 else
91 {
92 fprintf(stderr, "WARNING: [limit of steps] not set, use default value of %d\n", iStepsLimit);
93 }
94
95 try
96 {
97 // Load program from file
98 VMFileLoader oLoader(argv[1]);
99
100 // Get program core
101 const VMMemoryCore * pVMMemoryCore = oLoader.GetCore();
102
103 CDT oHash(CDT::HASH_VAL);
104
105 // Load JSON data
106 if(argc >= 3)
107 {
108 struct stat oStat;
109 // Get file size
110 if (stat(argv[2], &oStat) == -1 || oStat.st_size == 0) { fprintf(stderr, "ERROR: Cannot get size of file `%s`\n", argv[2]); return EX_SOFTWARE; }
111
112 // Allocate memory
113 CHAR_8 * szJSONBuffer = (CHAR_8 *)malloc(oStat.st_size + 1);
114 // Read from file
115 FILE * F = fopen(argv[2], "rb");
116 if (F == NULL) { fprintf(stderr, "ERROR: Cannot open file `%s` for reading\n", argv[2]); return EX_SOFTWARE; }
117
118 if (fread(szJSONBuffer, oStat.st_size, 1, F) != 1)
119 {
120 fprintf(stderr, "ERROR: Cannot read from file `%s`\n", argv[2]);
121 fclose(F);
122 free(szJSONBuffer);
123 return EX_SOFTWARE;
124 }
125
126 szJSONBuffer[oStat.st_size] = '\0';
127
128 CTPP2JSONParser oJSONParser(oHash);
129 CCHAR_P szEnd = szJSONBuffer + oStat.st_size;
130 oJSONParser.Parse(szJSONBuffer, szEnd);
131
132 // All Done
133 fclose(F);
134 // All done with loading
135 free(szJSONBuffer);
136 }
137 else
138 {
139 fprintf(stderr, "WARNING: [data.json] not given\n");
140 }
141
142 // Logger
143 FileLogger oLogger(stderr);
144
145 // Run program
146 VM oVM(&oSyscallFactory, 10240, 10240, iStepsLimit);
147
148 struct timeval sTimeValLocBegin;
149 gettimeofday(&sTimeValLocBegin, NULL);
150
151 UINT_32 iIP = 0;
152 oVM.Init(pVMMemoryCore, pOutputCollector.get(), &oLogger);
153 oVM.Run(pVMMemoryCore, pOutputCollector.get(), iIP, oHash, &oLogger);
154
155 struct timeval sTimeValLocEnd;
156 gettimeofday(&sTimeValLocEnd, NULL);
157
158 fprintf(stderr, "Completed in %f seconds.\n", (1.0 * (sTimeValLocEnd.tv_sec - sTimeValLocBegin.tv_sec) + 1.0 * (sTimeValLocEnd.tv_usec - sTimeValLocBegin.tv_usec) / 1000000));
159
160 iRetCode = EX_OK;
161 }
162 // CDT
163 catch(CDTTypeCastException & e) { fprintf(stderr, "ERROR: Type Cast %s\n", e.what()); }
164 catch(CDTAccessException & e) { fprintf(stderr, "ERROR: Array index out of bounds: %s\n", e.what()); }
165
166 // Virtual machine
167 catch(IllegalOpcode & e) { fprintf(stderr, "ERROR: Illegal opcode 0x%08X at 0x%08X\n", e.GetOpcode(), e.GetIP()); }
168 catch(InvalidSyscall & e)
169 {
170 if (e.GetIP() != 0)
171 {
172 VMDebugInfo oVMDebugInfo(e.GetDebugInfo());
173 fprintf(stderr, "ERROR: %s at 0x%08X (Template file \"%s\", Line %d, Pos %d)\n", e.what(), e.GetIP(), e.GetSourceName(), oVMDebugInfo.GetLine(), oVMDebugInfo.GetLinePos());
174 }
175 else
176 {
177 fprintf(stderr, "Unsupported syscall: \"%s\"\n", e.what());
178 }
179 }
180 catch(InvalidCall & e)
181 {
182 VMDebugInfo oVMDebugInfo(e.GetDebugInfo());
183 fprintf(stderr, "ERROR: at 0x%08X: Invalid block name \"%s\" in file \"%s\", Line %d, Pos %d\n", e.GetIP(), e.what(), e.GetSourceName(), oVMDebugInfo.GetLine(), oVMDebugInfo.GetLinePos());
184 }
185 catch(CodeSegmentOverrun & e) { fprintf(stderr, "ERROR: %s at 0x%08X\n", e.what(), e.GetIP()); }
186 catch(StackOverflow & e) { fprintf(stderr, "ERROR: Stack overflow at 0x%08X\n", e.GetIP()); }
187 catch(StackUnderflow & e) { fprintf(stderr, "ERROR: Stack underflow at 0x%08X\n", e.GetIP()); }
188 catch(ExecutionLimitReached & e) { fprintf(stderr, "ERROR: Execution limit of %d step(s) reached at 0x%08X\n", iStepsLimit, e.GetIP()); }
189 catch(VMException & e) { fprintf(stderr, "ERROR: VM generic exception: %s at 0x%08X\n", e.what(), e.GetIP()); }
190
191 // CTPP
192 catch(CTPPLogicError & e) { fprintf(stderr, "ERROR: %s\n", e.what()); }
193 catch(CTPPUnixException & e) { fprintf(stderr, "ERROR: I/O in %s: %s\n", e.what(), strerror(e.ErrNo())); }
194 catch(CTPPException & e) { fprintf(stderr, "ERROR: CTPP Generic exception: %s\n", e.what()); }
195
196 // Destroy standard library
197 STDLibInitializer::DestroyLibrary(oSyscallFactory);
198
199 // make valgrind happy
200 fclose(stdin);
201 fclose(stdout);
202 fclose(stderr);
203
204 return iRetCode;
205 }
206 // End.
207
208