OSDN Git Service

adds README
[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     //TODO: *.qdt file cannot be imported by QCAD.\r
189     std::cerr << "Saving " << ofilename << std::endl;\r
190     qBits->SaveToFile(ofilename.c_str());\r
191     std::cerr << "Saving " << tfilename << std::endl;\r
192     qBits->SaveAsText(tfilename.c_str());\r
193     delete qBits;\r
194     delete qCCntl;\r
195 \r
196     for (unsigned int i = 0; i < qCalcUnits->size(); i++) {\r
197       delete (*qCalcUnits)[i];\r
198     }\r
199     delete qCalcUnits;\r
200     ifs.close();\r
201 \r
202     std::cerr << "done." << std::endl;\r
203   }\r
204 \r
205   return 0;\r
206 }\r
207 \r
208 //----------------------------------------------------------------------------\r
209 /**\r
210  *  Check options\r
211  */\r
212 Appoptions checkOption(const char * inOptions) {\r
213   Appoptions retVal = 0;\r
214   inOptions++;\r
215   while ('\0' != *inOptions) {\r
216     switch (*inOptions) {\r
217     case 'h':\r
218       retVal |= opt_help;\r
219       break;\r
220     case 'o':\r
221       retVal |= opt_output;\r
222       break;\r
223     case 'v':\r
224       retVal |= opt_verbose;\r
225       break;\r
226     case 'V':\r
227       retVal |= opt_version;\r
228       break;\r
229     default:\r
230       errorAndQuit("there are some invalid options.");\r
231       break;\r
232     }\r
233     inOptions++;\r
234   }\r
235   return retVal;\r
236 }\r
237 \r
238 //----------------------------------------------------------------------------\r
239 /**\r
240  *\r
241  */\r
242 void compile(QCompilerCntl * const ioCompiler, QCalcUnits * const ioUnits) {\r
243   QCalcUnit *cu = NULL;\r
244   ioUnits->clear();\r
245 \r
246   if (true == ioCompiler->Compile()) {\r
247     unsigned int cntl_size = ioCompiler->GetNumberOfControl();\r
248     for (unsigned int i = 0; i < cntl_size; i++) {\r
249       cu = ioCompiler->AllocateControl(i);\r
250       if (NULL != cu) ioUnits->push_back(cu);\r
251     }\r
252   } else {\r
253     errorAndQuit("Parse error occurred.\n");\r
254   }\r
255 }\r
256 \r
257 //----------------------------------------------------------------------------\r
258 /**\r
259  *  Force quit\r
260  */\r
261 void forceQuit(void) {\r
262   std::cerr << "Quit forced.\n";\r
263   std::exit(1);\r
264 }\r
265 \r
266 //----------------------------------------------------------------------------\r
267 /**\r
268  *  Print usages\r
269  */\r
270 void printUsage(void) {\r
271   std::cout << "Usage: " << app_name\r
272             << " [-hvV] [-o output_file] input_file.mcd\n\n"\r
273             << "    -h  show this help\n"\r
274             << "    -v  verbose mode\n"\r
275             << "    -V  show version\n\n"\r
276             << std::flush;\r
277 }\r
278 \r
279 //----------------------------------------------------------------------------\r
280 /**\r
281  *  Print version\r
282  */\r
283 void printVersion(void) {\r
284   std::cout << "\nCopyright (C) 2002-2003 QCAD project\n"\r
285             << app_name << " version " << app_version << "\n\n"\r
286             << std::flush;\r
287 }\r
288 \r
289 //----------------------------------------------------------------------------\r
290 /**\r
291  *  Show message and quit\r
292  */\r
293 void errorAndQuit(const char * const inMessage) {\r
294   std::cerr << "Error: " << inMessage << "\n\n";\r
295   printUsage();\r
296   forceQuit();\r
297 }\r
298 \r
299 //----------------------------------------------------------------------------\r
300 /**\r
301  *  get basename of filename\r
302  */\r
303 std::string getBaseFilename(const std::string &inString) {\r
304   std::string retString = "";\r
305 \r
306   unsigned int posdot = inString.rfind(".", inString.length() - 1);\r
307 \r
308   if (posdot == std::string::npos) {\r
309     retString = inString;\r
310   } else {\r
311     retString.assign(inString, 0, posdot);\r
312   }\r
313   return retString;\r
314 }\r
315 //----------------------------------------------------------------------------\r