1 /*
2 * MBDyn (C) is a multibody analysis code.
3 * http://www.mbdyn.org
4 *
5 * Copyright (C) 1996-2017
6 *
7 * Pierangelo Masarati <masarati@aero.polimi.it>
8 * Paolo Mantegazza <mantegazza@aero.polimi.it>
9 *
10 * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
11 * via La Masa, 34 - 20156 Milano, Italy
12 * http://www.aero.polimi.it
13 *
14 * Changing this copyright notice is forbidden.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation (version 2 of the License).
19 *
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 */
30
31 /*
32 AUTHOR: Reinhard Resch <r.resch@secop.com>
33 Copyright (C) 2011(-2017) all rights reserved.
34
35 The copyright of this code is transferred
36 to Pierangelo Masarati and Paolo Mantegazza
37 for use in the software MBDyn as described
38 in the GNU Public License version 2.1
39 */
40
41 #include <mbconfig.h>
42
43 #ifdef USE_OCTAVE
44
45 #include <octave/oct.h>
46 #include <octave/parse.h>
47 #include <octave/dynamic-ld.h>
48 #include <octave/oct-map.h>
49 #include <octave/oct-stream.h>
50 #include <octave/ov-base-scalar.h>
51
52 #include <iostream>
53
54 using namespace std;
55
56 #include "octave_object.h"
57
58 namespace oct {
59
lookup_method(const std::string & method_name) const60 octave_object::method_function* octave_object::class_object::lookup_method(const std::string& method_name)const
61 {
62 typedef method_table_t::const_iterator iter_t;
63
64 iter_t p = method_table.find(method_name);
65
66 if ( p != method_table.end() )
67 return p->second;
68
69 if ( parent_object != NULL )
70 {
71 return parent_object->lookup_method(method_name);
72 }
73 else
74 {
75 cerr << "octave_object::class_object::lookup_method(\"" << method_name << "\") failed!" << endl;
76 const class_object* class_obj = this;
77
78 cerr << "dump of octave_object::class_object::method_table:" << endl;
79
80 while ( class_obj != NULL )
81 {
82 for ( iter_t p = class_obj->method_table.begin(); p != class_obj->method_table.end(); ++p )
83 cerr << " " << p->first << "->" << p->second << endl;
84 class_obj = class_obj->parent_object;
85 }
86 }
87
88 return NULL;
89 }
90
91 octave_object::class_object octave_object::dispatch_class_object(NULL,NULL);
92
octave_object()93 octave_object::octave_object()
94 {
95
96 }
97
~octave_object()98 octave_object::~octave_object()
99 {
100
101 }
102
any_arg_is_magic_colon(const octave_value_list & args)103 static bool any_arg_is_magic_colon (const octave_value_list& args)
104 {
105 int nargin = args.length ();
106
107 for (int i = 0; i < nargin; i++)
108 if (args(i).is_magic_colon ())
109 return true;
110
111 return false;
112 }
113
114 #if TRACE_SUBSREF == 1
115
print_args(const octave_value_list & args)116 static void print_args(const octave_value_list& args)
117 {
118 int nargin = args.length ();
119
120 for (int i = 0; i < nargin; i++)
121 {
122 args(i).print(octave_stdout);
123
124 if( i < nargin - 1 )
125 octave_stdout << ',';
126 }
127 }
128
129 #endif
130
lookup_method(const std::string & method_name)131 octave_object::method_function* octave_object::lookup_method(const std::string& method_name)
132 {
133 return get_class_object()->lookup_method(method_name);
134 }
135
subsref(const std::string & type,const std::list<octave_value_list> & idx,int nargout)136 octave_value_list octave_object::subsref (const std::string& type,
137 const std::list<octave_value_list>& idx,
138 int nargout)
139 {
140 #if TRACE_SUBSREF == 1
141 {
142 octave_stdout << endl;
143 octave_stdout << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__ << endl;
144 octave_stdout << "type=" << type << endl;
145
146 typedef std::list<octave_value_list>::const_iterator iter_t;
147
148 int i = 0;
149
150 for ( iter_t it = idx.begin(); it != idx.end(); ++it, ++i )
151 {
152 octave_stdout << "idx(" << i << ")=";
153 print_args(*it);
154 octave_stdout << endl;
155 }
156 }
157 #endif
158
159 octave_value_list retval;
160 size_t skip = 1;
161
162 if ( type.length() < 1 )
163 {
164 panic_impossible();
165 }
166
167 const char operator_char = type[0];
168
169 switch( operator_char )
170 {
171 case '.':
172 {
173 octave_value_list method_name_list = idx.front();
174
175 if ( method_name_list.length () != 1 || !method_name_list(0).is_string() )
176 panic_impossible();
177
178 const std::string method_name = method_name_list(0).string_value();
179
180 method_function *method_pfn = lookup_method(method_name);
181
182 if ( method_pfn == NULL )
183 {
184 error("octave_object: class \"%s\" has no member \"%s\"", class_name().c_str(), method_name.c_str());
185 return retval;
186 }
187
188 if ( idx.size() < 2 || type[1] != '(')
189 {
190 retval = (*method_pfn)(this,octave_value_list(),nargout);
191 }
192 else
193 {
194 skip = 2;
195 std::list<octave_value_list>::const_iterator pidx = idx.begin();
196 pidx++;
197
198 if (any_arg_is_magic_colon (*pidx))
199 {
200 error("octave object: invalid use of colon in method argument list");
201 return retval;
202 }
203 else
204 {
205 retval = (*method_pfn)(this,*pidx,nargout);
206 }
207 }
208 }
209 break;
210 case '(':
211 {
212 if (idx.size() < 1)
213 {
214 error("octave object: invalid number of indices");
215 return retval;
216 }
217
218 retval = (*this)(idx.front());
219 }
220 break;
221 case '{':
222 {
223 std::string nm = type_name();
224 error("%s cannot be indexed with %c", nm.c_str(), operator_char);
225 return retval;
226
227 }
228 break;
229
230 default:
231 panic_impossible();
232 }
233
234 if ( !error_state && idx.size() > skip )
235 {
236 retval = retval(0).next_subsref(type, idx, skip);
237 }
238
239 return retval;
240 }
241
operator ()(const octave_value_list & idx) const242 octave_value octave_object::operator()(const octave_value_list& idx) const
243 {
244 std::string nm = type_name();
245 error("%s cannot be indexed with %c", nm.c_str(), '(');
246 return octave_value();
247 }
248
subsref(const std::string & type,const std::list<octave_value_list> & idx)249 octave_value octave_object::subsref(const std::string& type,
250 const std::list<octave_value_list>& idx)
251 {
252 octave_value_list ret_val = subsref(type,idx,1);
253
254 if ( ret_val.length() < 1 )
255 return octave_value();
256
257 return ret_val(0);
258 }
259
error(const char * fmt,...)260 void error(const char* fmt, ...)
261 {
262 va_list va;
263 va_start(va, fmt);
264 ::verror(fmt, va);
265 va_end(va);
266 }
267
268 } // namespace
269
270 #endif // USE_OCTAVE
271