1 /*$Id: ap_convert.cc,v 26.138 2013/04/24 03:03:11 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.07.17
23 #include "u_opt.h"
24 #include "ap.h"
25 /*--------------------------------------------------------------------------*/
26 //	char	 CS::ctoc();
27 //	void	 CS::ctostr(char* d, int l, const string& t);
28 //	string	 CS::ctos(const string& term);
29 //	int	 CS::ctoi();
30 //	unsigned CS::ctou();
31 //	int	 CS::ctoo();
32 //	int	 CS::ctox();
33 //	double	 CS::ctof();
34 /*--------------------------------------------------------------------------*/
35 /* ctoc: character input to character
36  */
ctoc()37 char CS::ctoc()
38 {
39   char c=_cmd[_cnt];
40   if(_cnt<=_length) {
41     ++_cnt;
42   }else{untested();
43   }
44   return c;
45 }
46 /*--------------------------------------------------------------------------*/
47 /* ctostr: character input to string
48  * scan (and eat) an input string (cmd) using index (cnt).
49  * result in (des)  (null terminated).
50  * max length (actual char count) is (len).
51  * (des) must be at least (len)+1 characters long.
52  * (cmd) unchanged.  (*cnt) updated to point to next argument.
53  * skips leading whitespace.  skips trailing whitespace and comma
54  * skips parts of input word too big for destination
55  */
ctostr(char * des,int len,const std::string & term)56 void CS::ctostr(char* des, int len, const std::string& term)
57 {
58   skipbl();
59   int ii;
60   for (ii = 0;  ii < len && !is_term(term);  ++ii) {
61     des[ii] = ctoc();
62   }
63   des[ii] = '\0';
64 
65   while (!is_term(term)) {untested();
66     skip();
67   }
68   skipcom();
69 }
70 /*--------------------------------------------------------------------------*/
ctos(const std::string & term,const std::string & begin_quote,const std::string & end_quote,const std::string & trap)71 std::string CS::ctos(const std::string& term,
72 		     const std::string& begin_quote,
73 		     const std::string& end_quote,
74 		     const std::string& trap)
75 {
76   assert(begin_quote.length() == end_quote.length());
77 
78   skipbl();
79   unsigned begin_string = cursor();
80   unsigned end_string = cursor();
81 
82   std::string s;
83   std::string::size_type which_quote = find1(begin_quote);
84   if (which_quote != std::string::npos) {
85     int quotes = 1;
86     skip(); // the quote
87     begin_string = cursor();
88     char the_begin_quote = begin_quote[which_quote];
89     char the_end_quote = end_quote[which_quote];
90     for (;;) {
91       if (!ns_more()) {itested();
92 	end_string = cursor();
93 	warn(bDANGER, std::string("need ") + the_end_quote);
94 	break;
95       }else if (skip1(the_end_quote)) {
96 	if (--quotes <= 0) {
97 	  end_string = cursor() - 1;
98 	  break;
99 	}else{
100 	}
101       }else if (skip1(the_begin_quote)) {
102 	++quotes;
103 	skip();
104       }else if (skip1('\\')) {
105 	end_string = cursor() - 1;
106 	s += _cmd.substr(begin_string, end_string-begin_string);
107 	begin_string = cursor();
108 	skip1(the_end_quote);
109       }else{
110 	skip();
111       }
112     }
113     s += _cmd.substr(begin_string, end_string-begin_string);
114   }else{
115     while(ns_more() && !is_term(term)) {
116       skip();
117     }
118     if (match1(trap)) {untested();
119       warn(bDANGER, "ap_convert trap-exit");
120     }else{
121     }
122     end_string = cursor();
123     s = _cmd.substr(begin_string, end_string-begin_string);
124   }
125 
126   skipcom();
127   _ok = end_string > begin_string;
128   return s;
129 }
130 /*--------------------------------------------------------------------------*/
get_to(const std::string & term)131 std::string CS::get_to(const std::string& term)
132 {
133   std::string des;
134   while(ns_more() && !match1(term)) {
135     des += ctoc();
136   }
137   return des;
138 }
139 /*--------------------------------------------------------------------------*/
140 /* ctob: character input to bool
141  * no match makes it true;
142  * Mismatch belongs to next token
143  */
ctob()144 bool CS::ctob()
145 {
146   skipbl();
147   unsigned here = cursor();
148   bool val = true;
149   ONE_OF
150     || Set(*this, "1",       &val, true)
151     || Set(*this, "0",       &val, false)
152     || Set(*this, "t{rue}",  &val, true)
153     || Set(*this, "f{alse}", &val, false)
154     || Set(*this, "y{es}",   &val, true)
155     || Set(*this, "n{o}",    &val, false)
156     || Set(*this, "#t{rue}", &val, true)
157     || Set(*this, "#f{alse}",&val, false)
158     ;
159   skipcom();
160   _ok = cursor() > here;
161   return val;
162 }
163 /*--------------------------------------------------------------------------*/
164 /* ctoi: character input to integer
165  * Returns signed integer, or 0 if the string is not a number.
166  * Input must be integer: no multipliers, no decimal point.
167  * Dot or letter belongs to the next token.
168  */
ctoi()169 int CS::ctoi()
170 {
171   int val = 0;
172   int sign = 1;
173 
174   skipbl();
175   unsigned here = cursor();
176   if (skip1("-")) {
177     sign = -1;
178   }else{
179     skip1("+");
180   }
181 
182   while (is_digit()) {
183     val = 10 * val + (ctoc()-'0');
184   }
185   skipcom();
186   _ok = cursor() > here;
187   return val * sign;
188 }
189 /*--------------------------------------------------------------------------*/
190 /* ctou: character input to unsigned integer
191  * Returns unsigned integer, or 0 if the string is not a number.
192  * Input must be integer: no multipliers, no decimal point.
193  * Dot or letter belongs to the next token.
194  */
ctou()195 unsigned CS::ctou()
196 {
197   unsigned val = 0;
198 
199   skipbl();
200   unsigned here = cursor();
201   while (is_digit()) {
202     val = 10 * val + static_cast<unsigned>(ctoc()-'0');
203   }
204   skipcom();
205   _ok = cursor() > here;
206   return val;
207 }
208 /*--------------------------------------------------------------------------*/
209 /* ctoo: character octal input to integer
210  * Returns integer, or 0 if the string is not a number.
211  * Input must be integer: no multipliers, no decimal point.
212  * Dot or letter belongs to the next token.
213  * There is no check against '8' and '9'.
214  */
ctoo()215 int CS::ctoo()
216 {
217   int val = 0;
218 
219   skipbl();
220   unsigned here = cursor();
221   while (is_digit()) {
222     val = 8 * val + (ctoc()-'0');
223   }
224   skipcom();
225   _ok = cursor() > here;
226   return val;
227 }
228 /*--------------------------------------------------------------------------*/
229 /* ctox: character hex input to unsigned integer
230  * Returns integer, or 0 if the string is not a number.
231  * Input must be hex integer: no multipliers, no decimal point.
232  * Dot or letter belongs to the next token.
233  */
ctox()234 int CS::ctox()
235 {untested();
236   int val = 0;
237 
238   skipbl();
239   unsigned here = cursor();
240   while (is_xdigit()) {untested();
241     if (is_digit()) {untested();
242       val = 16 * val + (ctoc()-'0');
243     }else{untested();
244       val = 16 * val + (tolower(ctoc())-'a'+10);
245     }
246   }
247   skipcom();
248   _ok = cursor() > here;
249   return val;
250 }
251 /*--------------------------------------------------------------------------*/
252 /* ctof: floating point input
253  * return double number if got, else 0
254  * supports letter multipliers (spice style)
255  * skips trailing letters (10uhenries == 10u)
256  * skips trailing spaces and one comma
257  * pointer points to char following comma
258  * or first non-space following number just got
259  * or first non-space (if non-number)
260  */
ctof()261 double CS::ctof()
262 {
263   double val = 0.0;
264   double power = 1.0;
265   int    sign = 1;
266 
267   skipbl();
268   if (!is_float()) {
269     skipcom();
270     _ok = false;
271     return 0.;
272   }else{
273   }
274 
275   if (skip1("-")) {			// sign
276     sign = -1;
277   }else{
278     skip1("+");
279   }
280 
281   while (is_digit()) {			// up to dec pt
282     val = 10.0 * val + (ctoc()-'0');
283   }
284   skip1(".");				// dec pt
285 
286   while (is_digit()) {			// after dec pt
287     val = 10.0 * val + (ctoc()-'0');
288     power *= .1;
289   }
290 
291   if (skip1("eE")) {			// exponent: E form
292     int expo = 0;
293     int es = 1;
294     if (skip1("-")) {
295       es = -1;
296     }else{
297       skip1("+");
298     }
299     while (is_digit())
300       expo = 10 * expo + (ctoc()-'0');
301     expo *= es;
302     power *= pow(10., expo);
303   }else if ((OPT::units == uSPICE) && skip1("mM")) {		// M is special
304     if (skip1("eE")) {			// meg
305       power *= 1e6;
306     }else if (skip1("iI")) {		// mil
307       power *= 25.4e-6;
308     }else{				// plain m (milli)
309       power *= 1e-3;
310     }
311   }else if (skip1("M")) {
312     assert(OPT::units == uSI);
313     power *= 1e6;
314   }else if (skip1("m")) {
315     assert(OPT::units == uSI);
316     power *= 1e-3;
317   }else if (skip1("uU")) {		// other letters
318     power *= 1e-6;
319   }else if (skip1("nN")) {
320     power *= 1e-9;
321   }else if (skip1("p")) {
322     power *= 1e-12;
323   }else if (skip1("P")) {
324     power *= ((OPT::units == uSI) ? (1e15) : 1e-12);
325   }else if (skip1("fF")) {
326     power *= 1e-15;
327   }else if (skip1("aA")) {
328     power *= 1e-18;
329   }else if (skip1("kK")) {
330     power *= 1e3;
331   }else if (skip1("gG")) {
332     power *= 1e9;
333   }else if (skip1("tT")) {
334     power *= 1e12;
335   }else if (skip1("%")) {untested();
336     power *= 1e-2;
337   }else{
338   }
339   while (is_alpha()) {			// skip letters
340     skip();
341   }
342   skipcom();
343   _ok = true;
344   return (sign*val*power);
345 }
346 /*--------------------------------------------------------------------------*/
347 /*--------------------------------------------------------------------------*/
348