OSDN Git Service

Initial Commit
[qcad/qcad.git] / compiler / qcpp.cpp
1 //----------------------------------------------------------------------------\r
2 //  qcpp.cpp\r
3 //  Interpreter for ntermediate code\r
4 //  $Date: 2003/02/20 00:24:16 $\r
5 //  $Revision: 1.3 $\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 "QCompilerCode.h"\r
15 \r
16 typedef unsigned int                Appoptions;\r
17 \r
18 const char * const  app_name        = "qcpp";\r
19 const char * const  app_version     = "1.0";\r
20 const char * const  app_extension   = ".cpp";\r
21 \r
22 const Appoptions    opt_version     = 1;\r
23 const Appoptions    opt_help        = 1 << 1;\r
24 const Appoptions    opt_verbose     = 1 << 2;\r
25 const Appoptions    opt_output      = 1 << 3;\r
26 const Appoptions    opt_input       = 1 << 4;\r
27 \r
28 //----------------------------------------------------------------------------\r
29 //  Function prototypes\r
30 //----------------------------------------------------------------------------\r
31 inline bool isSet(const Appoptions &o1, const Appoptions &o2) {\r
32   return (o2 == (o1 & o2));\r
33 }\r
34 \r
35 Appoptions  checkOption(const char * inOptions);\r
36 void        forceQuit(void);\r
37 void        printUsage(void);\r
38 void        printVersion(void);\r
39 void        errorAndQuit(const char * const inMessage);\r
40 std::string setOutputFilename(const std::string &inString,\r
41                               const char * const inExt = app_extension);\r
42 \r
43 //----------------------------------------------------------------------------\r
44 /**\r
45  *  Main\r
46  */\r
47 int main(int argc, char **argv) {\r
48   Appoptions      parameters_ready    = 0;\r
49   QCompilerCode   *qCCode             = NULL;\r
50 \r
51   std::string               ofilename = "";\r
52   std::string               ifilename = "";\r
53   std::vector<std::string>  args;\r
54 \r
55   if (argc <= 1) {\r
56     printVersion();\r
57     printUsage();\r
58     std::exit(0);\r
59   }\r
60 \r
61   for (int i = 0; i < argc; i++) {\r
62     std::string tmpstr = argv[i];\r
63     args.push_back(tmpstr);\r
64   }\r
65 \r
66   unsigned int vec_size = args.size();\r
67   unsigned int arg_at   = 1;\r
68 \r
69   while (arg_at < vec_size) {\r
70     if ('-' == args[arg_at][0] && args[arg_at].length() > 1) {\r
71       Appoptions tmpoptions = checkOption(args[arg_at].c_str());\r
72 \r
73       //_____ HELP _____\r
74       if (isSet(tmpoptions, opt_help)) {\r
75         if (isSet(parameters_ready, opt_help)) {\r
76           errorAndQuit("-h option can be used only once.");\r
77         } else {\r
78           parameters_ready |= opt_help;\r
79         }\r
80       }\r
81 \r
82       //_____ VERBOSE _____\r
83       if (isSet(tmpoptions, opt_verbose)) {\r
84         if (isSet(parameters_ready, opt_verbose)) {\r
85           errorAndQuit("-v option can be used only once.");\r
86         } else {\r
87           parameters_ready |= opt_verbose;\r
88         }\r
89       }\r
90 \r
91       //_____ VERSION _____\r
92       if (isSet(tmpoptions, opt_version)) {\r
93         if (isSet(parameters_ready, opt_version)) {\r
94           errorAndQuit("-V option can be used only once.");\r
95         } else {\r
96           parameters_ready |= opt_version;\r
97         }\r
98       }\r
99 \r
100       //_____ OUTPUT _____\r
101       if (isSet(tmpoptions, opt_output)) {\r
102         if (isSet(parameters_ready, opt_output)) {\r
103           errorAndQuit("-o option can be used only once.");\r
104         }\r
105 \r
106         if (arg_at < vec_size - 1) {\r
107           ofilename         = args[++arg_at];\r
108           parameters_ready |= opt_output;\r
109         } else {\r
110           errorAndQuit("too few parameters.");\r
111         }\r
112       }\r
113       arg_at++;\r
114       continue;\r
115     }\r
116 \r
117     if (isSet(parameters_ready, opt_input)) {\r
118       errorAndQuit("too many input file.");\r
119     } else {\r
120       ifilename = args[arg_at];\r
121       parameters_ready |= opt_input;\r
122     }\r
123     arg_at++;\r
124   }\r
125 \r
126   //_____ VERSION _____\r
127   if (isSet(parameters_ready, opt_version)) printVersion();\r
128 \r
129   //_____ HELP ________\r
130   if (isSet(parameters_ready, opt_help))    printUsage();\r
131 \r
132   //_____ OUTPUT ______\r
133   if (isSet(parameters_ready, opt_input)) {\r
134     if (false == isSet(parameters_ready, opt_output)) {\r
135       ofilename = "none";\r
136     }\r
137 \r
138     std::ifstream ifs(ifilename.c_str(), std::ios::in);\r
139     if (!ifs) {\r
140       std::cerr << "Cannot open the input file.\n";\r
141       forceQuit();\r
142     }\r
143 \r
144     if (isSet(parameters_ready, opt_verbose)) {\r
145       std::cerr << "Input  file: " << ifilename << "\n"\r
146                 << "Output file: " << ofilename << "\n";\r
147     }\r
148 \r
149     try {\r
150       qCCode      = new QCompilerCode(ifs, setOutputFilename(ifilename, ".qdt").c_str());\r
151     } catch (const std::bad_alloc ex) {\r
152       std::cerr << "Failed in memory allocation.\n";\r
153       forceQuit();\r
154     }\r
155 \r
156     if (true == qCCode->Compile()) {\r
157       if (isSet(parameters_ready, opt_output)) {\r
158         std::ofstream ofs(ofilename.c_str(), std::ios::out);\r
159         qCCode->SaveToStream(ofs);\r
160         ofs.close();\r
161       } else {\r
162         qCCode->SaveToStream(std::cout);\r
163       }\r
164     }\r
165 \r
166     delete qCCode;\r
167 \r
168     ifs.close();\r
169 \r
170     if (isSet(parameters_ready, opt_verbose)) {\r
171       std::cerr << "qcpp: done." << std::endl;\r
172     }\r
173   }\r
174 \r
175   return 0;\r
176 }\r
177 \r
178 //----------------------------------------------------------------------------\r
179 /**\r
180  *  Check options\r
181  */\r
182 Appoptions checkOption(const char * inOptions) {\r
183   Appoptions retVal = 0;\r
184   inOptions++;\r
185   while ('\0' != *inOptions) {\r
186     switch (*inOptions) {\r
187     case 'h':\r
188       retVal |= opt_help;\r
189       break;\r
190     case 'o':\r
191       retVal |= opt_output;\r
192       break;\r
193     case 'v':\r
194       retVal |= opt_verbose;\r
195       break;\r
196     case 'V':\r
197       retVal |= opt_version;\r
198       break;\r
199     default:\r
200       errorAndQuit("there are some invalid options.");\r
201       break;\r
202     }\r
203     inOptions++;\r
204   }\r
205   return retVal;\r
206 }\r
207 \r
208 //----------------------------------------------------------------------------\r
209 /**\r
210  *  Force quit\r
211  */\r
212 void forceQuit(void) {\r
213   std::cerr << "Quit forced.\n";\r
214   std::exit(1);\r
215 }\r
216 \r
217 //----------------------------------------------------------------------------\r
218 /**\r
219  *  Print usages\r
220  */\r
221 void printUsage(void) {\r
222   std::cout << "Usage: " << app_name\r
223             << " [-hvV] [-o output_file] input_file.mcd\n\n"\r
224             << "    -h  show this help\n"\r
225             << "    -v  verbose mode\n"\r
226             << "    -V  show version\n\n"\r
227             << std::flush;\r
228 }\r
229 \r
230 //----------------------------------------------------------------------------\r
231 /**\r
232  *  Print version\r
233  */\r
234 void printVersion(void) {\r
235   std::cout << "\nCopyright (C) 2002-2003 QCAD project\n"\r
236             << app_name << " version " << app_version << "\n\n"\r
237             << std::flush;\r
238 }\r
239 \r
240 //----------------------------------------------------------------------------\r
241 /**\r
242  *  Show message and quit\r
243  */\r
244 void errorAndQuit(const char * const inMessage) {\r
245   std::cerr << "Error: " << inMessage << "\n\n";\r
246   printUsage();\r
247   forceQuit();\r
248 }\r
249 \r
250 //----------------------------------------------------------------------------\r
251 /**\r
252  *  Set output filename\r
253  */\r
254 std::string setOutputFilename(const std::string &inString,\r
255                               const char * const inExt) {\r
256   std::string retString = "";\r
257 \r
258   unsigned int posdot = inString.rfind(".", inString.length() - 1);\r
259 \r
260   if (posdot == std::string::npos) {\r
261     retString = inString;\r
262   } else {\r
263     retString.assign(inString, 0, posdot);\r
264   }\r
265 \r
266   retString += inExt;\r
267 \r
268   return retString;\r
269 }\r
270 \r