MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
octave_object.cc
Go to the documentation of this file.
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 
60 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 
93 octave_object::octave_object()
94 {
95 
96 }
97 
98 octave_object::~octave_object()
99 {
100 
101 }
102 
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 
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 
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 
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 
242 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 
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 
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
int error(const char *test, int value)
int nargin
octave_value_list retval
if(nargin< 1)