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