OSDN Git Service

d8c29170e881caab26dcf868a9b43bc167a7884d
[qcad/qcad.git] / compiler / qcrun.cpp
1 //----------------------------------------------------------------------------\r
2 //  qcrun.cpp\r
3 //  Interpreter for ntermediate code\r
4 //  $Date: 2003/02/20 00:24:16 $\r
5 //  $Revision: 1.8 $\r
6 //----------------------------------------------------------------------------\r
7 #include <iostream>\r
8 #include <iomanip>\r
9 #include <fstream>\r
10 #include <cstdlib>\r
11 #include <vector>\r
12 #include <string>\r
13 \r
14 #include "QBits.h"\r
15 #include "QCompilerCntl.h"\r
16 #include "QCalcUnit.h"\r
17 \r
18 typedef unsigned int                Appoptions;\r
19 typedef std::vector<QCalcUnit *>    QCalcUnits;\r
20 \r
21 const char * const  app_name        = "qcrun";\r
22 const char * const  app_version     = "1.0";\r
23 \r
24 const Appoptions    opt_version     = 1;\r
25 const Appoptions    opt_help        = 1 << 1;\r
26 const Appoptions    opt_verbose     = 1 << 2;\r
27 const Appoptions    opt_output      = 1 << 3;\r
28 const Appoptions    opt_input       = 1 << 4;\r
29 \r
30 //----------------------------------------------------------------------------\r
31 //  Function prototypes\r
32 //----------------------------------------------------------------------------\r
33 inline bool isSet(const Appoptions &o1, const Appoptions &o2) {\r
34   return (o2 == (o1 & o2));\r
35 }\r
36 \r
37 Appoptions  checkOption(const char * inOptions);\r
38 void        compile(QCompilerCntl * const , QCalcUnits * const);\r
39 void        forceQuit(void);\r
40 void        printUsage(void);\r
41 void        printVersion(void);\r
42 void        errorAndQuit(const char * const inMessage);\r
43 std::string getBaseFilename(const std::string &inString);\r
44 \r
45 //----------------------------------------------------------------------------\r
46 /**\r
47  *  Main\r
48  */\r
49 int main(int argc, char **argv) {\r
50   Appoptions      parameters_ready    = 0;\r
51   QBits           *qBits              = NULL;\r
52   QCompilerCntl   *qCCntl             = NULL;\r
53   QCalcUnits      *qCalcUnits         = NULL;\r
54 \r
55   std::string               tfilename = "";\r
56   std::string               ofilename = "";\r
57   std::string               ifilename = "";\r
58   std::vector<std::string>  args;\r
59 \r
60   if (argc <= 1) {\r
61     printVersion();\r
62     printUsage();\r
63     std::exit(0);\r
64   }\r
65 \r
66   for (int i = 0; i < argc; i++) {\r
67     std::string tmpstr = argv[i];\r
68     args.push_back(tmpstr);\r
69   }\r
70 \r
71   int vec_size = args.size();\r
72   int arg_at   = 1;\r
73 \r
74   while (arg_at < vec_size) {\r
75     if ('-' == args[arg_at][0] && args[arg_at].length() > 1) {\r
76       Appoptions tmpoptions = checkOption(args[arg_at].c_str());\r
77 \r
78       //_____ HELP _____\r
79       if (isSet(tmpoptions, opt_help)) {\r
80         if (isSet(parameters_ready, opt_help)) {\r
81           errorAndQuit("-h option can be used only once.");\r
82         } else {\r
83           parameters_ready |= opt_help;\r
84         }\r
85       }\r
86 \r
87       //_____ VERBOSE _____\r
88       if (isSet(tmpoptions, opt_verbose)) {\r
89         if (isSet(parameters_ready, opt_verbose)) {\r
90           errorAndQuit("-v option can be used only once.");\r
91         } else {\r
92           parameters_ready |= opt_verbose;\r
93         }\r
94       }\r
95 \r
96       //_____ VERSION _____\r
97       if (isSet(tmpoptions, opt_version)) {\r
98         if (isSet(parameters_ready, opt_version)) {\r
99           errorAndQuit("-V option can be used only once.");\r
100         } else {\r
101           parameters_ready |= opt_version;\r
102         }\r
103       }\r
104 \r
105       //_____ OUTPUT _____\r
106       if (isSet(tmpoptions, opt_output)) {\r
107         if (isSet(parameters_ready, opt_output)) {\r
108           errorAndQuit("-o option can be used only once.");\r
109         }\r
110 \r
111         if (arg_at < vec_size - 1) {\r
112           ofilename         = args[++arg_at];\r
113           parameters_ready |= opt_output;\r
114         } else {\r
115           errorAndQuit("too few parameters.");\r
116         }\r
117       }\r
118       arg_at++;\r
119       continue;\r
120     }\r
121 \r
122     if (isSet(parameters_ready, opt_input)) {\r
123       errorAndQuit("too many input file.");\r
124     } else {\r
125       ifilename = args[arg_at];\r
126       parameters_ready |= opt_input;\r
127     }\r
128     arg_at++;\r
129   }\r
130 \r
131   //_____ VERSION _____\r
132   if (isSet(parameters_ready, opt_version)) printVersion();\r
133 \r
134   //_____ HELP ________\r
135   if (isSet(parameters_ready, opt_help))    printUsage();\r
136 \r
137   //_____ OUTPUT ______\r
138   if (isSet(parameters_ready, opt_input)) {\r
139     if (false == isSet(parameters_ready, opt_output)) {\r
140       ofilename = getBaseFilename(ifilename)+".qdt";\r
141       tfilename = getBaseFilename(ifilename)+".txt";\r
142     }\r
143 \r
144     std::cerr << "Reading " << ifilename << std::endl;\r
145     std::ifstream ifs(ifilename.c_str(), std::ios::in);\r
146     if (!ifs) {\r
147       std::cerr << "Cannot open the input file.\n";\r
148       forceQuit();\r
149     }\r
150 \r
151     if (isSet(parameters_ready, opt_verbose)) {\r
152       std::cerr << "Input  file: " << ifilename << "\n"\r
153                 << "Output file: " << ofilename << "\n";\r
154     }\r
155 \r
156     try {\r
157       qCCntl      = new QCompilerCntl(ifs);\r
158       qCalcUnits  = new QCalcUnits(0);\r
159     } catch (const std::bad_alloc ex) {\r
160       std::cerr << "Failed in memory allocation.\n";\r
161       forceQuit();\r
162     }\r
163 \r
164     compile(qCCntl, qCalcUnits);\r
165 \r
166     try {\r
167       qBits       = new QBits(qCCntl->GetNumberOfQBits());\r
168     } catch (const std::bad_alloc &ex) {\r
169       std::cerr << "Failed in memory allocation.\n"\r
170                 << "This .mcd code needs at least "\r
171                 << (1 << (qCCntl->GetNumberOfQBits() + 1 + 3))\r
172                 << " bytes to allocate the qubits.\n";\r
173       forceQuit();\r
174     }\r
175 \r
176     for (unsigned int i = 0; i < qCalcUnits->size(); i++) {\r
177       if (isSet(parameters_ready, opt_verbose)) {\r
178         std::cerr << std::setw(15) << std::left\r
179                   << (*qCalcUnits)[i]->GetName()\r
180                   << " ... ";\r
181       }\r
182       (*qCalcUnits)[i]->Calc(qBits);\r
183       if (isSet(parameters_ready, opt_verbose)) {\r
184         std::cerr << "OK\n";\r
185       }\r
186     }\r
187 \r
188     std::cerr << "Saving " << ofilename << std::endl;\r
189     qBits->SaveToFile(ofilename.c_str());\r
190     std::cerr << "Saving " << tfilename << std::endl;\r
191     qBits->SaveAsText(tfilename.c_str());\r
192     delete qBits;\r
193     delete qCCntl;\r
194 \r
195     for (unsigned int i = 0; i < qCalcUnits->size(); i++) {\r
196       delete (*qCalcUnits)[i];\r
197     }\r
198     delete qCalcUnits;\r
199     ifs.close();\r
200 \r
201     std::cerr << "done." << std::endl;\r
202   }\r
203 \r
204   return 0;\r
205 }\r
206 \r
207 //----------------------------------------------------------------------------\r
208 /**\r
209  *  Check options\r
210  */\r
211 Appoptions checkOption(const char * inOptions) {\r
212   Appoptions retVal = 0;\r
213   inOptions++;\r
214   while ('\0' != *inOptions) {\r
215     switch (*inOptions) {\r
216     case 'h':\r
217       retVal |= opt_help;\r
218       break;\r
219     case 'o':\r
220       retVal |= opt_output;\r
221       break;\r
222     case 'v':\r
223       retVal |= opt_verbose;\r
224       break;\r
225     case 'V':\r
226       retVal |= opt_version;\r
227       break;\r
228     default:\r
229       errorAndQuit("there are some invalid options.");\r
230       break;\r
231     }\r
232     inOptions++;\r
233   }\r
234   return retVal;\r
235 }\r
236 \r
237 //----------------------------------------------------------------------------\r
238 /**\r
239  *\r
240  */\r
241 void compile(QCompilerCntl * const ioCompiler, QCalcUnits * const ioUnits) {\r
242   QCalcUnit *cu = NULL;\r
243   ioUnits->clear();\r
244 \r
245   if (true == ioCompiler->Compile()) {\r
246     unsigned int cntl_size = ioCompiler->GetNumberOfControl();\r
247     for (unsigned int i = 0; i < cntl_size; i++) {\r
248       cu = ioCompiler->AllocateControl(i);\r
249       if (NULL != cu) ioUnits->push_back(cu);\r
250     }\r
251   } else {\r
252     errorAndQuit("Parse error occurred.\n");\r
253   }\r
254 }\r
255 \r
256 //----------------------------------------------------------------------------\r
257 /**\r
258  *  Force quit\r
259  */\r
260 void forceQuit(void) {\r
261   std::cerr << "Quit forced.\n";\r
262   std::exit(1);\r
263 }\r
264 \r
265 //----------------------------------------------------------------------------\r
266 /**\r
267  *  Print usages\r
268  */\r
269 void printUsage(void) {\r
270   std::cout << "Usage: " << app_name\r
271             << " [-hvV] [-o output_file] input_file.mcd\n\n"\r
272             << "    -h  show this help\n"\r
273             << "    -v  verbose mode\n"\r
274             << "    -V  show version\n\n"\r
275             << std::flush;\r
276 }\r
277 \r
278 //----------------------------------------------------------------------------\r
279 /**\r
280  *  Print version\r
281  */\r
282 void printVersion(void) {\r
283   std::cout << "\nCopyright (C) 2002-2003 QCAD project\n"\r
284             << app_name << " version " << app_version << "\n\n"\r
285             << std::flush;\r
286 }\r
287 \r
288 //----------------------------------------------------------------------------\r
289 /**\r
290  *  Show message and quit\r
291  */\r
292 void errorAndQuit(const char * const inMessage) {\r
293   std::cerr << "Error: " << inMessage << "\n\n";\r
294   printUsage();\r
295   forceQuit();\r
296 }\r
297 \r
298 //----------------------------------------------------------------------------\r
299 /**\r
300  *  get basename of filename\r
301  */\r
302 std::string getBaseFilename(const std::string &inString) {\r
303   std::string retString = "";\r
304 \r
305   unsigned int posdot = inString.rfind(".", inString.length() - 1);\r
306 \r
307   if (posdot == std::string::npos) {\r
308     retString = inString;\r
309   } else {\r
310     retString.assign(inString, 0, posdot);\r
311   }\r
312   return retString;\r
313 }\r
314 //----------------------------------------------------------------------------\r