src/ov-fcn-inline.cc
author Benjamin Lindner <lindnerb@users.sourceforge.net>
Wed Mar 18 15:23:14 2009 +0100 (2009-03-18)
changeset 7685 34b75a47e712
parent 7509 ad9e3e3293ba
permissions -rw-r--r--
fix leaving stray '\r' in stream when reading from CRLF data file
* * *
fix CRLF issues with text-mode reading in windows when loading ascii data
jwe@4933
     1
/*
jwe@4933
     2
jwe@7017
     3
Copyright (C) 2004, 2005, 2006, 2007 David Bateman
jwe@4933
     4
jwe@7016
     5
This file is part of Octave.
jwe@4933
     6
jwe@7016
     7
Octave is free software; you can redistribute it and/or modify it
jwe@7016
     8
under the terms of the GNU General Public License as published by the
jwe@7016
     9
Free Software Foundation; either version 3 of the License, or (at your
jwe@7016
    10
option) any later version.
jwe@7016
    11
jwe@7016
    12
Octave is distributed in the hope that it will be useful, but WITHOUT
jwe@7016
    13
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jwe@7016
    14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jwe@7016
    15
for more details.
jwe@4933
    16
jwe@4933
    17
You should have received a copy of the GNU General Public License
jwe@7016
    18
along with Octave; see the file COPYING.  If not, see
jwe@7016
    19
<http://www.gnu.org/licenses/>.
jwe@4933
    20
jwe@4933
    21
In addition to the terms of the GPL, you are permitted to link
jwe@4933
    22
this program with any Open Source program, as defined by the
jwe@4933
    23
Open Source Initiative (www.opensource.org)
jwe@4933
    24
jwe@4933
    25
*/
jwe@4933
    26
jwe@4933
    27
#ifdef HAVE_CONFIG_H
jwe@4933
    28
#include <config.h>
jwe@4933
    29
#endif
jwe@4933
    30
jwe@4988
    31
#include <istream>
jwe@4933
    32
#include <iostream>
jwe@5765
    33
#include <sstream>
jwe@5164
    34
#include <vector>
jwe@4933
    35
jwe@4933
    36
#include "defun.h"
jwe@4933
    37
#include "error.h"
jwe@4933
    38
#include "gripes.h"
jwe@4933
    39
#include "oct-map.h"
jwe@4933
    40
#include "ov-base.h"
jwe@4933
    41
#include "ov-fcn-inline.h"
jwe@4933
    42
#include "pr-output.h"
jwe@4933
    43
#include "variables.h"
jwe@4933
    44
#include "parse.h"
jwe@4933
    45
jwe@4972
    46
#include "byte-swap.h"
jwe@4972
    47
#include "ls-oct-ascii.h"
jwe@4972
    48
#include "ls-hdf5.h"
jwe@4972
    49
#include "ls-utils.h"
lindnerb@7685
    50
#include "ls-ascii-helper.h"
jwe@4972
    51
jwe@4933
    52
DEFINE_OCTAVE_ALLOCATOR (octave_fcn_inline);
jwe@4933
    53
jwe@4933
    54
DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_inline,
jwe@4933
    55
				     "inline function",
jwe@6220
    56
				     "function_handle");
jwe@4933
    57
jwe@4933
    58
octave_fcn_inline::octave_fcn_inline (const std::string& f,
jwe@4973
    59
				      const string_vector& a,
jwe@4933
    60
				      const std::string& n)
jwe@5007
    61
  : octave_fcn_handle (n), iftext (f), ifargs (a)
jwe@4933
    62
{
jwe@4973
    63
  // Form a string representing the function.
jwe@4933
    64
jwe@5765
    65
  std::ostringstream buf;
jwe@4933
    66
jwe@5007
    67
  buf << "@(";
jwe@4933
    68
jwe@4933
    69
  for (int i = 0; i < ifargs.length (); i++)
jwe@4933
    70
    {
jwe@4933
    71
      if (i > 0)
jwe@4933
    72
	buf << ", ";
jwe@4933
    73
jwe@4933
    74
      buf << ifargs(i);
jwe@4933
    75
    }
jwe@4933
    76
jwe@5765
    77
  buf << ") " << iftext;
jwe@4973
    78
jwe@5007
    79
  int parse_status;
jwe@5765
    80
  octave_value anon_fcn_handle = eval_string (buf.str (), true, parse_status);
jwe@4933
    81
jwe@5007
    82
  if (parse_status == 0)
jwe@5007
    83
    {
jwe@5007
    84
      octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
jwe@4933
    85
jwe@5007
    86
      if (fh)
jwe@5007
    87
	fcn = fh->fcn_val ();
jwe@5007
    88
    }
jwe@4933
    89
jwe@5007
    90
  if (fcn.is_undefined ())
jwe@4933
    91
    error ("inline: unable to define function");
jwe@4933
    92
}
jwe@4933
    93
dbateman@6625
    94
// This function is supplied to allow a Matlab style class structure
dbateman@6625
    95
// to be returned..
dbateman@6625
    96
Octave_map
dbateman@6625
    97
octave_fcn_inline::map_value (void) const
dbateman@6625
    98
{
dbateman@6625
    99
  Octave_map m;
dbateman@6625
   100
  string_vector args = fcn_arg_names ();
dbateman@6625
   101
  m.assign ("version", octave_value (1.0));
dbateman@6625
   102
  m.assign ("isEmpty", octave_value (0.0));
dbateman@6625
   103
  m.assign ("expr", octave_value (fcn_text ()));
dbateman@6625
   104
  m.assign ("numArgs", octave_value (args.length ()));
dbateman@6625
   105
  m.assign ("args", octave_value (args));
dbateman@6625
   106
  std::ostringstream buf;
dbateman@6625
   107
  for (int i = 0; i < args.length (); i++)
dbateman@6625
   108
    buf << args(i) << " = INLINE_INPUTS_{" << i + 1 << "}; ";
dbateman@6625
   109
  m.assign ("inputExpr", octave_value (buf.str ()));
dbateman@6625
   110
dbateman@6625
   111
  return m;
dbateman@6625
   112
}
dbateman@6625
   113
jwe@4972
   114
bool
jwe@6974
   115
octave_fcn_inline::save_ascii (std::ostream& os)
jwe@4972
   116
{
jwe@4973
   117
  os << "# nargs: " <<  ifargs.length () << "\n";
jwe@4972
   118
  for (int i = 0; i < ifargs.length (); i++)
jwe@4973
   119
    os << ifargs(i) << "\n";
jwe@4973
   120
  if (nm.length () < 1)
jwe@4973
   121
    // Write an invalid value to flag empty fcn handle name.
jwe@4972
   122
    os << "0\n";
jwe@4972
   123
  else
jwe@4972
   124
    os << nm << "\n";
jwe@4972
   125
  os << iftext << "\n";
jwe@4972
   126
  return true;
jwe@4972
   127
}
jwe@4972
   128
jwe@4972
   129
bool
jwe@4972
   130
octave_fcn_inline::load_ascii (std::istream& is)
jwe@4972
   131
{
jwe@4972
   132
  int nargs;
jwe@4972
   133
  if (extract_keyword (is, "nargs", nargs, true))
jwe@4972
   134
    {
jwe@4972
   135
      ifargs.resize (nargs);
jwe@4972
   136
      for (int i = 0; i < nargs; i++)
jwe@4973
   137
	is >> ifargs(i);
jwe@4972
   138
      is >> nm;
jwe@4972
   139
      if (nm == "0")
jwe@4972
   140
	nm = "";
jwe@4988
   141
jwe@4988
   142
      char c;
lindnerb@7685
   143
      std::string buf;
jwe@4988
   144
jwe@4988
   145
      // Skip preceeding newline(s)
lindnerb@7685
   146
      skip_preceeding_newline (is);
jwe@4988
   147
jwe@4988
   148
      if (is)
jwe@4988
   149
	{
jwe@4988
   150
jwe@4988
   151
	  // Get a line of text whitespace characters included, leaving
jwe@4988
   152
	  // newline in the stream
lindnerb@7685
   153
	  buf = read_until_newline (is, true);
jwe@4988
   154
	}
jwe@4988
   155
lindnerb@7685
   156
      iftext = buf;
jwe@4972
   157
jwe@4972
   158
      octave_fcn_inline tmp (iftext, ifargs, nm);
jwe@4972
   159
      fcn = tmp.fcn;
jwe@4972
   160
jwe@4972
   161
      return true;
jwe@4972
   162
    }
jwe@4972
   163
  else
jwe@4972
   164
    return false;
jwe@4972
   165
}
jwe@4972
   166
jwe@4973
   167
bool
jwe@4972
   168
octave_fcn_inline::save_binary (std::ostream& os, bool&)
jwe@4972
   169
{
jwe@5828
   170
  int32_t tmp = ifargs.length ();
jwe@5760
   171
  os.write (reinterpret_cast<char *> (&tmp), 4);
jwe@4973
   172
  for (int i = 0; i < ifargs.length (); i++)
jwe@4972
   173
    {
jwe@4973
   174
      tmp = ifargs(i).length ();
jwe@5760
   175
      os.write (reinterpret_cast<char *> (&tmp), 4);
jwe@4973
   176
      os.write (ifargs(i).c_str (), ifargs(i).length ());
jwe@4972
   177
    }
jwe@4973
   178
  tmp = nm.length ();
jwe@5760
   179
  os.write (reinterpret_cast<char *> (&tmp), 4);
jwe@4973
   180
  os.write (nm.c_str (), nm.length ());
jwe@4973
   181
  tmp = iftext.length ();
jwe@5760
   182
  os.write (reinterpret_cast<char *> (&tmp), 4);
jwe@4973
   183
  os.write (iftext.c_str (), iftext.length ());
jwe@4972
   184
  return true;
jwe@4972
   185
}
jwe@4972
   186
jwe@4973
   187
bool
jwe@4972
   188
octave_fcn_inline::load_binary (std::istream& is, bool swap,
jwe@4972
   189
				oct_mach_info::float_format)
jwe@4972
   190
{
jwe@5828
   191
  int32_t nargs;
jwe@5760
   192
  if (! is.read (reinterpret_cast<char *> (&nargs), 4))
jwe@4972
   193
    return false;
jwe@4972
   194
  if (swap)
jwe@4972
   195
    swap_bytes<4> (&nargs);
jwe@4972
   196
jwe@4972
   197
  if (nargs < 1)
jwe@4972
   198
    return false;
jwe@4972
   199
  else
jwe@4972
   200
    {
jwe@5828
   201
      int32_t tmp;
jwe@4973
   202
      ifargs.resize (nargs);
jwe@4972
   203
      for (int i = 0; i < nargs; i++)
jwe@4972
   204
	{
jwe@5760
   205
	  if (! is.read (reinterpret_cast<char *> (&tmp), 4))
jwe@4972
   206
	    return false;
jwe@4972
   207
	  if (swap)
jwe@4972
   208
	    swap_bytes<4> (&tmp);
jwe@4972
   209
jwe@4972
   210
	  OCTAVE_LOCAL_BUFFER (char, ctmp, tmp+1);
jwe@4972
   211
	  is.read (ctmp, tmp);
jwe@4972
   212
	  ifargs(i) = std::string (ctmp);
jwe@4972
   213
jwe@4972
   214
	  if (! is)
jwe@4972
   215
	    return false;
jwe@4973
   216
	}
jwe@4972
   217
jwe@5760
   218
      if (! is.read (reinterpret_cast<char *> (&tmp), 4))
jwe@4972
   219
	return false;
jwe@4972
   220
      if (swap)
jwe@4972
   221
	swap_bytes<4> (&tmp);
jwe@4972
   222
jwe@4972
   223
      OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1);
jwe@4972
   224
      is.read (ctmp1, tmp);
jwe@4972
   225
      nm = std::string (ctmp1);
jwe@4972
   226
jwe@4972
   227
      if (! is)
jwe@4972
   228
	return false;
jwe@4972
   229
jwe@5760
   230
      if (! is.read (reinterpret_cast<char *> (&tmp), 4))
jwe@4972
   231
	return false;
jwe@4972
   232
      if (swap)
jwe@4972
   233
	swap_bytes<4> (&tmp);
jwe@4972
   234
jwe@4972
   235
      OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
jwe@4972
   236
      is.read (ctmp2, tmp);
jwe@4972
   237
      iftext = std::string (ctmp2);
jwe@4972
   238
jwe@4972
   239
      if (! is)
jwe@4972
   240
	return false;
jwe@4972
   241
jwe@4972
   242
      octave_fcn_inline ftmp (iftext, ifargs, nm);
jwe@4972
   243
      fcn = ftmp.fcn;
jwe@4972
   244
    }
jwe@4972
   245
  return true;
jwe@4972
   246
}
jwe@4972
   247
jwe@4972
   248
#if defined (HAVE_HDF5)
jwe@4972
   249
bool
jwe@4972
   250
octave_fcn_inline::save_hdf5 (hid_t loc_id, const char *name,
jwe@4972
   251
			      bool /* save_as_floats */)
jwe@4972
   252
{
jwe@4972
   253
  hid_t group_hid = -1;
jwe@4972
   254
  group_hid = H5Gcreate (loc_id, name, 0);
jwe@4972
   255
  if (group_hid < 0 ) return false;
jwe@4972
   256
jwe@4972
   257
  size_t len = 0;
jwe@4973
   258
  for (int i = 0; i < ifargs.length (); i++)
jwe@4973
   259
    if (len < ifargs(i).length ())
jwe@4973
   260
      len = ifargs(i).length ();
jwe@4972
   261
jwe@4972
   262
  hid_t space_hid = -1, data_hid = -1, type_hid = -1;;
jwe@4972
   263
  bool retval = true;
jwe@4972
   264
jwe@5775
   265
  // FIXME Is there a better way of saving string vectors, than a
jwe@4972
   266
  // null padded matrix?
jwe@4972
   267
jwe@4972
   268
  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2);
jwe@4972
   269
jwe@4972
   270
  // Octave uses column-major, while HDF5 uses row-major ordering
jwe@4973
   271
  hdims[1] = ifargs.length ();
jwe@4972
   272
  hdims[0] = len + 1;
jwe@4972
   273
jwe@4972
   274
  space_hid = H5Screate_simple (2, hdims, 0);
jwe@4972
   275
  if (space_hid < 0)
jwe@4972
   276
    {
jwe@4972
   277
      H5Gclose (group_hid);
jwe@4972
   278
      return false;
jwe@4972
   279
    }
jwe@4972
   280
jwe@4973
   281
  data_hid = H5Dcreate (group_hid, "args", H5T_NATIVE_CHAR, space_hid,
jwe@4972
   282
			H5P_DEFAULT);
jwe@4972
   283
  if (data_hid < 0)
jwe@4972
   284
    {
jwe@4972
   285
      H5Sclose (space_hid);
jwe@4972
   286
      H5Gclose (group_hid);
jwe@4972
   287
      return false;
jwe@4972
   288
    }
jwe@4972
   289
jwe@4973
   290
  OCTAVE_LOCAL_BUFFER (char, s, ifargs.length () * (len + 1));
jwe@4972
   291
jwe@4972
   292
  // Save the args as a null teminated list
jwe@4973
   293
  for (int i = 0; i < ifargs.length (); i++)
jwe@4972
   294
    {
jwe@4973
   295
      const char * cptr = ifargs(i).c_str ();
jwe@4973
   296
      for (size_t j = 0; j < ifargs(i).length (); j++)
jwe@4972
   297
	s[i*(len+1)+j] = *cptr++;
jwe@4973
   298
      s[ifargs(i).length ()] = '\0';
jwe@4972
   299
    }
jwe@4972
   300
jwe@4973
   301
  retval = H5Dwrite (data_hid, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL,
jwe@4972
   302
		     H5P_DEFAULT, s) >= 0;
jwe@4972
   303
jwe@4972
   304
  H5Dclose (data_hid);
jwe@4972
   305
  H5Sclose (space_hid);
jwe@4972
   306
jwe@4972
   307
  if (!retval)
jwe@4972
   308
    {
jwe@4972
   309
      H5Gclose (group_hid);
jwe@4972
   310
      return false;
jwe@4973
   311
    }
jwe@4972
   312
jwe@4972
   313
  // attach the type of the variable
jwe@4973
   314
  type_hid = H5Tcopy (H5T_C_S1);
jwe@4972
   315
  H5Tset_size (type_hid, nm.length () + 1);
jwe@4972
   316
  if (type_hid < 0)
jwe@4972
   317
    {
jwe@4972
   318
      H5Gclose (group_hid);
jwe@4972
   319
      return false;
jwe@4973
   320
    }
jwe@4972
   321
jwe@4972
   322
  hdims[0] = 0;
jwe@5760
   323
  space_hid = H5Screate_simple (0 , hdims, 0);
jwe@4972
   324
  if (space_hid < 0)
jwe@4972
   325
    {
jwe@4972
   326
      H5Tclose (type_hid);
jwe@4972
   327
      H5Gclose (group_hid);
jwe@4972
   328
      return false;
jwe@4973
   329
    }
jwe@4972
   330
jwe@4972
   331
  data_hid = H5Dcreate (group_hid, "nm",  type_hid, space_hid, H5P_DEFAULT);
jwe@4973
   332
  if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL,
jwe@5760
   333
				H5P_DEFAULT, nm.c_str ()) < 0)
jwe@4972
   334
    {
jwe@4972
   335
      H5Sclose (space_hid);
jwe@4972
   336
      H5Tclose (type_hid);
jwe@4972
   337
      H5Gclose (group_hid);
jwe@4972
   338
      return false;
jwe@4973
   339
    }
jwe@4972
   340
  H5Dclose (data_hid);
jwe@4972
   341
jwe@4972
   342
  // attach the type of the variable
jwe@4972
   343
  H5Tset_size (type_hid, iftext.length () + 1);
jwe@4972
   344
  if (type_hid < 0)
jwe@4972
   345
    {
jwe@4972
   346
      H5Gclose (group_hid);
jwe@4972
   347
      return false;
jwe@4973
   348
    }
jwe@4972
   349
jwe@4973
   350
  data_hid = H5Dcreate (group_hid, "iftext",  type_hid, space_hid,
jwe@4972
   351
			H5P_DEFAULT);
jwe@4973
   352
  if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL,
jwe@5760
   353
				H5P_DEFAULT, iftext.c_str ()) < 0)
jwe@4972
   354
    {
jwe@4972
   355
      H5Sclose (space_hid);
jwe@4972
   356
      H5Tclose (type_hid);
jwe@4972
   357
      H5Gclose (group_hid);
jwe@4972
   358
      return false;
jwe@4973
   359
    }
jwe@4972
   360
jwe@4972
   361
  H5Dclose (data_hid);
jwe@4988
   362
  H5Sclose (space_hid);
jwe@4988
   363
  H5Tclose (type_hid);
jwe@4988
   364
  H5Gclose (group_hid);
jwe@4972
   365
jwe@4972
   366
  return retval;
jwe@4972
   367
}
jwe@4972
   368
jwe@4972
   369
bool
jwe@4972
   370
octave_fcn_inline::load_hdf5 (hid_t loc_id, const char *name,
jwe@4973
   371
			      bool /* have_h5giterate_bug */)
jwe@4972
   372
{
jwe@4972
   373
  hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
jwe@4972
   374
  hsize_t rank;
jwe@4972
   375
  int slen;
jwe@4972
   376
jwe@4972
   377
  group_hid = H5Gopen (loc_id, name);
jwe@4972
   378
  if (group_hid < 0 ) return false;
jwe@4972
   379
jwe@4972
   380
  data_hid = H5Dopen (group_hid, "args");
jwe@4972
   381
  space_hid = H5Dget_space (data_hid);
jwe@4972
   382
  rank = H5Sget_simple_extent_ndims (space_hid);
jwe@4972
   383
jwe@4972
   384
  if (rank != 2)
jwe@4973
   385
    {
jwe@4972
   386
      H5Dclose (data_hid);
jwe@4972
   387
      H5Sclose (space_hid);
jwe@4972
   388
      H5Gclose (group_hid);
jwe@4972
   389
      return false;
jwe@4972
   390
    }
jwe@4972
   391
jwe@4972
   392
  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
jwe@4972
   393
  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
jwe@4972
   394
jwe@4972
   395
  H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
jwe@4972
   396
jwe@4973
   397
  ifargs.resize (hdims[1]);
jwe@4972
   398
jwe@4972
   399
  OCTAVE_LOCAL_BUFFER (char, s1, hdims[0] * hdims[1]);
jwe@4972
   400
jwe@4973
   401
  if (H5Dread (data_hid, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL,
jwe@4972
   402
	       H5P_DEFAULT, s1) < 0)
jwe@4973
   403
    {
jwe@4972
   404
      H5Dclose (data_hid);
jwe@4972
   405
      H5Sclose (space_hid);
jwe@4972
   406
      H5Gclose (group_hid);
jwe@4972
   407
      return false;
jwe@4972
   408
    }
jwe@4972
   409
jwe@4972
   410
  H5Dclose (data_hid);
jwe@4972
   411
  H5Sclose (space_hid);
jwe@4972
   412
jwe@4972
   413
  for (size_t i = 0; i < hdims[1]; i++)
jwe@4972
   414
    ifargs(i) = std::string (s1 + i*hdims[0]);
jwe@4972
   415
jwe@4972
   416
  data_hid = H5Dopen (group_hid, "nm");
jwe@4972
   417
jwe@4972
   418
  if (data_hid < 0)
jwe@4972
   419
    {
jwe@4972
   420
      H5Gclose (group_hid);
jwe@4972
   421
      return false;
jwe@4972
   422
    }
jwe@4972
   423
jwe@4972
   424
  type_hid = H5Dget_type (data_hid);
jwe@4972
   425
  type_class_hid = H5Tget_class (type_hid);
jwe@4972
   426
jwe@4972
   427
  if (type_class_hid != H5T_STRING)
jwe@4972
   428
    {
jwe@4972
   429
      H5Tclose (type_hid);
jwe@4972
   430
      H5Dclose (data_hid);
jwe@4972
   431
      H5Gclose (group_hid);
jwe@4972
   432
      return false;
jwe@4972
   433
    }
jwe@4973
   434
jwe@4972
   435
  space_hid = H5Dget_space (data_hid);
jwe@4972
   436
  rank = H5Sget_simple_extent_ndims (space_hid);
jwe@4972
   437
jwe@4972
   438
  if (rank != 0)
jwe@4972
   439
    {
jwe@4972
   440
      H5Sclose (space_hid);
jwe@4972
   441
      H5Tclose (type_hid);
jwe@4972
   442
      H5Dclose (data_hid);
jwe@4972
   443
      H5Gclose (group_hid);
jwe@4972
   444
      return false;
jwe@4972
   445
    }
jwe@4972
   446
jwe@4972
   447
  slen = H5Tget_size (type_hid);
jwe@4972
   448
  if (slen < 0)
jwe@4972
   449
    {
jwe@4972
   450
      H5Sclose (space_hid);
jwe@4972
   451
      H5Tclose (type_hid);
jwe@4972
   452
      H5Dclose (data_hid);
jwe@4972
   453
      H5Gclose (group_hid);
jwe@4972
   454
      return false;
jwe@4972
   455
    }
jwe@4972
   456
jwe@4972
   457
  OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen);
jwe@4972
   458
jwe@4972
   459
  // create datatype for (null-terminated) string to read into:
jwe@4972
   460
  st_id = H5Tcopy (H5T_C_S1);
jwe@4972
   461
  H5Tset_size (st_id, slen);
jwe@4972
   462
jwe@5760
   463
  if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, nm_tmp) < 0)
jwe@4972
   464
    {
jwe@4972
   465
      H5Sclose (space_hid);
jwe@4972
   466
      H5Tclose (type_hid);
jwe@4972
   467
      H5Gclose (group_hid);
jwe@4972
   468
      return false;
jwe@4972
   469
    }
jwe@4972
   470
  H5Tclose (st_id);
jwe@4972
   471
  H5Dclose (data_hid);
jwe@4972
   472
  nm = nm_tmp;
jwe@4972
   473
jwe@4972
   474
  data_hid = H5Dopen (group_hid, "iftext");
jwe@4972
   475
jwe@4972
   476
  if (data_hid < 0)
jwe@4972
   477
    {
jwe@4972
   478
      H5Gclose (group_hid);
jwe@4972
   479
      return false;
jwe@4972
   480
    }
jwe@4972
   481
jwe@4972
   482
  type_hid = H5Dget_type (data_hid);
jwe@4972
   483
  type_class_hid = H5Tget_class (type_hid);
jwe@4972
   484
jwe@4972
   485
  if (type_class_hid != H5T_STRING)
jwe@4972
   486
    {
jwe@4972
   487
      H5Tclose (type_hid);
jwe@4972
   488
      H5Dclose (data_hid);
jwe@4972
   489
      H5Gclose (group_hid);
jwe@4972
   490
      return false;
jwe@4972
   491
    }
jwe@4973
   492
jwe@4972
   493
  space_hid = H5Dget_space (data_hid);
jwe@4972
   494
  rank = H5Sget_simple_extent_ndims (space_hid);
jwe@4972
   495
jwe@4972
   496
  if (rank != 0)
jwe@4972
   497
    {
jwe@4972
   498
      H5Sclose (space_hid);
jwe@4972
   499
      H5Tclose (type_hid);
jwe@4972
   500
      H5Dclose (data_hid);
jwe@4972
   501
      H5Gclose (group_hid);
jwe@4972
   502
      return false;
jwe@4972
   503
    }
jwe@4972
   504
jwe@4972
   505
  slen = H5Tget_size (type_hid);
jwe@4972
   506
  if (slen < 0)
jwe@4972
   507
    {
jwe@4972
   508
      H5Sclose (space_hid);
jwe@4972
   509
      H5Tclose (type_hid);
jwe@4972
   510
      H5Dclose (data_hid);
jwe@4972
   511
      H5Gclose (group_hid);
jwe@4972
   512
      return false;
jwe@4972
   513
    }
jwe@4972
   514
jwe@4972
   515
  OCTAVE_LOCAL_BUFFER (char, iftext_tmp, slen);
jwe@4972
   516
jwe@4972
   517
  // create datatype for (null-terminated) string to read into:
jwe@4972
   518
  st_id = H5Tcopy (H5T_C_S1);
jwe@4972
   519
  H5Tset_size (st_id, slen);
jwe@4972
   520
jwe@5760
   521
  if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, iftext_tmp) < 0)
jwe@4972
   522
    {
jwe@4972
   523
      H5Sclose (space_hid);
jwe@4972
   524
      H5Tclose (type_hid);
jwe@4972
   525
      H5Gclose (group_hid);
jwe@4972
   526
      return false;
jwe@4972
   527
    }
jwe@4972
   528
  H5Tclose (st_id);
jwe@4972
   529
  H5Dclose (data_hid);
jwe@4972
   530
  iftext = iftext_tmp;
jwe@4972
   531
jwe@4972
   532
  octave_fcn_inline ftmp (iftext, ifargs, nm);
jwe@4972
   533
  fcn = ftmp.fcn;
jwe@4972
   534
jwe@4972
   535
  return true;
jwe@4972
   536
}
jwe@4972
   537
#endif
jwe@4972
   538
jwe@4933
   539
void
jwe@4933
   540
octave_fcn_inline::print (std::ostream& os, bool pr_as_read_syntax) const
jwe@4933
   541
{
jwe@4933
   542
  print_raw (os, pr_as_read_syntax);
jwe@4933
   543
  newline (os);
jwe@4933
   544
}
jwe@4933
   545
jwe@4933
   546
void
jwe@4933
   547
octave_fcn_inline::print_raw (std::ostream& os, bool pr_as_read_syntax) const
jwe@4933
   548
{
jwe@5765
   549
  std::ostringstream buf;
jwe@4933
   550
jwe@4933
   551
  if (nm.empty ())
jwe@4933
   552
    buf << "f(";
jwe@4933
   553
  else
jwe@4933
   554
    buf << nm << "(";
jwe@4933
   555
jwe@4933
   556
  for (int i = 0; i < ifargs.length (); i++)
jwe@4933
   557
    {
jwe@4933
   558
      if (i)
jwe@4933
   559
	buf << ", ";
jwe@4933
   560
jwe@4933
   561
      buf << ifargs(i);
jwe@4933
   562
    }
jwe@4933
   563
jwe@5765
   564
  buf << ") = " << iftext;
jwe@4933
   565
jwe@5765
   566
  octave_print_internal (os, buf.str (), pr_as_read_syntax,
jwe@4933
   567
			 current_print_indent_level ());
jwe@4933
   568
}
jwe@4933
   569
jwe@4933
   570
octave_value
jwe@5279
   571
octave_fcn_inline::convert_to_str_internal (bool, bool, char type) const
jwe@4933
   572
{
jwe@5279
   573
  return octave_value (fcn_text (), type);
jwe@4933
   574
}
jwe@4933
   575
jwe@6973
   576
DEFUNX ("inline", Finline, args, ,
jwe@4933
   577
  "-*- texinfo -*-\n\
jwe@4933
   578
@deftypefn {Built-in Function} {} inline (@var{str})\n\
jwe@6547
   579
@deftypefnx {Built-in Function} {} inline (@var{str}, @var{arg1}, @dots{})\n\
jwe@4933
   580
@deftypefnx {Built-in Function} {} inline (@var{str}, @var{n})\n\
jwe@4933
   581
Create an inline function from the character string @var{str}.\n\
jwe@5034
   582
If called with a single argument, the arguments of the generated\n\
jwe@5034
   583
function are extracted from the function itself. The generated\n\
jwe@5034
   584
function arguments will then be in alphabetical order. It should\n\
jwe@5034
   585
be noted that i, and j are ignored as arguments due to the\n\
jwe@5034
   586
ambiguity between their use as a variable or their use as an inbuilt\n\
jwe@7001
   587
constant. All arguments followed by a parenthesis are considered\n\
jwe@5034
   588
to be functions.\n\
jwe@4933
   589
\n\
jwe@4933
   590
If the second and subsequent arguments are character strings,\n\
jwe@4933
   591
they are the names of the arguments of the function.\n\
jwe@4933
   592
\n\
jwe@4933
   593
If the second argument is an integer @var{n}, the arguments are\n\
jwe@4933
   594
@code{\"x\"}, @code{\"P1\"}, @dots{}, @code{\"P@var{N}\"}.\n\
jwe@5642
   595
@seealso{argnames, formula, vectorize}\n\
jwe@5642
   596
@end deftypefn")
jwe@4933
   597
{
jwe@4933
   598
  octave_value retval;
jwe@4933
   599
jwe@4933
   600
  int nargin = args.length ();
jwe@4933
   601
jwe@4933
   602
  if (nargin > 0)
jwe@4933
   603
    {
jwe@4933
   604
      std::string fun = args(0).string_value ();
jwe@4933
   605
jwe@4933
   606
      if (! error_state)
jwe@4933
   607
	{
jwe@4933
   608
	  string_vector fargs;
jwe@4933
   609
jwe@4933
   610
	  if (nargin == 1)
jwe@4933
   611
	    {
jwe@5034
   612
	      bool is_arg = false;
jwe@5037
   613
	      bool in_string = false;
jwe@5034
   614
	      std::string tmp_arg;
jwe@5034
   615
	      size_t i = 0;
jwe@5034
   616
	      
jwe@5034
   617
	      while (i < fun.length ())
jwe@5034
   618
		{
jwe@5037
   619
		  bool terminate_arg = false;
jwe@5034
   620
		  char c = fun[i++];
jwe@5022
   621
jwe@5037
   622
		  if (in_string)
jwe@5037
   623
		    {
jwe@5037
   624
		      if (c == '\'' || c == '\"')
jwe@5037
   625
			in_string = false;
jwe@5037
   626
		    }
jwe@5037
   627
		  else if (c == '\'' || c == '\"')
jwe@5037
   628
		    {
jwe@5037
   629
		      in_string = true;
jwe@5037
   630
		      if (is_arg)
jwe@5037
   631
			terminate_arg = true;
jwe@5037
   632
		    }
jwe@5037
   633
		  else if (! isalpha (c) && c != '_')
jwe@5034
   634
		    if (! is_arg)
jwe@5034
   635
		      continue;
jwe@5034
   636
		    else if (isdigit (c))
jwe@5037
   637
		      tmp_arg.append (1, c);
jwe@5034
   638
		    else
jwe@5034
   639
		      {
jwe@5037
   640
			// Before we do anything remove trailing whitespaces.
jwe@5034
   641
			while (i < fun.length () && isspace (c))
jwe@5034
   642
			  c = fun[i++];
jwe@5037
   643
			
jwe@5034
   644
			// Do we have a variable or a function?
jwe@5034
   645
			if (c != '(')
jwe@5037
   646
			  terminate_arg = true;
jwe@5037
   647
			else
jwe@5034
   648
			  {
jwe@5037
   649
			    tmp_arg = std::string ();
jwe@5037
   650
			    is_arg = false;
jwe@5034
   651
			  }
jwe@5034
   652
		      }
jwe@5034
   653
		  else
jwe@5022
   654
		    {
jwe@5034
   655
		      tmp_arg.append (1, c);
jwe@5034
   656
		      is_arg = true;
jwe@5037
   657
		    }
jwe@5023
   658
jwe@5037
   659
		  if (terminate_arg || (i == fun.length () && is_arg))
jwe@5037
   660
		    {
jwe@5037
   661
		      bool have_arg = false;
jwe@5037
   662
		      
jwe@5037
   663
		      for (int j = 0; j < fargs.length (); j++)
jwe@5037
   664
			if (tmp_arg == fargs (j))
jwe@5037
   665
			  {
jwe@5037
   666
			    have_arg = true;
jwe@5037
   667
			    break;
jwe@5037
   668
			  }
jwe@5034
   669
			  
dbateman@7509
   670
		      if (! have_arg && tmp_arg != "i" && tmp_arg != "j" &&
dbateman@7509
   671
			  tmp_arg != "NaN" && tmp_arg != "nan" && 
dbateman@7509
   672
			  tmp_arg != "Inf" && tmp_arg != "inf" && 
dbateman@7509
   673
			  tmp_arg != "NA" && tmp_arg != "pi" &&
dbateman@7509
   674
			  tmp_arg != "eps")
jwe@5037
   675
			fargs.append (tmp_arg);
jwe@5037
   676
jwe@5037
   677
		      tmp_arg = std::string ();
jwe@5037
   678
		      is_arg = false;
jwe@5022
   679
		    }
jwe@5022
   680
		}
jwe@5034
   681
jwe@5037
   682
	      // Sort the arguments into ascii order.
jwe@5034
   683
	      fargs.qsort ();
jwe@4933
   684
	    }
jwe@4933
   685
	  else if (nargin == 2 && args(1).is_numeric_type ())
jwe@4933
   686
	    {
jwe@4933
   687
	      int n = args(1).int_value ();
jwe@4933
   688
jwe@4933
   689
	      if (! error_state)
jwe@4933
   690
		{
jwe@4933
   691
		  if (n >= 0)
jwe@4933
   692
		    {
jwe@4933
   693
		      fargs.resize (n+1);
jwe@4933
   694
jwe@4933
   695
		      fargs(0) = "x";
jwe@4933
   696
jwe@4933
   697
		      for (int i = 1; i < n+1; i++)
jwe@4933
   698
			{
jwe@5765
   699
			  std::ostringstream buf;
jwe@5765
   700
			  buf << "P" << i;
jwe@5765
   701
			  fargs(i) = buf.str ();
jwe@4933
   702
			}
jwe@4933
   703
		    }
jwe@4933
   704
		  else
jwe@4933
   705
		    {
jwe@4933
   706
		      error ("inline: numeric argument must be nonnegative");
jwe@4933
   707
		      return retval;
jwe@4933
   708
		    }
jwe@4933
   709
		}
jwe@4933
   710
	      else
jwe@4933
   711
		{
jwe@4933
   712
		  error ("inline: expecting second argument to be an integer");
jwe@4933
   713
		  return retval;
jwe@4933
   714
		}
jwe@4933
   715
	    }
jwe@4933
   716
	  else
jwe@4933
   717
	    {
jwe@4933
   718
	      fargs.resize (nargin - 1);
jwe@4933
   719
jwe@4933
   720
	      for (int i = 1; i < nargin; i++)
jwe@4933
   721
		{
jwe@4933
   722
		  std::string s = args(i).string_value ();
jwe@4933
   723
jwe@4933
   724
		  if (! error_state)
jwe@4933
   725
		    fargs(i-1) = s;
jwe@4933
   726
		  else
jwe@4933
   727
		    {
jwe@4933
   728
		      error ("inline: expecting string arguments");
jwe@4933
   729
		      return retval;
jwe@4933
   730
		    }
jwe@4933
   731
		}
jwe@4933
   732
	    }
jwe@4933
   733
jwe@4933
   734
	  retval = octave_value (new octave_fcn_inline (fun, fargs));
jwe@4933
   735
	}
jwe@4933
   736
      else
jwe@4933
   737
	error ("inline: first argument must be a string");
jwe@4933
   738
    }
jwe@4933
   739
  else
jwe@5823
   740
    print_usage ();
jwe@4933
   741
jwe@4933
   742
  return retval;
jwe@4933
   743
}
jwe@4933
   744
jwe@4933
   745
DEFUN (formula, args, ,
jwe@4933
   746
  "-*- texinfo -*-\n\
jwe@4933
   747
@deftypefn {Built-in Function} {} formula (@var{fun})\n\
jwe@4933
   748
Return a character string representing the inline function @var{fun}.\n\
jwe@4933
   749
Note that @code{char (@var{fun})} is equivalent to\n\
jwe@4933
   750
@code{formula (@var{fun})}.\n\
jwe@5642
   751
@seealso{argnames, inline, vectorize}\n\
jwe@5642
   752
@end deftypefn")
jwe@4933
   753
{
jwe@4933
   754
  octave_value retval;
jwe@4933
   755
jwe@4933
   756
  int nargin = args.length ();
jwe@4933
   757
jwe@4933
   758
  if (nargin == 1)
jwe@4933
   759
    {
jwe@4933
   760
      octave_fcn_inline* fn = args(0).fcn_inline_value (true);
jwe@4933
   761
jwe@4933
   762
      if (fn)
jwe@4933
   763
	retval = octave_value (fn->fcn_text ());
jwe@4933
   764
      else
jwe@4933
   765
	error ("formula: must be an inline function");
jwe@4933
   766
    }
jwe@4933
   767
  else
jwe@5823
   768
    print_usage ();
jwe@4933
   769
jwe@4933
   770
  return retval;
jwe@4933
   771
}
jwe@4933
   772
jwe@4933
   773
DEFUN (argnames, args, ,
jwe@4933
   774
  "-*- texinfo -*-\n\
jwe@4933
   775
@deftypefn {Built-in Function} {} argnames (@var{fun})\n\
jwe@4933
   776
Return a cell array of character strings containing the names of\n\
jwe@4933
   777
the arguments of the inline function @var{fun}.\n\
jwe@6529
   778
@seealso{inline, formula, vectorize}\n\
jwe@5642
   779
@end deftypefn")
jwe@4933
   780
{
jwe@4933
   781
  octave_value retval;
jwe@4933
   782
jwe@4933
   783
  int nargin = args.length ();
jwe@4933
   784
jwe@4933
   785
  if (nargin == 1)
jwe@4933
   786
    {
jwe@4933
   787
      octave_fcn_inline *fn = args(0).fcn_inline_value (true);
jwe@4933
   788
jwe@4933
   789
      if (fn)
jwe@4933
   790
	{
jwe@4933
   791
	  string_vector t1 = fn->fcn_arg_names ();
jwe@4933
   792
jwe@4933
   793
	  Cell t2 (dim_vector (t1.length (), 1));
jwe@4933
   794
jwe@4933
   795
	  for (int i = 0; i < t1.length (); i++)
jwe@4933
   796
	    t2(i) = t1(i);
jwe@4933
   797
jwe@4933
   798
	  retval = t2;
jwe@4933
   799
	}
jwe@4933
   800
      else
jwe@4933
   801
	error ("argnames: argument must be an inline function");
jwe@4933
   802
    }
jwe@4933
   803
  else
jwe@5823
   804
    print_usage ();
jwe@4933
   805
jwe@4933
   806
  return retval;
jwe@4933
   807
}
jwe@4933
   808
jwe@4933
   809
DEFUN (vectorize, args, ,
jwe@4933
   810
  "-*- texinfo -*-\n\
dbateman@6635
   811
@deftypefn {Built-in Function} {} vectorize (@var{fun})\n\
jwe@4933
   812
Create a vectorized version of the inline function @var{fun}\n\
jwe@4933
   813
by replacing all occurrences of @code{*}, @code{/}, etc., with\n\
jwe@4933
   814
@code{.*}, @code{./}, etc.\n\
jwe@5642
   815
@end deftypefn")
jwe@4933
   816
{
jwe@4933
   817
  octave_value retval;
jwe@4933
   818
jwe@4933
   819
  int nargin = args.length ();
jwe@4933
   820
jwe@4933
   821
  if (nargin == 1)
jwe@4933
   822
    {
dbateman@5409
   823
      std::string old_func;
dbateman@5409
   824
      octave_fcn_inline* old = 0;
dbateman@5409
   825
      bool func_is_string = true;
jwe@4933
   826
dbateman@5409
   827
      if (args(0).is_string ())
dbateman@5409
   828
	old_func = args(0).string_value ();
dbateman@5409
   829
      else
jwe@4933
   830
	{
dbateman@5409
   831
	  old = args(0).fcn_inline_value (true);
dbateman@5409
   832
	  func_is_string = false;
dbateman@5409
   833
dbateman@5409
   834
	  if (old)
dbateman@5409
   835
	    old_func = old->fcn_text ();
dbateman@5409
   836
	  else
dbateman@5409
   837
	    error ("vectorize: must be a string or inline function");
dbateman@5409
   838
	}
dbateman@5409
   839
dbateman@5409
   840
      if (! error_state)
dbateman@5409
   841
	{
jwe@4933
   842
	  std::string new_func;
jwe@4933
   843
	  size_t i = 0;
jwe@4933
   844
jwe@4933
   845
	  while (i < old_func.length ())
jwe@4933
   846
	    {
jwe@4933
   847
	      std::string t1 = old_func.substr (i, 1);
jwe@4933
   848
jwe@4933
   849
	      if (t1 == "*" || t1 == "/" || t1 == "\\" || t1 == "^")
jwe@4933
   850
		{
jwe@4933
   851
		  if (i && old_func.substr (i-1, 1) != ".")
jwe@4933
   852
		    new_func.append (".");
jwe@4933
   853
jwe@4933
   854
		  // Special case for ** operator.
jwe@4973
   855
		  if (t1 == "*" && i < (old_func.length () - 1)
jwe@4933
   856
		      && old_func.substr (i+1, 1) == "*")
jwe@4933
   857
		    {
jwe@4933
   858
		      new_func.append ("*");
jwe@4933
   859
		      i++;
jwe@4933
   860
		    }
jwe@4933
   861
		}
jwe@4933
   862
	      new_func.append (t1);
jwe@4933
   863
	      i++;
jwe@4933
   864
	    }
jwe@4933
   865
dbateman@5409
   866
	  if (func_is_string)
dbateman@5409
   867
	    retval = octave_value (new_func);
dbateman@5409
   868
	  else
dbateman@5409
   869
	    retval = octave_value (new octave_fcn_inline 
dbateman@5409
   870
				   (new_func, old->fcn_arg_names ()));
jwe@4933
   871
	}
jwe@4933
   872
    }
jwe@4933
   873
  else
jwe@5823
   874
    print_usage ();
jwe@4933
   875
jwe@4933
   876
  return retval;
jwe@4933
   877
}
jwe@4933
   878
jwe@4933
   879
/*
jwe@4933
   880
;;; Local Variables: ***
jwe@4933
   881
;;; mode: C++ ***
jwe@4933
   882
;;; End: ***
jwe@4933
   883
*/