1 /*$Id: mg_.h,v 26.81 2008/05/27 05:33:43 al Exp $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
4 *
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 */
22 //testing=script 2006.10.31
23 #include <stdexcept>
24 #include "md.h"
25 #include "ap.h"
26 /*--------------------------------------------------------------------------*/
27 // defined here
28 class Base;
29 class C_Comment;
30 class Cxx_Comment;
31 class Parameter;
32 class Code_Block;
33 class Parameter_Block;
34 class String_Arg;
35 class Model;
36 class Head;
37 class File;
38 /*--------------------------------------------------------------------------*/
39 // external
40 class CS;
41 /*--------------------------------------------------------------------------*/
42 #ifdef PASS_TRACE_TAGS
43 #define make_tag() (out << "//" << __func__ << ":" << __LINE__ << "\n")
44 #else
45 #define make_tag()
46 #endif
47 /*--------------------------------------------------------------------------*/
to_lower(std::string s)48 inline std::string to_lower(std::string s)
49 {
50 for (std::string::iterator i = s.begin(); i != s.end(); ++i) {
51 *i = static_cast<char>(tolower(*i));
52 }
53 return s;
54 }
55 /*--------------------------------------------------------------------------*/
to_upper(std::string s)56 inline std::string to_upper(std::string s)
57 {
58 for (std::string::iterator i = s.begin(); i != s.end(); ++i) {
59 *i = static_cast<char>(toupper(*i));
60 }
61 return s;
62 }
63 /*--------------------------------------------------------------------------*/
error(const std::string & message)64 inline void error(const std::string& message)
65 {untested();
66 std::cerr << message << '\n';
67 exit(1);
68 }
69 /*--------------------------------------------------------------------------*/
os_error(const std::string & name)70 inline void os_error(const std::string& name)
71 {untested();
72 error(name + ':' + strerror(errno));
73 }
74 /*--------------------------------------------------------------------------*/
75 class Base
76 {
77 public:
78 virtual void parse(CS&) = 0;
print(std::ostream & f)79 virtual void print(std::ostream& f)const {unreachable(); f << "Base::print";}
~Base()80 virtual ~Base() {}
81 };
82 inline CS& operator>>(CS& f, Base& b)
83 {untested();b.parse(f); return f;}
84 inline std::ostream& operator<<(std::ostream& f, const Base& d)
85 {d.print(f); return f;}
86 /*--------------------------------------------------------------------------*/
87 template <class T>
88 class List_Base
89 :public Base
90 {
91 protected:
92 typedef typename std::list<T*> _Std_List_T;
93 _Std_List_T _list;
~List_Base()94 virtual ~List_Base() {
95 for (typename std::list<T*>::iterator
96 i = _list.begin();
97 i != _list.end();
98 ++i) {
99 delete *i;
100 }
101 }
102 public:
103 virtual void parse(CS& f) = 0;
104 typedef typename std::list<T*>::const_iterator const_iterator;
begin()105 const_iterator begin()const {return _list.begin();}
end()106 const_iterator end()const {return _list.end();}
is_empty()107 bool is_empty()const {return _list.empty();}
size()108 size_t size()const {return _list.size();}
109 };
110 /*--------------------------------------------------------------------------*/
111 class C_Comment
112 :public Base
113 {
114 public:
115 void parse(CS& f);
116 };
117 /*--------------------------------------------------------------------------*/
118 class Cxx_Comment
119 :public Base
120 {
121 public:
122 void parse(CS& f);
123 };
124 /*--------------------------------------------------------------------------*/
125 /* A "Collection" differs from a "List" in how it is parsed.
126 * Each parse of a "Collection" created one more object and stores
127 * it in the Collection. The size of the Collection therefore grows by 1.
128 * A "Collection" is often parsed many times.
129 * Each parse of a "List" creates a bunch of objects, and storing them.
130 * A list has opening and closing delimeters, usually {}.
131 * A "List" is usually parsed once.
132 */
133 template <class T, char BEGIN, char END>
134 class List
135 :public List_Base<T>
136 {
137 using List_Base<T>::_list;
138 public:
139 //BUG// why not inherited?
140 typedef typename std::list<T*>::const_iterator const_iterator;
begin()141 const_iterator begin()const {return _list.begin();}
end()142 const_iterator end()const {return _list.end();}
143
parse(CS & file)144 void parse(CS& file) {
145 int paren = !BEGIN || file.skip1b(BEGIN);
146 unsigned here = file.cursor();
147 for (;;) {
148 C_Comment c_comment;
149 Cxx_Comment cxx_comment;
150 (file >> "/*") && (file >> c_comment);
151 (file >> "//") && (file >> cxx_comment);
152 if (file.stuck(&here)) {
153 paren -= file.skip1b(END);
154 if (paren == 0) {
155 //file.warn(0, "list exit");
156 break;
157 }else{
158 //file.warn(0, "list");
159 }
160 T* p = new T(file);
161 if (!file.stuck(&here)) {
162 _list.push_back(p);
163 }else{itested();
164 delete p;
165 file.warn(0, "not valid here");
166 break;
167 }
168 }else{
169 }
170 }
171 }
print(std::ostream & f)172 void print(std::ostream& f)const {
173 f << BEGIN;
174 for (const_iterator i = begin(); i != end(); ++i) {
175 f << (**i);
176 }
177 f << END;
178 }
179 };
180 /*--------------------------------------------------------------------------*/
181 /* A "Collection" differs from a "List" in how it is parsed.
182 * Each parse of a "Collection" created one more object and stores
183 * it in the Collection. The size of the Collection therefore grows by 1.
184 * A "Collection" is often parsed many times.
185 * Each parse of a "List" creates a bunch of objects, and storing them.
186 * A list has opening and closing delimeters, usually {}.
187 * A "List" is usually parsed once.
188 */
189 template <class T>
190 class Collection
191 :public List_Base<T>
192 {
193 using List_Base<T>::_list;
194 public:
195 //BUG// why not inherited?
196 typedef typename std::list<T*>::const_iterator const_iterator;
begin()197 const_iterator begin()const {return _list.begin();}
end()198 const_iterator end()const {return _list.end();}
199
parse(CS & file)200 void parse(CS& file) {
201 unsigned here = file.cursor();
202 T* m = new T(file);
203 if (!file.stuck(&here)) {
204 _list.push_back(m);
205 }else{untested();
206 delete m;
207 file.warn(0, "what's this??");
208 }
209 }
print(std::ostream & f)210 void print(std::ostream& f)const {
211 for (const_iterator i = begin(); i != end(); ++i) {
212 f << (**i);
213 }
214 }
215 };
216 /*--------------------------------------------------------------------------*/
217 class Key
218 :public Base
219 {
220 std::string _name;
221 std::string _var;
222 std::string _value;
223 public:
parse(CS & f)224 void parse(CS& f) {f >> _name >> _var >> '=' >> _value >> ';';}
print(std::ostream & f)225 void print(std::ostream& f)const
226 {f << name() << " " << var() << "=" << value() << "; ";}
Key(CS & f)227 Key(CS& f) {parse(f);}
name()228 const std::string& name()const {return _name;}
var()229 const std::string& var()const {return _var;}
value()230 const std::string& value()const {return _value;}
231 };
232 typedef List<Key, '{', '}'> Key_List;
233 /*--------------------------------------------------------------------------*/
234 class String_Arg
235 :public Base
236 {
237 std::string _s;
238 public:
parse(CS & f)239 void parse(CS& f) {f >> _s >> ';';}
print(std::ostream & f)240 void print(std::ostream& f)const {f << _s;}
241 void operator=(const std::string& s) {untested();_s = s;}
242 void operator+=(const std::string& s) {_s += s;}
243 bool operator!=(const std::string& s)const {return _s != s;}
is_empty()244 bool is_empty()const {return _s.empty();}
lower()245 std::string lower()const {return to_lower(_s);}
to_string()246 const std::string& to_string()const {return _s;}
247 };
248 /*--------------------------------------------------------------------------*/
249 class Bool_Arg
250 :public Base
251 {
252 bool _s;
253 public:
parse(CS & f)254 void parse(CS& f) {_s = true; f.skip1b(";");}
print(std::ostream & f)255 void print(std::ostream& f)const {untested();f << _s;}
Bool_Arg()256 Bool_Arg() :_s(false) {}
257 operator bool()const {return _s;}
258 };
259 /*--------------------------------------------------------------------------*/
260 class Parameter
261 :public Base
262 {
263 std::string _type;
264 std::string _code_name;
265 std::string _user_name;
266 std::string _alt_name;
267 std::string _default_val;
268 std::string _comment;
269 std::string _print_test;
270 std::string _calc_print_test;
271 std::string _scale;
272 std::string _offset;
273 std::string _calculate;
274 std::string _quiet_min;
275 std::string _quiet_max;
276 std::string _final_default;
277 bool _positive;
278 bool _octal;
279 public:
280 void parse(CS& f);
281 void print(std::ostream& f)const;
Parameter(CS & f)282 Parameter(CS& f) :_positive(false), _octal(false) {parse(f);}
type()283 const std::string& type()const {return _type;}
code_name()284 const std::string& code_name()const {return _code_name;}
user_name()285 const std::string& user_name()const {return _user_name;}
alt_name()286 const std::string& alt_name()const {return _alt_name;}
comment()287 const std::string& comment()const {return _comment;}
default_val()288 const std::string& default_val()const {return _default_val;}
print_test()289 const std::string& print_test()const {return _print_test;}
calc_print_test()290 const std::string& calc_print_test()const {return _calc_print_test;}
scale()291 const std::string& scale()const {return _scale;}
offset()292 const std::string& offset()const {return _offset;}
calculate()293 const std::string& calculate()const {return _calculate;}
quiet_min()294 const std::string& quiet_min()const {return _quiet_min;}
quiet_max()295 const std::string& quiet_max()const {return _quiet_max;}
final_default()296 const std::string& final_default()const {return _final_default;}
positive()297 bool positive()const {return _positive;}
octal()298 bool octal()const {return _octal;}
299
fill_in_default_name()300 void fill_in_default_name() {
301 if (_user_name.empty()) {
302 _user_name = to_upper(_code_name);
303 }else{
304 }
305 }
306 };
307 typedef List<Parameter, '{', '}'> Parameter_List;
308 /*--------------------------------------------------------------------------*/
309 class Code_Block
310 :public Base
311 {
312 std::string s;
313 public:
314 void parse(CS& f);
print(std::ostream & f)315 void print(std::ostream& f)const {f << s;}
Code_Block()316 Code_Block() {}
is_empty()317 bool is_empty()const {return s.length() < 2;}
318 };
319 /*--------------------------------------------------------------------------*/
320 class Parameter_Block
321 :public Base
322 {
323 String_Arg _unnamed_value;
324 Parameter_List _override;
325 Parameter_List _raw;
326 Parameter_List _calculated;
327 Code_Block _code_pre;
328 Code_Block _code_mid;
329 Code_Block _code_post;
330 public:
331 void parse(CS& f);
332 void print(std::ostream& f)const;
unnamed_value()333 const String_Arg& unnamed_value()const {return _unnamed_value;}
override()334 const Parameter_List& override()const {return _override;}
raw()335 const Parameter_List& raw()const {return _raw;}
calculated()336 const Parameter_List& calculated()const {return _calculated;}
code_pre()337 const Code_Block& code_pre()const {return _code_pre;}
code_mid()338 const Code_Block& code_mid()const {return _code_mid;}
code_post()339 const Code_Block& code_post()const {return _code_post;}
is_empty()340 bool is_empty()const {return (calculated().is_empty()
341 && code_post().is_empty()
342 && code_mid().is_empty()
343 && override().is_empty()
344 && raw().is_empty()
345 && code_pre().is_empty());}
346 void fill_in_default_values();
347 };
348 /*--------------------------------------------------------------------------*/
349 class Eval
350 :public Base
351 {
352 protected:
353 String_Arg _name;
354 Code_Block _code;
Eval()355 Eval() :_name(), _code() {}
356 public:
357 void parse(CS& f);
358 void print(std::ostream& f)const;
Eval(CS & f)359 Eval(CS& f) :_name(), _code() {parse(f);}
name()360 const String_Arg& name()const {return _name;}
code()361 const Code_Block& code()const {return _code;}
362 };
363 typedef Collection<Eval> Eval_List;
364 /*--------------------------------------------------------------------------*/
365 class Function
366 :public Eval
367 {
368 public:
369 void parse(CS& f);
370 void print(std::ostream& f)const;
Function(CS & f)371 Function(CS& f) :Eval() {parse(f);}
372 };
373 typedef Collection<Function> Function_List;
374 /*--------------------------------------------------------------------------*/
375 class Port
376 :public Base
377 {
378 std::string _name;
379 std::string _short_to;
380 std::string _short_if;
381 public:
382 void parse(CS& f);
383 void print(std::ostream& f)const;
Port()384 Port() {untested();}
Port(CS & f)385 Port(CS& f) {parse(f);}
name()386 const std::string& name()const {return _name;}
short_to()387 const std::string& short_to()const {return _short_to;}
short_if()388 const std::string& short_if()const {return _short_if;}
389 };
390 typedef List<Port, '{', '}'> Port_List;
391 /*--------------------------------------------------------------------------*/
392 class Element
393 :public Base
394 {
395 std::string _dev_type;
396 std::string _name;
397 Port_List _port_list;
398 std::string _eval;
399 std::string _value;
400 std::string _args;
401 std::string _omit;
402 std::string _reverse;
403 std::string _state;
404 public:
405 void parse(CS&);
406 void print(std::ostream& f)const;
Element()407 Element() {untested();}
Element(CS & f)408 Element(CS& f) {parse(f);}
dev_type()409 const std::string& dev_type()const {return _dev_type;}
ports()410 const Port_List& ports()const {return _port_list;}
name()411 const std::string& name()const {return _name;}
eval()412 const std::string& eval()const {return _eval;}
value()413 const std::string& value()const {return _value;}
args()414 const std::string& args()const {return _args;}
omit()415 const std::string& omit()const {return _omit;}
reverse()416 const std::string& reverse()const {return _reverse;}
state()417 const std::string& state()const {return _state;}
num_nodes()418 size_t num_nodes()const {return ports().size();}
419 };
420 typedef Collection<Element> Element_List;
421 /*--------------------------------------------------------------------------*/
422 class Arg
423 :public Base
424 {
425 std::string _arg;
426 public:
427 void parse(CS& f);
print(std::ostream & f)428 void print(std::ostream& f)const {f << " " << arg() << ";\n";}
Arg(CS & f)429 Arg(CS& f) {parse(f);}
arg()430 const std::string& arg()const {return _arg;}
431 };
432 typedef List<Arg, '{', '}'> Arg_List;
433 /*--------------------------------------------------------------------------*/
434 class Args
435 :public Base
436 {
437 String_Arg _name;
438 String_Arg _type;
439 Arg_List _arg_list;
440 public:
parse(CS & f)441 void parse(CS& f) {f >> _name >> _type >> _arg_list;}
print(std::ostream & f)442 void print(std::ostream& f)const
443 {f << " args " << name() << " " << type() << "\n"
444 << arg_list() << "\n";}
Args(CS & f)445 Args(CS& f) {parse(f);}
name()446 const String_Arg& name()const {return _name;}
type()447 const String_Arg& type()const {return _type;}
arg_list()448 const Arg_List& arg_list()const {return _arg_list;}
449 typedef Arg_List::const_iterator const_iterator;
begin()450 const_iterator begin()const {return _arg_list.begin();}
end()451 const_iterator end()const {return _arg_list.end();}
452 };
453 typedef Collection<Args> Args_List;
454 /*--------------------------------------------------------------------------*/
455 class Circuit
456 :public Base
457 {
458 Port_List _required_nodes;
459 Port_List _optional_nodes;
460 Port_List _local_nodes;
461 Element_List _element_list;
462 Args_List _args_list;
463 bool _sync;
464 public:
465 void parse(CS&);
466 void print(std::ostream& f)const;
Circuit()467 Circuit() : _sync(false) {}
sync()468 bool sync()const {return _sync;}
req_nodes()469 const Port_List& req_nodes()const {return _required_nodes;}
opt_nodes()470 const Port_List& opt_nodes()const {return _optional_nodes;}
local_nodes()471 const Port_List& local_nodes()const {return _local_nodes;}
elements()472 const Element_List& elements()const {return _element_list;}
args_list()473 const Args_List& args_list()const {return _args_list;}
min_nodes()474 size_t min_nodes()const {return req_nodes().size();}
max_nodes()475 size_t max_nodes()const {return opt_nodes().size()+min_nodes();}
net_nodes()476 size_t net_nodes()const {untested();return max_nodes();}
477 };
478 /*--------------------------------------------------------------------------*/
479 class Probe
480 :public Base
481 {
482 std::string _name;
483 std::string _expression;
484 public:
parse(CS & f)485 void parse(CS& f) {f >> _name >> '=' >> _expression >> ';';}
print(std::ostream & f)486 void print(std::ostream& f)const
487 {f << " " << name() << " = \"" << expression() << "\";\n";}
Probe()488 Probe() {untested();}
Probe(CS & f)489 Probe(CS& f) {parse(f);}
name()490 const std::string& name()const {return _name;}
expression()491 const std::string& expression()const {return _expression;}
492 };
493 typedef List<Probe, '{', '}'> Probe_List;
494 /*--------------------------------------------------------------------------*/
495 /*--------------------------------------------------------------------------*/
496 class Model
497 :public Base
498 {
499 String_Arg _name;
500 String_Arg _level;
501 String_Arg _dev_type;
502 String_Arg _inherit;
503 Key_List _public_key_list;
504 Key_List _private_key_list;
505 Parameter_Block _independent;
506 Parameter_Block _size_dependent;
507 Parameter_Block _temperature;
508 Code_Block _tr_eval;
509 Code_Block _validate;
510 Bool_Arg _hide_base;
511 public:
512 void parse(CS& f);
513 void print(std::ostream& f)const;
Model(CS & f)514 Model(CS& f) {parse(f);}
hide_base()515 bool hide_base()const {return _hide_base;}
name()516 const String_Arg& name()const {return _name;}
level()517 const String_Arg& level()const {return _level;}
dev_type()518 const String_Arg& dev_type()const {return _dev_type;}
inherit()519 const String_Arg& inherit()const {return _inherit;}
public_key_list()520 const Key_List& public_key_list()const {return _public_key_list;}
private_key_list()521 const Key_List& private_key_list()const{return _private_key_list;}
independent()522 const Parameter_Block& independent()const {return _independent;}
size_dependent()523 const Parameter_Block& size_dependent()const {return _size_dependent;}
temperature()524 const Parameter_Block& temperature()const {return _temperature;}
tr_eval()525 const Code_Block& tr_eval()const {return _tr_eval;}
validate()526 const Code_Block& validate()const {return _validate;}
527 };
528 typedef Collection<Model> Model_List;
529 /*--------------------------------------------------------------------------*/
530 class Device
531 :public Base
532 {
533 String_Arg _name;
534 String_Arg _parse_name;
535 String_Arg _id_letter;
536 String_Arg _model_type;
537 Circuit _circuit;
538 Probe_List _probes;
539 Parameter_Block _device;
540 Parameter_Block _common;
541 Code_Block _tr_eval;
542 Eval_List _eval_list;
543 Function_List _function_list;
544 public:
545 void parse(CS& f);
546 void print(std::ostream& f)const;
Device(CS & f)547 Device(CS& f) {parse(f);}
name()548 const String_Arg& name()const {return _name;}
parse_name()549 const String_Arg& parse_name()const {return _parse_name;}
id_letter()550 const String_Arg& id_letter()const {return _id_letter;}
model_type()551 const String_Arg& model_type()const {return _model_type;}
circuit()552 const Circuit& circuit()const {return _circuit;}
probes()553 const Probe_List& probes()const {return _probes;}
device()554 const Parameter_Block& device()const {return _device;}
common()555 const Parameter_Block& common()const {return _common;}
tr_eval()556 const Code_Block& tr_eval()const {return _tr_eval;}
eval_list()557 const Eval_List& eval_list()const {return _eval_list;}
function_list()558 const Function_List& function_list()const {return _function_list;}
min_nodes()559 size_t min_nodes()const {return circuit().min_nodes();}
max_nodes()560 size_t max_nodes()const {return circuit().max_nodes();}
net_nodes()561 size_t net_nodes()const {untested();return circuit().net_nodes();}
562 };
563 typedef Collection<Device> Device_List;
564 /*--------------------------------------------------------------------------*/
565 /*--------------------------------------------------------------------------*/
566 class Head
567 :public Base
568 {
569 std::string s;
570 public:
571 void parse(CS& f);
print(std::ostream & f)572 void print(std::ostream& f)const {f << s;}
Head()573 Head() {}
574 };
575 /*--------------------------------------------------------------------------*/
576 /*--------------------------------------------------------------------------*/
577 class Attribute
578 :public Base
579 {
580 String_Arg _name;
581 String_Arg _value;
582 public:
583 void parse(CS& f);
Attribute(CS & f)584 Attribute(CS& f) {untested();parse(f);}
name()585 const String_Arg& name()const {untested();return _name;}
value()586 const String_Arg& value()const {untested();return _value;}
587 };
588 typedef Collection<Attribute> Attribute_List;
589 /*--------------------------------------------------------------------------*/
590 /*--------------------------------------------------------------------------*/
591 class File
592 {
593 std::string _name;
594 CS _file;
595 Head _head;
596 Code_Block _h_headers;
597 Code_Block _cc_headers;
598 Model_List _model_list;
599 Device_List _device_list;
600 Code_Block _h_direct;
601 Code_Block _cc_direct;
602 public:
603 File(const std::string& file_name);
name()604 const std::string& name()const {return _name;}
head()605 const Head& head()const {return _head;}
h_headers()606 const Code_Block& h_headers()const {return _h_headers;}
cc_headers()607 const Code_Block& cc_headers()const {return _cc_headers;}
models()608 const Model_List& models()const {return _model_list;}
devices()609 const Device_List& devices()const {return _device_list;}
h_direct()610 const Code_Block& h_direct()const {return _h_direct;}
cc_direct()611 const Code_Block& cc_direct()const {return _cc_direct;}
612 };
613 /*--------------------------------------------------------------------------*/
614 /*--------------------------------------------------------------------------*/
615