PageRenderTime 70ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/SN-NG4.1/snavigator/demo/c++/glish/Value.cc

https://gitlab.com/OpenSourceMirror/sourcenav
C++ | 2024 lines | 1668 code | 309 blank | 47 comment | 299 complexity | 31fa4c309afeaf373a199cffb3d261aa MD5 | raw file
  1. // $Header$
  2. #include "system.h"
  3. #include <string.h>
  4. #include <stream.h>
  5. #include <stdlib.h>
  6. #include "Sds/sdsgen.h"
  7. #include "Glish/Value.h"
  8. #include "glish_event.h"
  9. #include "BinOpExpr.h"
  10. #include "Func.h"
  11. #include "Reporter.h"
  12. int num_Values_created = 0;
  13. int num_Values_deleted = 0;
  14. const char* type_names[NUM_GLISH_TYPES] =
  15. {
  16. "error", "ref", "const", "subref", "subconst",
  17. "boolean", "byte", "short", "integer",
  18. "float", "double", "string", "agent", "function", "record",
  19. "complex", "dcomplex", "opaque",
  20. };
  21. const Value* false_value;
  22. #define AGENT_MEMBER_NAME "*agent*"
  23. class SDS_ValueManager : public GlishObject {
  24. public:
  25. SDS_ValueManager( int sds_index ) { sds = sds_index; }
  26. ~SDS_ValueManager()
  27. {
  28. sds_destroy( sds );
  29. sds_discard( sds );
  30. }
  31. protected:
  32. int sds;
  33. };
  34. class DelObj : public GlishObject {
  35. public:
  36. DelObj( GlishObject* arg_obj ) { obj = arg_obj; ptr = 0; }
  37. DelObj( void* arg_ptr ) { obj = 0; ptr = arg_ptr; }
  38. ~DelObj();
  39. protected:
  40. GlishObject* obj;
  41. void* ptr;
  42. };
  43. DelObj::~DelObj()
  44. {
  45. Unref( obj );
  46. delete ptr;
  47. }
  48. #define DEFINE_SINGLETON_CONSTRUCTOR(constructor_type) \
  49. Value::Value( constructor_type value ) \
  50. { \
  51. InitValue(); \
  52. SetValue( &value, 1, COPY_ARRAY ); \
  53. }
  54. #define DEFINE_ARRAY_CONSTRUCTOR(constructor_type) \
  55. Value::Value( constructor_type value[], int len, array_storage_type storage )\
  56. { \
  57. InitValue(); \
  58. SetValue( value, len, storage ); \
  59. }
  60. #define DEFINE_ARRAY_REF_CONSTRUCTOR(constructor_type) \
  61. Value::Value( constructor_type& value_ref ) \
  62. { \
  63. InitValue(); \
  64. SetValue( value_ref ); \
  65. }
  66. #define DEFINE_CONSTRUCTORS(type,reftype) \
  67. DEFINE_SINGLETON_CONSTRUCTOR(type) \
  68. DEFINE_ARRAY_CONSTRUCTOR(type) \
  69. DEFINE_ARRAY_REF_CONSTRUCTOR(reftype)
  70. DEFINE_CONSTRUCTORS(glish_bool,glish_boolref)
  71. DEFINE_CONSTRUCTORS(byte,byteref)
  72. DEFINE_CONSTRUCTORS(short,shortref)
  73. DEFINE_CONSTRUCTORS(int,intref)
  74. DEFINE_CONSTRUCTORS(float,floatref)
  75. DEFINE_CONSTRUCTORS(double,doubleref)
  76. DEFINE_CONSTRUCTORS(complex,complexref)
  77. DEFINE_CONSTRUCTORS(dcomplex,dcomplexref)
  78. DEFINE_CONSTRUCTORS(charptr,charptrref)
  79. DEFINE_SINGLETON_CONSTRUCTOR(agentptr)
  80. DEFINE_SINGLETON_CONSTRUCTOR(funcptr)
  81. DEFINE_ARRAY_CONSTRUCTOR(funcptr)
  82. Value::Value( recordptr value, Agent* agent )
  83. {
  84. InitValue();
  85. SetValue( value, agent );
  86. }
  87. Value::Value( SDS_Index& value )
  88. {
  89. InitValue();
  90. SetValue( value );
  91. }
  92. Value::Value( Value* ref_value, value_type val_type )
  93. {
  94. InitValue();
  95. storage = TAKE_OVER_ARRAY;
  96. if ( val_type == VAL_CONST )
  97. type = TYPE_CONST;
  98. else if ( val_type == VAL_REF )
  99. type = TYPE_REF;
  100. else
  101. fatal->Report( "bad value_type in Value::Value" );
  102. if ( ref_value->IsConst() && val_type == VAL_REF )
  103. warn->Report(
  104. "\"ref\" reference created from \"const\" reference" );
  105. ref_value = ref_value->Deref();
  106. attributes = ref_value->CopyAttributePtr();
  107. Ref( ref_value );
  108. values = (void*) ref_value;
  109. }
  110. Value::Value( Value* ref_value, int index[], int num_elements,
  111. value_type val_type )
  112. {
  113. InitValue();
  114. SetValue( ref_value, index, num_elements, val_type );
  115. attributes = ref_value->CopyAttributePtr();
  116. }
  117. void Value::TakeValue( Value* new_value )
  118. {
  119. new_value = new_value->Deref();
  120. if ( new_value == this )
  121. {
  122. error->Report( "reference loop created" );
  123. return;
  124. }
  125. DeleteValue();
  126. int my_ref_count = ref_count;
  127. *this = *new_value;
  128. ref_count = my_ref_count;
  129. new_value->type = TYPE_ERROR;
  130. Unref( new_value );
  131. }
  132. Value::~Value()
  133. {
  134. DeleteValue();
  135. ++num_Values_deleted;
  136. }
  137. #define DEFINE_ARRAY_SET_VALUE(type, glish_type) \
  138. void Value::SetValue( type array[], int len, array_storage_type arg_storage )\
  139. { \
  140. SetType( glish_type ); \
  141. max_size = length = len; \
  142. storage = arg_storage; \
  143. values = storage == COPY_ARRAY ? copy_values( array, type ) : array;\
  144. }
  145. #define DEFINE_REF_SET_VALUE(reftype, glish_type) \
  146. void Value::SetValue( reftype& value_ref ) \
  147. { \
  148. SetType( glish_type ); \
  149. max_size = length = value_ref.Length(); \
  150. storage = COPY_ARRAY; \
  151. values = value_ref.DupVec(); \
  152. }
  153. #define DEFINE_SET_VALUE(type, reftype, glish_type) \
  154. DEFINE_ARRAY_SET_VALUE(type, glish_type) \
  155. DEFINE_REF_SET_VALUE(reftype, glish_type)
  156. DEFINE_SET_VALUE(glish_bool,glish_boolref,TYPE_BOOL)
  157. DEFINE_SET_VALUE(byte,byteref,TYPE_BYTE)
  158. DEFINE_SET_VALUE(short,shortref,TYPE_SHORT)
  159. DEFINE_SET_VALUE(int,intref,TYPE_INT)
  160. DEFINE_SET_VALUE(float,floatref,TYPE_FLOAT)
  161. DEFINE_SET_VALUE(double,doubleref,TYPE_DOUBLE)
  162. DEFINE_SET_VALUE(complex,complexref,TYPE_COMPLEX)
  163. DEFINE_SET_VALUE(dcomplex,dcomplexref,TYPE_DCOMPLEX)
  164. DEFINE_ARRAY_SET_VALUE(agentptr,TYPE_AGENT)
  165. DEFINE_ARRAY_SET_VALUE(funcptr,TYPE_FUNC)
  166. DEFINE_REF_SET_VALUE(charptrref,TYPE_STRING)
  167. void Value::SetValue( const char* array[], int len,
  168. array_storage_type arg_storage )
  169. {
  170. SetType( TYPE_STRING );
  171. max_size = length = len;
  172. storage = arg_storage;
  173. if ( storage == COPY_ARRAY )
  174. {
  175. values = (void*) new charptr[len];
  176. charptr* sptr = StringPtr();
  177. for ( int i = 0; i < len; ++i )
  178. sptr[i] = strdup( array[i] );
  179. }
  180. else
  181. values = array;
  182. }
  183. void Value::SetValue( recordptr value, Agent* agent )
  184. {
  185. SetType( TYPE_RECORD );
  186. values = (void*) value;
  187. max_size = length = 1;
  188. storage = TAKE_OVER_ARRAY;
  189. if ( agent )
  190. RecordPtr()->Insert( strdup( AGENT_MEMBER_NAME ),
  191. new Value( agent ) );
  192. }
  193. void Value::SetValue( SDS_Index& value )
  194. {
  195. SetType( TYPE_OPAQUE );
  196. values = (void*) value.Index();
  197. max_size = length = 1;
  198. storage = PRESERVE_ARRAY;
  199. }
  200. void Value::SetValue( Value* ref_value, int index[], int num_elements,
  201. value_type val_type )
  202. {
  203. if ( val_type == VAL_CONST )
  204. SetType( TYPE_SUBVEC_CONST );
  205. else if ( val_type == VAL_REF )
  206. SetType( TYPE_SUBVEC_REF );
  207. else
  208. fatal->Report( "bad value_type in Value::Value" );
  209. storage = TAKE_OVER_ARRAY;
  210. if ( ref_value->IsConst() && val_type == VAL_REF )
  211. warn->Report(
  212. "\"ref\" reference created from \"const\" reference" );
  213. ref_value = ref_value->Deref();
  214. length = num_elements;
  215. int max_index;
  216. if ( ! IndexRange( index, num_elements, max_index ) )
  217. fatal->Report( "bad index in Value::Value" );
  218. if ( max_index > ref_value->Length() )
  219. if ( ! ref_value->Grow( max_index ) )
  220. return;
  221. switch ( ref_value->Type() )
  222. {
  223. case TYPE_BOOL:
  224. case TYPE_BYTE:
  225. case TYPE_SHORT:
  226. case TYPE_INT:
  227. case TYPE_FLOAT:
  228. case TYPE_DOUBLE:
  229. case TYPE_COMPLEX:
  230. case TYPE_DCOMPLEX:
  231. case TYPE_STRING:
  232. case TYPE_SUBVEC_REF:
  233. case TYPE_SUBVEC_CONST:
  234. values = (void*) new VecRef( ref_value, index,
  235. num_elements, max_index );
  236. break;
  237. default:
  238. fatal->Report( "bad Value in Value::Value" );
  239. }
  240. }
  241. void Value::InitValue()
  242. {
  243. type = TYPE_ERROR;
  244. description = 0;
  245. value_manager = 0;
  246. attributes = 0;
  247. ++num_Values_created;
  248. }
  249. void Value::SetType( glish_type new_type )
  250. {
  251. DeleteValue();
  252. type = new_type;
  253. }
  254. void Value::DeleteValue()
  255. {
  256. switch ( type )
  257. {
  258. case TYPE_CONST:
  259. case TYPE_REF:
  260. Unref( RefPtr() );
  261. // So we don't also delete "values" ...
  262. type = TYPE_ERROR;
  263. break;
  264. case TYPE_SUBVEC_CONST:
  265. case TYPE_SUBVEC_REF:
  266. Unref( VecRefPtr() );
  267. type = TYPE_ERROR;
  268. break;
  269. case TYPE_STRING:
  270. if ( ! value_manager && storage != PRESERVE_ARRAY )
  271. {
  272. charptr* sptr = StringPtr();
  273. for ( int i = 0; i < length; ++i )
  274. delete (char*) sptr[i];
  275. }
  276. break;
  277. case TYPE_AGENT:
  278. // Here we rely on the fact that Agent is derived
  279. // GlishObject, which has a virtual destructor.
  280. Unref( (GlishObject*) AgentVal() );
  281. break;
  282. case TYPE_RECORD:
  283. {
  284. delete_record( RecordPtr() );
  285. // So we don't delete "values" again ...
  286. type = TYPE_ERROR;
  287. break;
  288. }
  289. default:
  290. break;
  291. }
  292. if ( type != TYPE_ERROR )
  293. {
  294. if ( value_manager )
  295. {
  296. Unref( value_manager );
  297. // It's important to get rid of our value_manager
  298. // pointer here; a call to DeleteValue does not
  299. // necessarily mean we're throwing away the entire
  300. // Value object. (For example, we may be called
  301. // by SetType, called in turn by Polymorph.) Thus
  302. // as we're done with this value_manager, mark it
  303. // as so.
  304. value_manager = 0;
  305. }
  306. else if ( storage != PRESERVE_ARRAY )
  307. delete values;
  308. DeleteAttributes();
  309. }
  310. }
  311. void Value::DeleteAttributes()
  312. {
  313. Unref( attributes );
  314. attributes = 0;
  315. }
  316. void Value::DeleteAttribute( const Value* index )
  317. {
  318. char* index_string = index->StringVal();
  319. DeleteAttribute( index_string );
  320. delete index_string;
  321. }
  322. void Value::DeleteAttribute( const char field[] )
  323. {
  324. attributeptr attr = ModAttributePtr();
  325. if ( attr )
  326. delete attr->Remove( field );
  327. }
  328. int Value::IsNumeric() const
  329. {
  330. switch ( type )
  331. {
  332. case TYPE_BOOL:
  333. case TYPE_BYTE:
  334. case TYPE_SHORT:
  335. case TYPE_INT:
  336. case TYPE_FLOAT:
  337. case TYPE_DOUBLE:
  338. case TYPE_COMPLEX:
  339. case TYPE_DCOMPLEX:
  340. return 1;
  341. case TYPE_CONST:
  342. case TYPE_REF:
  343. case TYPE_STRING:
  344. case TYPE_AGENT:
  345. case TYPE_FUNC:
  346. case TYPE_RECORD:
  347. case TYPE_OPAQUE:
  348. return 0;
  349. case TYPE_SUBVEC_CONST:
  350. case TYPE_SUBVEC_REF:
  351. return VecRefPtr()->Val()->IsNumeric();
  352. case TYPE_ERROR:
  353. default:
  354. fatal->Report( "bad type in Value::IsNumeric()" );
  355. return 0; // for overly clever compilers
  356. }
  357. }
  358. int Value::IsAgentRecord() const
  359. {
  360. if ( VecRefDeref()->Type() == TYPE_RECORD &&
  361. (*RecordPtr())[AGENT_MEMBER_NAME] )
  362. return 1;
  363. else
  364. return 0;
  365. }
  366. #define DEFINE_CONST_ACCESSOR(name,tag,type) \
  367. type Value::name() const \
  368. { \
  369. if ( IsVecRef() ) \
  370. return ((const Value*) VecRefPtr()->Val())->name(); \
  371. else if ( Type() != tag ) \
  372. fatal->Report( "bad use of const accessor" ); \
  373. return (type) values; \
  374. }
  375. DEFINE_CONST_ACCESSOR(BoolPtr,TYPE_BOOL,glish_bool*)
  376. DEFINE_CONST_ACCESSOR(BytePtr,TYPE_BYTE,byte*)
  377. DEFINE_CONST_ACCESSOR(ShortPtr,TYPE_SHORT,short*)
  378. DEFINE_CONST_ACCESSOR(IntPtr,TYPE_INT,int*)
  379. DEFINE_CONST_ACCESSOR(FloatPtr,TYPE_FLOAT,float*)
  380. DEFINE_CONST_ACCESSOR(DoublePtr,TYPE_DOUBLE,double*)
  381. DEFINE_CONST_ACCESSOR(ComplexPtr,TYPE_COMPLEX,complex*)
  382. DEFINE_CONST_ACCESSOR(DcomplexPtr,TYPE_DCOMPLEX,dcomplex*)
  383. DEFINE_CONST_ACCESSOR(StringPtr,TYPE_STRING,charptr*)
  384. DEFINE_CONST_ACCESSOR(FuncPtr,TYPE_FUNC,funcptr*)
  385. DEFINE_CONST_ACCESSOR(AgentPtr,TYPE_AGENT,agentptr*)
  386. DEFINE_CONST_ACCESSOR(RecordPtr,TYPE_RECORD,recordptr)
  387. #define DEFINE_ACCESSOR(name,tag,type) \
  388. type Value::name() \
  389. { \
  390. if ( IsVecRef() ) \
  391. return VecRefPtr()->Val()->name(); \
  392. if ( Type() != tag ) \
  393. Polymorph( tag ); \
  394. return (type) values; \
  395. }
  396. DEFINE_ACCESSOR(BoolPtr,TYPE_BOOL,glish_bool*)
  397. DEFINE_ACCESSOR(BytePtr,TYPE_BYTE,byte*)
  398. DEFINE_ACCESSOR(ShortPtr,TYPE_SHORT,short*)
  399. DEFINE_ACCESSOR(IntPtr,TYPE_INT,int*)
  400. DEFINE_ACCESSOR(FloatPtr,TYPE_FLOAT,float*)
  401. DEFINE_ACCESSOR(DoublePtr,TYPE_DOUBLE,double*)
  402. DEFINE_ACCESSOR(ComplexPtr,TYPE_COMPLEX,complex*)
  403. DEFINE_ACCESSOR(DcomplexPtr,TYPE_DCOMPLEX,dcomplex*)
  404. DEFINE_ACCESSOR(StringPtr,TYPE_STRING,charptr*)
  405. DEFINE_ACCESSOR(FuncPtr,TYPE_FUNC,funcptr*)
  406. DEFINE_ACCESSOR(AgentPtr,TYPE_AGENT,agentptr*)
  407. DEFINE_ACCESSOR(RecordPtr,TYPE_RECORD,recordptr)
  408. #define DEFINE_CONST_REF_ACCESSOR(name,tag,type) \
  409. type& Value::name() const \
  410. { \
  411. if ( ! IsVecRef() ) \
  412. fatal->Report( "bad use of subarray reference accessor" );\
  413. if ( VecRefPtr()->Type() != tag ) \
  414. fatal->Report( "bad use of subarray reference accessor" );\
  415. return *(VecRefPtr()->name()); \
  416. }
  417. DEFINE_CONST_REF_ACCESSOR(BoolRef,TYPE_BOOL,glish_boolref)
  418. DEFINE_CONST_REF_ACCESSOR(ByteRef,TYPE_BYTE,byteref)
  419. DEFINE_CONST_REF_ACCESSOR(ShortRef,TYPE_SHORT,shortref)
  420. DEFINE_CONST_REF_ACCESSOR(IntRef,TYPE_INT,intref)
  421. DEFINE_CONST_REF_ACCESSOR(FloatRef,TYPE_FLOAT,floatref)
  422. DEFINE_CONST_REF_ACCESSOR(DoubleRef,TYPE_DOUBLE,doubleref)
  423. DEFINE_CONST_REF_ACCESSOR(ComplexRef,TYPE_COMPLEX,complexref)
  424. DEFINE_CONST_REF_ACCESSOR(DcomplexRef,TYPE_DCOMPLEX,dcomplexref)
  425. DEFINE_CONST_REF_ACCESSOR(StringRef,TYPE_STRING,charptrref)
  426. #define DEFINE_REF_ACCESSOR(name,tag,type) \
  427. type& Value::name() \
  428. { \
  429. if ( ! IsVecRef() ) \
  430. fatal->Report( "bad use of subarray reference accessor" );\
  431. if ( VecRefPtr()->Type() != tag ) \
  432. Polymorph( tag ); \
  433. return *(VecRefPtr()->name()); \
  434. }
  435. DEFINE_REF_ACCESSOR(BoolRef,TYPE_BOOL,glish_boolref)
  436. DEFINE_REF_ACCESSOR(ByteRef,TYPE_BYTE,byteref)
  437. DEFINE_REF_ACCESSOR(ShortRef,TYPE_SHORT,shortref)
  438. DEFINE_REF_ACCESSOR(IntRef,TYPE_INT,intref)
  439. DEFINE_REF_ACCESSOR(FloatRef,TYPE_FLOAT,floatref)
  440. DEFINE_REF_ACCESSOR(DoubleRef,TYPE_DOUBLE,doubleref)
  441. DEFINE_REF_ACCESSOR(ComplexRef,TYPE_COMPLEX,complexref)
  442. DEFINE_REF_ACCESSOR(DcomplexRef,TYPE_DCOMPLEX,dcomplexref)
  443. DEFINE_REF_ACCESSOR(StringRef,TYPE_STRING,charptrref)
  444. #define XXX_VAL(name, val_type, rhs_elm, text_func, type_name, zero) \
  445. val_type Value::name( int n ) const \
  446. { \
  447. if ( IsRef() ) \
  448. return Deref()->name( n ); \
  449. \
  450. if ( length < 1 ) \
  451. { \
  452. error->Report( "empty array converted to ", type_name );\
  453. return zero; \
  454. } \
  455. \
  456. if ( n < 1 || n > length ) \
  457. { \
  458. error->Report( "in conversion to ", type_name, " index (=", n,\
  459. ") out of bounds, length =", length ); \
  460. return zero; \
  461. } \
  462. \
  463. switch ( type ) \
  464. { \
  465. case TYPE_BOOL: \
  466. return val_type( BoolPtr()[n - 1] ? 1 : 0 ); \
  467. \
  468. case TYPE_BYTE: \
  469. return val_type( BytePtr()[n - 1] ); \
  470. \
  471. case TYPE_SHORT: \
  472. return val_type( ShortPtr()[n - 1] ); \
  473. \
  474. case TYPE_INT: \
  475. return val_type( IntPtr()[n - 1] ); \
  476. \
  477. case TYPE_FLOAT: \
  478. return val_type( FloatPtr()[n - 1] ); \
  479. \
  480. case TYPE_DOUBLE: \
  481. return val_type( DoublePtr()[n - 1] ); \
  482. \
  483. case TYPE_COMPLEX: \
  484. return val_type( ComplexPtr()[n - 1] rhs_elm ); \
  485. \
  486. case TYPE_DCOMPLEX: \
  487. return val_type( DcomplexPtr()[n - 1] rhs_elm );\
  488. \
  489. case TYPE_STRING: \
  490. { \
  491. int successful; \
  492. val_type result = val_type( \
  493. text_func( StringPtr()[n - 1], successful ) );\
  494. \
  495. if ( ! successful ) \
  496. warn->Report( "string \"", this, \
  497. "\" converted to ", type_name );\
  498. return result; \
  499. } \
  500. \
  501. case TYPE_AGENT: \
  502. case TYPE_FUNC: \
  503. case TYPE_RECORD: \
  504. case TYPE_OPAQUE: \
  505. error->Report( "bad type", type_names[Type()], \
  506. "converted to ", type_name, ":", this );\
  507. return zero; \
  508. \
  509. case TYPE_SUBVEC_CONST: \
  510. case TYPE_SUBVEC_REF: \
  511. { \
  512. VecRef* ref = VecRefPtr(); \
  513. int err; \
  514. int off = ref->TranslateIndex( n-1, &err ); \
  515. if ( err ) \
  516. { \
  517. error->Report( "bad sub-vector subscript" );\
  518. return zero; \
  519. } \
  520. return ref->Val()->name( off ); \
  521. } \
  522. \
  523. default: \
  524. fatal->Report( "bad type in Value::XXX_VAL()" );\
  525. return zero; \
  526. } \
  527. }
  528. XXX_VAL(BoolVal, glish_bool, .r, text_to_integer, "bool", glish_false)
  529. XXX_VAL(ByteVal, byte, .r, text_to_integer, "byte", 0)
  530. XXX_VAL(ShortVal, short, .r, text_to_integer, "short", 0)
  531. XXX_VAL(IntVal, int, .r, text_to_integer, "integer", 0)
  532. XXX_VAL(FloatVal, float, .r, text_to_double, "float", 0.0)
  533. XXX_VAL(DoubleVal, double, .r, text_to_double, "double", 0.0)
  534. XXX_VAL(ComplexVal, complex,, text_to_dcomplex, "complex", complex(0.0, 0.0))
  535. XXX_VAL(DcomplexVal, dcomplex,, text_to_dcomplex, "dcomplex",
  536. dcomplex(0.0, 0.0))
  537. static void append_buf( char* &buf, char* &buf_ptr, unsigned int& buf_size,
  538. const char* a = 0, const char* b = 0, const char* c = 0 )
  539. {
  540. a = a ? a : "";
  541. b = b ? b : "";
  542. c = c ? c : "";
  543. int buf_remaining = &buf[buf_size] - buf_ptr;
  544. int size_of_addition = strlen( a ) + strlen( b ) + strlen( c );
  545. while ( size_of_addition >= buf_remaining - 5 /* slop */ )
  546. { // Need to grow the buffer.
  547. int buf_ptr_offset = buf_ptr - buf;
  548. buf_size *= 2;
  549. buf = (char*) realloc_memory( (void*) buf, buf_size );
  550. if ( ! buf )
  551. fatal->Report( "out of memory in append_buf()" );
  552. buf_ptr = buf + buf_ptr_offset;
  553. buf_remaining = &buf[buf_size] - buf_ptr;
  554. }
  555. *buf_ptr = '\0';
  556. strcat( buf_ptr, a );
  557. strcat( buf_ptr, b );
  558. strcat( buf_ptr, c );
  559. buf_ptr += size_of_addition;
  560. }
  561. char* Value::StringVal( char sep, int useAttributes ) const
  562. {
  563. if ( IsRef() )
  564. return Deref()->StringVal( sep, useAttributes );
  565. if ( type == TYPE_RECORD )
  566. return RecordStringVal();
  567. if ( type == TYPE_AGENT )
  568. return strdup( "<agent>" );
  569. if ( type == TYPE_FUNC )
  570. return strdup( "<function>" );
  571. if ( type == TYPE_OPAQUE )
  572. return strdup( "<opaque>" );
  573. if ( length == 0 )
  574. return strdup( "" );
  575. unsigned int buf_size;
  576. // Make a guess as to a probable good size for buf.
  577. if ( type == TYPE_STRING )
  578. {
  579. buf_size = strlen( StringPtr()[0] ) * (length + 1);
  580. if ( buf_size == 0 )
  581. buf_size = 8;
  582. }
  583. else if ( type == TYPE_COMPLEX || type == TYPE_DCOMPLEX )
  584. buf_size = length * 16 * 2 + 1;
  585. else if ( type == TYPE_FLOAT || type == TYPE_DOUBLE )
  586. buf_size = length * 16;
  587. else
  588. buf_size = length * 8;
  589. char* buf = new char[buf_size];
  590. if ( ! buf )
  591. fatal->Report( "out of memory in Value::StringVal()" );
  592. char* buf_ptr = buf;
  593. if ( type != TYPE_STRING && length > 1 )
  594. {
  595. // Insert []'s around value.
  596. *buf_ptr++ = '[';
  597. }
  598. glish_bool* bool_ptr;
  599. byte* byte_ptr;
  600. short* short_ptr;
  601. int* int_ptr;
  602. float* float_ptr;
  603. double* double_ptr;
  604. complex* complex_ptr;
  605. dcomplex* dcomplex_ptr;
  606. charptr* string_ptr;
  607. switch ( VecRefDeref()->type )
  608. {
  609. #define ASSIGN_PTR(tag,ptr_name,source) \
  610. case tag: \
  611. ptr_name = source; \
  612. break;
  613. ASSIGN_PTR(TYPE_BOOL,bool_ptr,BoolPtr())
  614. ASSIGN_PTR(TYPE_INT,int_ptr,IntPtr())
  615. ASSIGN_PTR(TYPE_BYTE,byte_ptr,BytePtr())
  616. ASSIGN_PTR(TYPE_SHORT,short_ptr,ShortPtr())
  617. ASSIGN_PTR(TYPE_FLOAT,float_ptr,FloatPtr())
  618. ASSIGN_PTR(TYPE_DOUBLE,double_ptr,DoublePtr())
  619. ASSIGN_PTR(TYPE_COMPLEX,complex_ptr,ComplexPtr())
  620. ASSIGN_PTR(TYPE_DCOMPLEX,dcomplex_ptr,DcomplexPtr())
  621. ASSIGN_PTR(TYPE_STRING,string_ptr,StringPtr())
  622. default:
  623. fatal->Report( "bad type in Value::StringVal()" );
  624. }
  625. // Macro to generate the text corresponding to a single element of a given type.
  626. #define PLACE_ELEMENT_ACTION(buffer,str_buffer,indx) \
  627. case TYPE_BOOL: \
  628. strcpy( buffer, bool_ptr[indx] ? "T" : "F" ); \
  629. break; \
  630. \
  631. case TYPE_BYTE: \
  632. sprintf( buffer, "%d", byte_ptr[indx] ); \
  633. break; \
  634. \
  635. case TYPE_SHORT: \
  636. sprintf( buffer, "%d", short_ptr[indx] ); \
  637. break; \
  638. \
  639. case TYPE_INT: \
  640. sprintf( buffer, "%d", int_ptr[indx] ); \
  641. break; \
  642. \
  643. case TYPE_FLOAT: \
  644. sprintf( buffer, "%g", float_ptr[indx] ); \
  645. break; \
  646. \
  647. case TYPE_DOUBLE: \
  648. sprintf( buffer, "%g", double_ptr[indx] ); \
  649. break; \
  650. \
  651. case TYPE_COMPLEX: \
  652. sprintf( buffer, complex_ptr[indx].i >= 0.0 ? \
  653. "%g+%gi" : "%g%gi", complex_ptr[indx].r,\
  654. complex_ptr[indx].i ); \
  655. break; \
  656. \
  657. case TYPE_DCOMPLEX: \
  658. sprintf( buffer, dcomplex_ptr[indx].i >= 0.0 ? \
  659. "%g+%gi":"%g%gi",dcomplex_ptr[indx].r, \
  660. dcomplex_ptr[indx].i); \
  661. break; \
  662. \
  663. case TYPE_STRING: \
  664. str_buffer = string_ptr[ indx ]; \
  665. break;
  666. // Generate text for an element, translating subref indices if needed.
  667. #define PLACE_ELEMENT(buffer,str_buffer,indx,alloced) \
  668. switch ( type ) \
  669. { \
  670. PLACE_ELEMENT_ACTION(buffer,str_buffer,indx) \
  671. \
  672. case TYPE_SUBVEC_REF: \
  673. case TYPE_SUBVEC_CONST: \
  674. { \
  675. VecRef* ref = VecRefPtr(); \
  676. int err; \
  677. int index = ref->TranslateIndex( indx, &err ); \
  678. if ( err ) \
  679. { \
  680. error->Report( "invalid sub-vector" ); \
  681. delete alloced; \
  682. return strdup( "error" ); \
  683. } \
  684. switch ( ref->Type() ) \
  685. { \
  686. PLACE_ELEMENT_ACTION(buffer,str_buffer,index)\
  687. \
  688. default: \
  689. fatal->Report( \
  690. "bad type in Value::StringVal()" ); \
  691. } \
  692. } \
  693. break; \
  694. \
  695. default: \
  696. fatal->Report( \
  697. "bad type in Value::StringVal()" ); \
  698. }
  699. char numeric_buf[256];
  700. const attributeptr attr = AttributePtr();
  701. const Value* shape_val;
  702. int shape_len;
  703. if ( ! useAttributes || ! attr || ! (shape_val = (*attr)["shape"]) ||
  704. ! shape_val->IsNumeric() ||
  705. (shape_len = shape_val->Length()) <= 1 )
  706. { // not an n-D array.
  707. for ( int i = 0; i < length; ++i )
  708. {
  709. const char* addition = numeric_buf;
  710. PLACE_ELEMENT(numeric_buf, addition, i, buf);
  711. append_buf( buf, buf_ptr, buf_size, addition );
  712. if ( i < length - 1 )
  713. // More to come.
  714. *buf_ptr++ = sep;
  715. }
  716. if ( type != TYPE_STRING && length > 1 )
  717. {
  718. // Insert []'s around value.
  719. *buf_ptr++ = ']';
  720. *buf_ptr = '\0';
  721. }
  722. return buf;
  723. }
  724. // Okay, from this point on it's an n-D array.
  725. static char indent[] = " ";
  726. // Later the pivots for outputting by planes can be made variable
  727. int r = 0;
  728. int c = 1;
  729. int shape_is_copy = 0;
  730. int* shape = shape_val->CoerceToIntArray( shape_is_copy, shape_len );
  731. // Store for setting up a plane in advance to get the proper
  732. // spacing for the columns. Note that these and the arrays
  733. // created just below are static, so we don't free them on exit.
  734. static int column_width_len = 64;
  735. static int* column_width = new int[column_width_len];
  736. // Arrays for iterating through the matrix.
  737. static int indices_len = 32;
  738. static int* indices = new int[indices_len];
  739. static int* factor = new int[indices_len];
  740. // Resize arrays as necessary.
  741. while ( shape[c] > column_width_len )
  742. {
  743. column_width_len *= 2;
  744. column_width = (int*) realloc_memory( (void*) column_width,
  745. column_width_len * sizeof(int) );
  746. if ( ! column_width )
  747. fatal->Report( "out of memory in Value::StringVal()" );
  748. }
  749. while ( shape_len > indices_len )
  750. {
  751. indices_len *= 2;
  752. indices = (int*) realloc_memory( (void*) indices,
  753. indices_len * sizeof(int) );
  754. factor = (int*) realloc_memory( (void*) factor,
  755. indices_len * sizeof(int) );
  756. if ( ! indices || ! factor )
  757. fatal->Report( "out of memory in Value::StringVal()" );
  758. }
  759. // Calculate the size and the offset for the columns.
  760. int size = 1;
  761. int offset = 0;
  762. for ( int i = 0; i < shape_len; ++i )
  763. {
  764. indices[i] = 0;
  765. factor[i] = size;
  766. size *= shape[i];
  767. }
  768. // Check to see if the vector length and the shape jive.
  769. if ( size > length )
  770. {
  771. warn->Report( "\"::shape\"/length mismatch" );
  772. delete buf;
  773. if ( shape_is_copy )
  774. delete shape;
  775. return StringVal( sep, 0 );
  776. }
  777. int max_free = shape_len-1;
  778. if ( shape_len > 2 )
  779. for ( max_free = shape_len-1; max_free > 0; --max_free )
  780. if ( max_free != r && max_free != c )
  781. break;
  782. while ( indices[max_free] < shape[max_free] )
  783. {
  784. // Output the plane label
  785. for ( i = 0; i < shape_len; ++i )
  786. {
  787. if ( i == r )
  788. sprintf( numeric_buf, "1:%d", shape[r] );
  789. else if ( i != c )
  790. sprintf( numeric_buf, "%d", indices[i] + 1 );
  791. else
  792. numeric_buf[0] = '\0';
  793. if ( i < shape_len - 1 )
  794. strcat( numeric_buf, "," );
  795. else
  796. strcat( numeric_buf, "]\n" );
  797. append_buf( buf, buf_ptr, buf_size, i==0 ? "[" : 0,
  798. numeric_buf );
  799. }
  800. // Calculate column widths.
  801. for ( indices[r] = 0; indices[r] < shape[r]; ++indices[r] )
  802. for ( indices[c] = 0; indices[c] < shape[c] - 1;
  803. ++indices[c] )
  804. {
  805. for ( i = 0, offset = 0; i < shape_len; ++i )
  806. offset += factor[i] * indices[i];
  807. char store[256];
  808. const char* addition = store;
  809. PLACE_ELEMENT(store,addition,offset,buf)
  810. int add_len = strlen( addition );
  811. if ( add_len > column_width[indices[c]] ||
  812. indices[r] == 0 )
  813. column_width[indices[c]] = add_len;
  814. }
  815. // Output plane.
  816. for ( indices[r] = 0; indices[r] < shape[r]; ++indices[r] )
  817. {
  818. for ( indices[c] = 0; indices[c] < shape[c];
  819. ++indices[c] )
  820. {
  821. for ( i = 0, offset = 0; i < shape_len; ++i )
  822. offset += factor[i] * indices[i];
  823. const char* addition = numeric_buf;
  824. PLACE_ELEMENT(numeric_buf,addition,offset,buf);
  825. char affix[256];
  826. if ( indices[c] < shape[c] - 1 )
  827. {
  828. int n = column_width[indices[c]] -
  829. strlen( addition ) + 1;
  830. for ( i = 0; i < n; ++i )
  831. affix[i] = ' ';
  832. affix[i] = '\0';
  833. }
  834. else if ( offset != size - 1 )
  835. {
  836. affix[0] = '\n';
  837. affix[1] = '\0';
  838. }
  839. else
  840. affix[0] = '\0';
  841. append_buf( buf, buf_ptr, buf_size,
  842. indices[c] == 0 ? indent : 0,
  843. addition, affix );
  844. }
  845. }
  846. // Increment counters.
  847. for ( i = 0; i <= max_free; ++i )
  848. {
  849. if ( i == r || i == c )
  850. continue;
  851. else if ( ++indices[i] < shape[i] )
  852. break;
  853. else if ( i != max_free )
  854. indices[i] = 0;
  855. }
  856. }
  857. if ( shape_is_copy )
  858. delete shape;
  859. append_buf( buf, buf_ptr, buf_size, "]" );
  860. return buf;
  861. }
  862. char* Value::RecordStringVal() const
  863. {
  864. if ( VecRefDeref()->Type() != TYPE_RECORD )
  865. fatal->Report( "non-record type in Value::RecordStringVal()" );
  866. recordptr rptr = RecordPtr();
  867. int len = rptr->Length();
  868. if ( len == 0 )
  869. return strdup( "[=]" );
  870. const char** key_strs = new const char*[len];
  871. char** element_strs = new char*[len];
  872. int total_len = 0;
  873. for ( int i = 0; i < len; ++i )
  874. {
  875. Value* nth_val = rptr->NthEntry( i, key_strs[i] );
  876. if ( ! nth_val )
  877. fatal->Report(
  878. "bad record in Value::RecordStringVal()" );
  879. element_strs[i] = nth_val->StringVal();
  880. total_len += strlen( element_strs[i] ) + strlen( key_strs[i] );
  881. }
  882. // We generate a result of the form [key1=val1, key2=val2, ...],
  883. // so in addition to room for the keys and values we need 3 extra
  884. // characters per element (for the '=', ',', and ' '), 2 more for
  885. // the []'s (we could steal these from the last element since it
  886. // doesn't have a ", " at the end of it, but that seems a bit
  887. // evil), and 1 more for the end-of-string.
  888. char* result = new char[total_len + 3 * len + 3];
  889. strcpy( result, "[" );
  890. for ( i = 0; i < len; ++i )
  891. {
  892. sprintf( &result[strlen( result )], "%s=%s, ",
  893. key_strs[i], element_strs[i] );
  894. delete element_strs[i];
  895. }
  896. // Now add the final ']', taking care to wipe out the trailing
  897. // ", ".
  898. strcpy( &result[strlen( result ) - 2], "]" );
  899. return result;
  900. }
  901. Agent* Value::AgentVal() const
  902. {
  903. if ( type == TYPE_AGENT )
  904. return AgentPtr()[0];
  905. if ( VecRefDeref()->Type() == TYPE_RECORD )
  906. {
  907. Value* member = (*RecordPtr())[AGENT_MEMBER_NAME];
  908. if ( member )
  909. return member->AgentVal();
  910. }
  911. error->Report( this, " is not an agent value" );
  912. return 0;
  913. }
  914. Func* Value::FuncVal() const
  915. {
  916. if ( type != TYPE_FUNC )
  917. {
  918. error->Report( this, " is not a function value" );
  919. return 0;
  920. }
  921. if ( length == 0 )
  922. {
  923. error->Report( "empty function array" );
  924. return 0;
  925. }
  926. if ( length > 1 )
  927. warn->Report( "more than one function element in", this,
  928. ", excess ignored" );
  929. return FuncPtr()[0];
  930. }
  931. int Value::SDS_IndexVal() const
  932. {
  933. if ( type != TYPE_OPAQUE )
  934. {
  935. error->Report( this, " is not an opaque value" );
  936. return SDS_NO_SUCH_SDS;
  937. }
  938. return int(values);
  939. }
  940. Value* Value::Deref()
  941. {
  942. if ( IsRef() )
  943. return RefPtr()->Deref();
  944. else
  945. return this;
  946. }
  947. const Value* Value::Deref() const
  948. {
  949. if ( IsRef() )
  950. return ((const Value*) RefPtr())->Deref();
  951. else
  952. return this;
  953. }
  954. Value* Value::VecRefDeref()
  955. {
  956. if ( IsVecRef() )
  957. return VecRefPtr()->Val()->VecRefDeref();
  958. else if ( IsRef() )
  959. return RefPtr()->VecRefDeref();
  960. else
  961. return this;
  962. }
  963. const Value* Value::VecRefDeref() const
  964. {
  965. if ( IsVecRef() )
  966. return ((const Value*) VecRefPtr()->Val())->VecRefDeref();
  967. else if ( IsRef() )
  968. return ((const Value*) RefPtr())->VecRefDeref();
  969. else
  970. return this;
  971. }
  972. #define COERCE_HDR(name, ctype, gtype, type_name, accessor) \
  973. if ( IsRef() ) \
  974. return Deref()->name( is_copy, size, result ); \
  975. \
  976. if ( ! IsNumeric() ) \
  977. fatal->Report( "non-numeric type in coercion of", this, \
  978. "to ", type_name ); \
  979. \
  980. if ( ! result && length == size && type == gtype ) \
  981. { \
  982. is_copy = 0; \
  983. return accessor(); \
  984. } \
  985. \
  986. is_copy = 1; \
  987. if ( ! result ) \
  988. result = new ctype[size]; \
  989. \
  990. int incr = (length == 1 ? 0 : 1); \
  991. int i, j;
  992. glish_bool* Value::CoerceToBoolArray( int& is_copy, int size,
  993. glish_bool* result ) const
  994. {
  995. COERCE_HDR(CoerceToBoolArray, glish_bool, TYPE_BOOL, "bool", BoolPtr)
  996. switch ( type )
  997. {
  998. #define BOOL_COERCE_BOOL_ACTION(OFFSET,XLATE) \
  999. case TYPE_BOOL: \
  1000. { \
  1001. glish_bool* bool_ptr = BoolPtr(); \
  1002. for ( i = 0, j = 0; i < size; ++i, j += incr ) \
  1003. { \
  1004. XLATE \
  1005. result[i] = bool_ptr[ OFFSET ]; \
  1006. } \
  1007. break; \
  1008. }
  1009. #define BOOL_COERCE_ACTION(tag,type,rhs_elm,accessor,OFFSET,XLATE) \
  1010. case tag: \
  1011. { \
  1012. type* ptr = accessor; \
  1013. for ( i = 0, j = 0; i < size; ++i, j += incr ) \
  1014. { \
  1015. XLATE \
  1016. result[i] = (ptr[ OFFSET ] rhs_elm ? glish_true : glish_false);\
  1017. } \
  1018. break; \
  1019. }
  1020. BOOL_COERCE_BOOL_ACTION(j,)
  1021. BOOL_COERCE_ACTION(TYPE_BYTE,byte,,BytePtr(),j,)
  1022. BOOL_COERCE_ACTION(TYPE_SHORT,short,,ShortPtr(),j,)
  1023. BOOL_COERCE_ACTION(TYPE_INT,int,,IntPtr(),j,)
  1024. BOOL_COERCE_ACTION(TYPE_FLOAT,float,,FloatPtr(),j,)
  1025. BOOL_COERCE_ACTION(TYPE_DOUBLE,double,,DoublePtr(),j,)
  1026. BOOL_COERCE_ACTION(TYPE_COMPLEX,complex,.r,ComplexPtr(),j,)
  1027. BOOL_COERCE_ACTION(TYPE_DCOMPLEX,dcomplex,.r,DcomplexPtr(),j,)
  1028. case TYPE_SUBVEC_REF:
  1029. case TYPE_SUBVEC_CONST:
  1030. {
  1031. VecRef *ref = VecRefPtr();
  1032. switch ( ref->Type() )
  1033. {
  1034. #define COERCE_ACTION_XLATE \
  1035. int err; \
  1036. int off = ref->TranslateIndex( j, &err ); \
  1037. if ( err ) \
  1038. { \
  1039. error->Report( "index (=",j, \
  1040. ") is out of range. Sub-vector reference may be invalid" );\
  1041. return 0; \
  1042. }
  1043. BOOL_COERCE_BOOL_ACTION(off,COERCE_ACTION_XLATE)
  1044. BOOL_COERCE_ACTION(TYPE_INT,int,,IntPtr(),off,COERCE_ACTION_XLATE)
  1045. BOOL_COERCE_ACTION(TYPE_FLOAT,float,,FloatPtr(),off,COERCE_ACTION_XLATE)
  1046. BOOL_COERCE_ACTION(TYPE_DOUBLE,double,,DoublePtr(),off,COERCE_ACTION_XLATE)
  1047. BOOL_COERCE_ACTION(TYPE_COMPLEX,complex,.r,ComplexPtr(),off,COERCE_ACTION_XLATE)
  1048. BOOL_COERCE_ACTION(TYPE_DCOMPLEX,dcomplex,.r,DcomplexPtr(),off,COERCE_ACTION_XLATE)
  1049. default:
  1050. error->Report(
  1051. "bad type in Value::CoerceToBoolArray()" );
  1052. return 0;
  1053. }
  1054. }
  1055. break;
  1056. default:
  1057. error->Report(
  1058. "bad type in Value::CoerceToBoolArray()" );
  1059. return 0;
  1060. }
  1061. return result;
  1062. }
  1063. #define COERCE_ACTION(tag,rhs_type,rhs_elm,lhs_type,accessor,OFFSET,XLATE)\
  1064. case tag: \
  1065. { \
  1066. rhs_type* rhs_ptr = accessor; \
  1067. for ( i = 0, j = 0; i < size; ++i, j += incr ) \
  1068. { \
  1069. XLATE \
  1070. result[i] = \
  1071. lhs_type(rhs_ptr[OFFSET] rhs_elm); \
  1072. } \
  1073. break; \
  1074. }
  1075. #define COERCE_ACTIONS(type,error_msg) \
  1076. COERCE_ACTION(TYPE_BOOL,glish_bool,,type,BoolPtr(),j,) \
  1077. COERCE_ACTION(TYPE_BYTE,byte,,type,BytePtr(),j,) \
  1078. COERCE_ACTION(TYPE_SHORT,short,,type,ShortPtr(),j,) \
  1079. COERCE_ACTION(TYPE_INT,int,,type,IntPtr(),j,) \
  1080. COERCE_ACTION(TYPE_FLOAT,float,,type,FloatPtr(),j,) \
  1081. COERCE_ACTION(TYPE_DOUBLE,double,,type,DoublePtr(),j,) \
  1082. COERCE_ACTION(TYPE_COMPLEX,complex,.r,type,ComplexPtr(),j,) \
  1083. COERCE_ACTION(TYPE_DCOMPLEX,dcomplex,.r,type,DcomplexPtr(),j,) \
  1084. \
  1085. case TYPE_SUBVEC_REF: \
  1086. case TYPE_SUBVEC_CONST: \
  1087. { \
  1088. VecRef *ref = VecRefPtr(); \
  1089. switch ( ref->Type() ) \
  1090. { \
  1091. \
  1092. COERCE_ACTION(TYPE_BOOL,glish_bool,,type,BoolPtr(),off,COERCE_ACTION_XLATE)\
  1093. COERCE_ACTION(TYPE_BYTE,byte,,type,BytePtr(),off,COERCE_ACTION_XLATE) \
  1094. COERCE_ACTION(TYPE_SHORT,short,,type,ShortPtr(),off,COERCE_ACTION_XLATE)\
  1095. COERCE_ACTION(TYPE_INT,int,,type,IntPtr(),off,COERCE_ACTION_XLATE) \
  1096. COERCE_ACTION(TYPE_FLOAT,float,,type,FloatPtr(),off,COERCE_ACTION_XLATE)\
  1097. COERCE_ACTION(TYPE_DOUBLE,double,,type,DoublePtr(),off,COERCE_ACTION_XLATE)\
  1098. COERCE_ACTION(TYPE_COMPLEX,complex,.r,type,ComplexPtr(),off,COERCE_ACTION_XLATE)\
  1099. COERCE_ACTION(TYPE_DCOMPLEX,dcomplex,.r,type,DcomplexPtr(),off,COERCE_ACTION_XLATE)\
  1100. \
  1101. default: \
  1102. error->Report( \
  1103. "bad type in Value::",error_msg);\
  1104. return 0; \
  1105. } \
  1106. } \
  1107. break;
  1108. byte* Value::CoerceToByteArray( int& is_copy, int size, byte* result ) const
  1109. {
  1110. COERCE_HDR(CoerceToByteArray, byte, TYPE_BYTE, "byte", BytePtr)
  1111. switch ( type )
  1112. {
  1113. COERCE_ACTIONS(byte,"CoerceToByteArray()")
  1114. default:
  1115. error->Report(
  1116. "bad type in Value::CoerceToByteArray()" );
  1117. return 0;
  1118. }
  1119. return result;
  1120. }
  1121. short* Value::CoerceToShortArray( int& is_copy, int size, short* result ) const
  1122. {
  1123. COERCE_HDR(CoerceToShortArray, short, TYPE_SHORT, "short", ShortPtr)
  1124. switch ( type )
  1125. {
  1126. COERCE_ACTIONS(short,"CoerceToShortArray()")
  1127. default:
  1128. error->Report(
  1129. "bad type in Value::CoerceToShortArray()" );
  1130. return 0;
  1131. }
  1132. return result;
  1133. }
  1134. int* Value::CoerceToIntArray( int& is_copy, int size, int* result ) const
  1135. {
  1136. COERCE_HDR(CoerceToIntArray, int, TYPE_INT, "integer", IntPtr)
  1137. switch ( type )
  1138. {
  1139. COERCE_ACTIONS(int,"CoerceToIntArray()")
  1140. default:
  1141. error->Report(
  1142. "bad type in Value::CoerceToIntArray()" );
  1143. return 0;
  1144. }
  1145. return result;
  1146. }
  1147. float* Value::CoerceToFloatArray( int& is_copy, int size, float* result ) const
  1148. {
  1149. COERCE_HDR(CoerceToFloatArray, float, TYPE_FLOAT, "float", FloatPtr)
  1150. switch ( type )
  1151. {
  1152. COERCE_ACTIONS(float,"CoerceToFloatArray()")
  1153. default:
  1154. error->Report(
  1155. "bad type in Value::CoerceToFloatArray()" );
  1156. return 0;
  1157. }
  1158. return result;
  1159. }
  1160. double* Value::CoerceToDoubleArray( int& is_copy, int size, double* result ) const
  1161. {
  1162. COERCE_HDR(CoerceToDoubleArray, double, TYPE_DOUBLE, "double", DoublePtr)
  1163. switch ( type )
  1164. {
  1165. COERCE_ACTIONS(double,"CoerceToDoubleArray()")
  1166. default:
  1167. error->Report(
  1168. "bad type in Value::CoerceToDoubleArray()" );
  1169. return 0;
  1170. }
  1171. return result;
  1172. }
  1173. // Coercion builtin->complex.
  1174. #define COMPLEX_BIN_COERCE_ACTION(tag,rhs_type,lhs_type,accessor,OFFSET,XLATE)\
  1175. case tag: \
  1176. { \
  1177. rhs_type* rhs_ptr = accessor; \
  1178. for ( i = 0, j = 0; i < size; ++i, j += incr ) \
  1179. { \
  1180. XLATE \
  1181. result[i].r = \
  1182. lhs_type(rhs_ptr[OFFSET]); \
  1183. result[i].i = lhs_type(0); \
  1184. } \
  1185. break; \
  1186. }
  1187. // Coercion complex->complex.
  1188. #define COMPLEX_CPX_COERCE_ACTION(tag,rhs_type,lhs_type,accessor,OFFSET,XLATE)\
  1189. case tag: \
  1190. { \
  1191. rhs_type* rhs_ptr = accessor; \
  1192. for ( i = 0, j = 0; i < size; ++i, j += incr ) \
  1193. { \
  1194. XLATE \
  1195. result[i].r = lhs_type(rhs_ptr[OFFSET].r); \
  1196. result[i].i = lhs_type(rhs_ptr[OFFSET].i); \
  1197. } \
  1198. break; \
  1199. }
  1200. #define COERCE_COMPLEX_ACTIONS(type,error_msg) \
  1201. COMPLEX_BIN_COERCE_ACTION(TYPE_BOOL,glish_bool,type,BoolPtr(),j,) \
  1202. COMPLEX_BIN_COERCE_ACTION(TYPE_BYTE,byte,type,BytePtr(),j,) \
  1203. COMPLEX_BIN_COERCE_ACTION(TYPE_SHORT,short,type,ShortPtr(),j,) \
  1204. COMPLEX_BIN_COERCE_ACTION(TYPE_INT,int,type,IntPtr(),j,) \
  1205. COMPLEX_BIN_COERCE_ACTION(TYPE_FLOAT,float,type,FloatPtr(),j,) \
  1206. COMPLEX_BIN_COERCE_ACTION(TYPE_DOUBLE,double,type,DoublePtr(),j,) \
  1207. COMPLEX_CPX_COERCE_ACTION(TYPE_COMPLEX,complex,type,ComplexPtr(),j,) \
  1208. COMPLEX_CPX_COERCE_ACTION(TYPE_DCOMPLEX,dcomplex,type,DcomplexPtr(),j,) \
  1209. \
  1210. case TYPE_SUBVEC_REF: \
  1211. case TYPE_SUBVEC_CONST: \
  1212. { \
  1213. VecRef *ref = VecRefPtr(); \
  1214. switch ( ref->Type() ) \
  1215. { \
  1216. \
  1217. COMPLEX_BIN_COERCE_ACTION(TYPE_BOOL,glish_bool,type,BoolPtr(),off,COERCE_ACTION_XLATE)\
  1218. COMPLEX_BIN_COERCE_ACTION(TYPE_BYTE,byte,type,BytePtr(),off,COERCE_ACTION_XLATE)\
  1219. COMPLEX_BIN_COERCE_ACTION(TYPE_SHORT,short,type,ShortPtr(),off,COERCE_ACTION_XLATE)\
  1220. COMPLEX_BIN_COERCE_ACTION(TYPE_INT,int,type,IntPtr(),off,COERCE_ACTION_XLATE)\
  1221. COMPLEX_BIN_COERCE_ACTION(TYPE_FLOAT,float,type,FloatPtr(),off,COERCE_ACTION_XLATE)\
  1222. COMPLEX_BIN_COERCE_ACTION(TYPE_DOUBLE,double,type,DoublePtr(),off,COERCE_ACTION_XLATE)\
  1223. COMPLEX_CPX_COERCE_ACTION(TYPE_COMPLEX,complex,type,ComplexPtr(),off,COERCE_ACTION_XLATE)\
  1224. COMPLEX_CPX_COERCE_ACTION(TYPE_DCOMPLEX,dcomplex,type,DcomplexPtr(),off,COERCE_ACTION_XLATE)\
  1225. \
  1226. default: \
  1227. error->Report( \
  1228. "bad type in Value::",error_msg );\
  1229. return 0; \
  1230. } \
  1231. } \
  1232. break;
  1233. complex* Value::CoerceToComplexArray( int& is_copy, int size,
  1234. complex* result ) const
  1235. {
  1236. COERCE_HDR(CoerceToComplexArray, complex, TYPE_COMPLEX,
  1237. "complex", ComplexPtr)
  1238. switch ( type )
  1239. {
  1240. COERCE_COMPLEX_ACTIONS(float,"CoerceToComplexArray()")
  1241. default:
  1242. error->Report(
  1243. "bad type in Value::CoerceToComplexArray()" );
  1244. return 0;
  1245. }
  1246. return result;
  1247. }
  1248. dcomplex* Value::CoerceToDcomplexArray( int& is_copy, int size,
  1249. dcomplex* result ) const
  1250. {
  1251. COERCE_HDR(CoerceToDcomplexArray, dcomplex, TYPE_DCOMPLEX,
  1252. "dcomplex", DcomplexPtr)
  1253. switch ( type )
  1254. {
  1255. COERCE_COMPLEX_ACTIONS(float,"CoerceToDcomplexArray()")
  1256. default:
  1257. error->Report(
  1258. "bad type in Value::CoerceToDcomplexArray()" );
  1259. return 0;
  1260. }
  1261. return result;
  1262. }
  1263. charptr* Value::CoerceToStringArray( int& is_copy, int size, charptr* result ) const
  1264. {
  1265. if ( IsRef() )
  1266. return Deref()->CoerceToStringArray(is_copy,size,result );
  1267. if ( VecRefDeref()->Type() != TYPE_STRING )
  1268. {
  1269. error->Report( "non-string type in coercion of", this,
  1270. "to string" );
  1271. return 0;
  1272. }
  1273. if ( ! result && Length() == size && ! IsVecRef() )
  1274. {
  1275. is_copy = 0;
  1276. return StringPtr();
  1277. }
  1278. is_copy = 1;
  1279. if ( ! result )
  1280. result = new charptr[size];
  1281. int incr = (Length() == 1 ? 0 : 1);
  1282. int i, j;
  1283. charptr* string_ptr = StringPtr();
  1284. if ( IsVecRef() )
  1285. {
  1286. VecRef* ref = VecRefPtr();
  1287. for ( i = 0, j = 0; i < size; ++i, j += incr )
  1288. {
  1289. int err;
  1290. int off = ref->TranslateIndex( j, &err );
  1291. if ( err )
  1292. {
  1293. error->Report( "index (=",j,
  1294. ") is out of range. Sub-vector reference may be invalid" );
  1295. return 0;
  1296. }
  1297. result[i] = string_ptr[off];
  1298. }
  1299. }
  1300. else
  1301. {
  1302. for ( i = 0, j = 0; i < size; ++i, j += incr )
  1303. result[i] = string_ptr[j];
  1304. }
  1305. return result;
  1306. }
  1307. funcptr* Value::CoerceToFuncArray( int& is_copy, int size, funcptr* result ) const
  1308. {
  1309. if ( type != TYPE_FUNC )
  1310. fatal->Report( "non-func type in CoerceToFuncArray()" );
  1311. if ( size != length )
  1312. fatal->Report( "size != length in CoerceToFuncArray()" );
  1313. if ( result )
  1314. fatal->Report( "prespecified result in CoerceToFuncArray()" );
  1315. is_copy = 0;
  1316. return FuncPtr();
  1317. }
  1318. Value* Value::operator []( const Value* index ) const
  1319. {
  1320. if ( index->Type() == TYPE_STRING )
  1321. return RecordRef( index );
  1322. int indices_are_copy;
  1323. int num_indices;
  1324. int* indices = GenerateIndices( index, num_indices, indices_are_copy );
  1325. if ( indices )
  1326. {
  1327. Value* result = ArrayRef( indices, num_indices );
  1328. if ( indices_are_copy )
  1329. delete indices;
  1330. return result;
  1331. }
  1332. else
  1333. return error_value();
  1334. }
  1335. Value* Value::operator []( const_value_list* args_val ) const
  1336. {
  1337. // These are a bunch of macros for cleaning up the dynamic memory used
  1338. // by this routine (and Value::SubRef) prior to exit.
  1339. #define SUBOP_CLEANUP_1 \
  1340. if ( shape_is_copy ) \
  1341. delete shape; \
  1342. delete factor;
  1343. #define SUBOP_CLEANUP_2(length) \
  1344. { \
  1345. SUBOP_CLEANUP_1 \
  1346. for ( int x = 0; x < length; ++x ) \
  1347. if ( index_is_copy[x] ) \
  1348. delete index[x]; \
  1349. \
  1350. delete index; \
  1351. delete index_is_copy; \
  1352. delete cur; \
  1353. }
  1354. #define SUBOP_ABORT(length,retval) \
  1355. SUBOP_CLEANUP_2(length) \
  1356. delete len; \
  1357. return retval;
  1358. if ( ! IsNumeric() && VecRefDeref()->Type() != TYPE_STRING )
  1359. {
  1360. error->Report( "invalid type in n-D array operation:",
  1361. this );
  1362. return error_value();
  1363. }
  1364. // Collect attributes.
  1365. int args_len = args_val->length();
  1366. const attributeptr ptr = AttributePtr();
  1367. const Value* shape_val = ptr ? (*ptr)["shape"] : 0;
  1368. if ( ! shape_val || ! shape_val->IsNumeric() )
  1369. {
  1370. warn->Report( "invalid or non-existant \"shape\" attribute" );
  1371. if ( args_len >= 1 )
  1372. return operator[]( (*args_val)[0] );
  1373. else
  1374. return copy_value( this );
  1375. }
  1376. int shape_len = shape_val->Length();
  1377. if ( shape_len != args_len )
  1378. {
  1379. error->Report( "invalid number of indexes for:", this );
  1380. return error_value();
  1381. }
  1382. int shape_is_copy;
  1383. int* shape = shape_val->CoerceToIntArray( shape_is_copy, shape_len );
  1384. Value* op_val = (*ptr)["op[]"];
  1385. int* factor = new int[shape_len];
  1386. int cur_factor = 1;
  1387. int offset = 0;
  1388. int max_len = 0;
  1389. for ( int i = 0; i < args_len; ++i )
  1390. {
  1391. const Value* arg = (*args_val)[i];
  1392. if ( arg )
  1393. {
  1394. if ( ! arg->IsNumeric() )
  1395. {
  1396. error->Report( "index #", i+1, "into", this,
  1397. "is not numeric");
  1398. SUBOP_CLEANUP_1
  1399. return error_value();
  1400. }
  1401. if ( arg->length > max_len )
  1402. max_len = arg->length;
  1403. if ( max_len == 1 )
  1404. {
  1405. int ind = arg->IntVal();
  1406. if ( ind < 1 || ind > shape[i] )
  1407. {
  1408. error->Report( "index #", i+1, "into",
  1409. this, "is out of range");
  1410. SUBOP_CLEANUP_1
  1411. return error_value();
  1412. }
  1413. offset += cur_factor * (ind - 1);
  1414. }
  1415. }
  1416. else
  1417. { // Missing subscript.
  1418. if ( shape[i] > max_len )
  1419. max_len = shape[i];
  1420. if ( max_len == 1 )
  1421. offset += cur_factor * (shape[i] - 1);
  1422. }
  1423. factor[i] = cur_factor;
  1424. cur_factor *= shape[i];
  1425. }
  1426. // Check to see if we're valid.
  1427. if ( cur_factor > Length() )
  1428. {
  1429. error->Report( "\"::shape\"/length mismatch" );
  1430. SUBOP_CLEANUP_1
  1431. return error_value();
  1432. }
  1433. if ( max_len == 1 )
  1434. {
  1435. SUBOP_CLEANUP_1
  1436. ++offset;
  1437. // Should separate ArrayRef to get a single value??
  1438. return ArrayRef( &offset, 1 );
  1439. }
  1440. int* index_is_copy = new int[shape_len];
  1441. int** index = new int*[shape_len];
  1442. int* cur = new int[shape_len];
  1443. int* len = new int[shape_len];
  1444. int vecsize = 1;
  1445. int is_element = 1;
  1446. int spoof_dimension = 0;
  1447. for ( i = 0; i < args_len; ++i )
  1448. {
  1449. const Value* arg = (*args_val)[i];
  1450. if ( arg )
  1451. {
  1452. index[i] = GenerateIndices( arg, len[i],
  1453. index_is_copy[i], 0 );
  1454. spoof_dimension = 0;
  1455. }
  1456. else
  1457. { // Spoof entire dimension.
  1458. len[i] = shape[i];
  1459. index[i] = new int[len[i]];
  1460. for ( int j = 0; j < len[i]; j++ )
  1461. index[i][j] = j+1;
  1462. index_is_copy[i] = 1;
  1463. spoof_dimension = 1;
  1464. }
  1465. if ( is_element && len[i] > 1 )
  1466. is_element = 0;
  1467. vecsize *= len[i];
  1468. cur[i] = 0;
  1469. if ( ! spoof_dimension )
  1470. {
  1471. for ( int j = 0; j < len[i]; ++j )
  1472. {
  1473. if ( index[i][j] >= 1 &&
  1474. index[i][j] <= shape[i] )
  1475. continue;
  1476. if ( len[i] > 1 )
  1477. error->Report( "index #", i+1, ",",
  1478. j+1, " into ", this,
  1479. "is out of range.");
  1480. else
  1481. error->Report( "index #", i+1, "into",
  1482. this, "is out of range.");
  1483. SUBOP_ABORT(i, error_value())
  1484. }
  1485. }
  1486. }
  1487. // Loop through filling resultant vector.
  1488. Value* result;
  1489. switch ( Type() )
  1490. {
  1491. #define SUBSCRIPT_OP_ACTION(tag,type,accessor,LEN,OFFSET,copy_func,ERROR)\
  1492. case tag: \
  1493. { \
  1494. type* vec = accessor; \
  1495. type* ret = new type[vecsize]; \
  1496. \
  1497. for ( int v = 0; v < vecsize; ++v ) \
  1498. { \
  1499. /**** Calculate offset ****/ \
  1500. for ( i = 0, offset = 0; i < shape_len; ++i ) \
  1501. offset += factor[i] * \
  1502. (index[i][cur[i]]-1); \
  1503. /**** Set Value ****/ \
  1504. ERROR \
  1505. ret[v] = copy_func( vec[OFFSET] ); \
  1506. /**** Advance counters ****/ \
  1507. for ( i = 0; i < shape_len; ++i ) \
  1508. if ( ++cur[i] < len[i] ) \
  1509. break; \
  1510. else \
  1511. cur[i] = 0; \
  1512. } \
  1513. \
  1514. result = new Value( ret, vecsize ); \
  1515. if ( ! is_element ) \
  1516. { \
  1517. for ( int x = 0, z = 0; x < shape_len; ++x ) \
  1518. if ( len[x] > 1 ) \
  1519. len[z++] = len[x]; \
  1520. \
  1521. result->AssignAttribute( "shape", \
  1522. new Value( len, z ) ); \
  1523. if ( op_val ) \
  1524. result->AssignAttribute( "op[]", op_val );\
  1525. } \
  1526. else \
  1527. delete len; \
  1528. } \
  1529. break;
  1530. SUBSCRIPT_OP_ACTION(TYPE_BOOL,glish_bool,BoolPtr(),length,offset,,)
  1531. SUBSCRIPT_OP_ACTION(TYPE_BYTE,byte,BytePtr(),length,offset,,)
  1532. SUBSCRIPT_OP_ACTION(TYPE_SHORT,short,ShortPtr(),length,offset,,)
  1533. SUBSCRIPT_OP_ACTION(TYPE_INT,int,IntPtr(),length,offset,,)
  1534. SUBSCRIPT_OP_ACTION(TYPE_FLOAT,float,FloatPtr(),length,offset,,)
  1535. SUBSCRIPT_OP_ACTION(TYPE_DOUBLE,double,DoublePtr(),length,offset,,)
  1536. SUBSCRIPT_OP_ACTION(TYPE_COMPLEX,complex,ComplexPtr(),length,offset,,)
  1537. SUBSCRIPT_OP_ACTION(TYPE_DCOMPLEX,dcomplex,DcomplexPtr(),length,offset,,)
  1538. SUBSCRIPT_OP_ACTION(TYPE_STRING,charptr,StringPtr(),length,offset,strdup,)
  1539. case TYPE_SUBVEC_REF:
  1540. case TYPE_SUBVEC_CONST:
  1541. {
  1542. VecRef* ref = VecRefPtr();
  1543. Value* theVal = ref->Val();
  1544. int theLen = theVal->Length();
  1545. switch ( theVal->Type() )
  1546. {
  1547. #define SUBSCRIPT_OP_ACTION_XLATE(EXTRA_ERROR) \
  1548. int err; \
  1549. int off = ref->TranslateIndex( offset, &err ); \
  1550. if ( err ) \
  1551. { \
  1552. EXTRA_ERROR \
  1553. delete ret; \
  1554. SUBOP_CLEANUP_2(shape_len) \
  1555. return error_value(); \
  1556. }
  1557. SUBSCRIPT_OP_ACTION(TYPE_BOOL, glish_bool, theVal->BoolPtr(),
  1558. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1559. SUBSCRIPT_OP_ACTION(TYPE_BYTE, byte, theVal->BytePtr(),
  1560. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1561. SUBSCRIPT_OP_ACTION(TYPE_SHORT, short, theVal->ShortPtr(),
  1562. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1563. SUBSCRIPT_OP_ACTION(TYPE_INT, int, theVal->IntPtr(),
  1564. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1565. SUBSCRIPT_OP_ACTION(TYPE_FLOAT, float, theVal->FloatPtr(),
  1566. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1567. SUBSCRIPT_OP_ACTION(TYPE_DOUBLE, double, theVal->DoublePtr(),
  1568. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1569. SUBSCRIPT_OP_ACTION(TYPE_COMPLEX, complex, theVal->ComplexPtr(),
  1570. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1571. SUBSCRIPT_OP_ACTION(TYPE_DCOMPLEX, dcomplex, theVal->DcomplexPtr(),
  1572. theLen, off,,SUBSCRIPT_OP_ACTION_XLATE(;))
  1573. SUBSCRIPT_OP_ACTION(TYPE_STRING, charptr, theVal->StringPtr(),
  1574. theLen, off,strdup,SUBSCRIPT_OP_ACTION_XLATE(for(int X=0;X<v;X++) delete (char *) ret[X];))
  1575. default:
  1576. fatal->Report(
  1577. "bad subref type in Value::operator[]" );
  1578. }
  1579. }
  1580. break;
  1581. default:
  1582. fatal->Report( "bad type in Value::operator[]" );
  1583. }
  1584. SUBOP_CLEANUP_2(shape_len)
  1585. return result;
  1586. }
  1587. Value* Value::Pick( const Value *index ) const
  1588. {
  1589. #define PICK_CLEANUP \
  1590. if ( shape_is_copy ) \
  1591. delete shape; \
  1592. if ( ishape_is_copy ) \
  1593. delete ishape; \
  1594. if ( indx_is_copy ) \
  1595. delete indx; \
  1596. delete factor;
  1597. #define PICK_INITIALIZE(error_return,SHORT) \
  1598. const attributeptr attr = AttributePtr(); \
  1599. const attributeptr iattr = index->AttributePtr(); \
  1600. const Value* shape_val = 0; \
  1601. const Value* ishape_val = 0; \
  1602. int shape_len = 0; \
  1603. int ishape_len = 0; \
  1604. \
  1605. if ( attr && (shape_val = (*attr)["shape"]) && \
  1606. shape_val->IsNumeric() ) \
  1607. shape_len = shape_val->Length(); \
  1608. if ( iattr && (ishape_val = (*iattr)["shape"]) && \
  1609. ishape_val->IsNumeric() ) \
  1610. ishape_len = ishape_val->Length(); \
  1611. \
  1612. /* Neither has a shape so pick from the vector. */ \
  1613. if ( ishape_len <= 1 && shape_len <= 1 ) \
  1614. { \
  1615. SHORT \
  1616. } \
  1617. \
  1618. if ( ! ishape_len ) \
  1619. { \
  1620. if ( ishape_val ) \
  1621. error->Report("error in the array \"::shape\": ",\
  1622. ishape_val ); \
  1623. else \
  1624. error->Report( "no \"::shape\" for ", index, \
  1625. " but the array has \"::shape\"" ); \
  1626. return error_return; \
  1627. } \
  1628. if ( ! shape_len ) \
  1629. { \
  1630. if ( shape_val ) \
  1631. error->Report("error in the array \"::shape\": ",\
  1632. shape_val ); \
  1633. else \
  1634. error->Report( "no \"::shape\" for ", this, \
  1635. " but the index has \"::shape\"" ); \
  1636. return error_return; \
  1637. } \
  1638. \
  1639. if ( ishape_len > 2 ) \
  1640. { \
  1641. error->Report("invalid index of dimension (=", ishape_len, \
  1642. ") greater than 2"); \
  1643. return error_return; \
  1644. } \
  1645. \
  1646. int shape_is_copy = 0; \
  1647. int ishape_is_copy = 0; \
  1648. int indx_is_copy = 0; \
  1649. int* shape = shape_val->CoerceToIntArray( shape_is_copy, shape_len );\
  1650. int* ishape = \
  1651. ishape_val->CoerceToIntArray( ishape_is_copy, ishape_len );\
  1652. int ilen = index->Length(); \
  1653. int len = Length(); \
  1654. int* factor = new int[shape_len]; \
  1655. int offset = 1; \
  1656. int* indx = index->CoerceToIntArray( indx_is_copy, ilen ); \
  1657. Value* result = 0; \
  1658. \
  1659. if ( ishape[1] != shape_len ) \
  1660. { \
  1661. PICK_CLEANUP \
  1662. error->Report( "wrong number of columns in index (=", \
  1663. ishape[1], ") expected ", shape_len ); \
  1664. return error_return; \
  1665. } \
  1666. if ( ilen < ishape[0] * ishape[1] ) \
  1667. { \
  1668. PICK_CLEANUP \
  1669. error->Report( "Index \"::shape\"/length mismatch" );\
  1670. return error_return; \
  1671. } \
  1672. for ( int i = 0; i < shape_len; ++i ) \
  1673. { \
  1674. factor[i] = offset; \
  1675. offset *= shape[i]; \
  1676. } \
  1677. \
  1678. if ( len < offset ) \
  1679. { \
  1680. PICK_CLEANUP \
  1681. error->Report("Array \"::shape\"/length mismatch"); \
  1682. return error_return; \
  1683. }
  1684. PICK_INITIALIZE(error_value(),return this->operator[]( index );)
  1685. switch ( Type() )
  1686. {
  1687. #define PICK_ACTION_CLEANUP for(int X=0;X<i;X++) delete (char *) ret[X];
  1688. #define PICK_ACTION(tag,type,accessor,OFFSET,COPY_FUNC,XLATE,CLEANUP) \
  1689. case tag: \
  1690. { \
  1691. type* ptr = accessor(); \
  1692. type* ret = new type[ishape[0]]; \
  1693. int cur = 0; \
  1694. for ( i = 0; i < ishape[0]; ++i ) \
  1695. { \
  1696. for ( int j = 0, offset = 0; j < ishape[1]; ++j )\
  1697. { \
  1698. cur = indx[i + j * ishape[0]]; \
  1699. if ( cur < 1 || cur > shape[j] ) \
  1700. { \
  1701. PICK_CLEANUP \
  1702. CLEANUP \
  1703. delete ret; \
  1704. error->Report( "index number ", j,\
  1705. " (=", cur, ") is out of range" );\
  1706. return error_value(); \
  1707. } \
  1708. offset += factor[j] * (cur-1); \
  1709. } \
  1710. XLATE \
  1711. ret[i] = COPY_FUNC( ptr[ OFFSET ] ); \
  1712. } \
  1713. result = new Value( ret, ishape[0] ); \
  1714. } \
  1715. b