File: Printf.cpp

package info (click to toggle)
freemat 4.0-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 174,736 kB
  • ctags: 67,053
  • sloc: cpp: 351,060; ansic: 255,892; sh: 40,590; makefile: 4,323; perl: 4,058; asm: 3,313; pascal: 2,718; fortran: 1,722; ada: 1,681; ml: 1,360; cs: 879; csh: 795; python: 430; sed: 162; lisp: 160; awk: 5
file content (566 lines) | stat: -rw-r--r-- 21,261 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
/*
 * Copyright (c) 2009 Eugene Ingerman
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "Printf.hpp"
#include "Print.hpp"
#include "HandleList.hpp"
#include "Algorithms.hpp"
#include "Utils.hpp"
#include <QTextCodec>
#include <QFile>
#include <QTextStream>

extern HandleList<FilePtr*> fileHandles;

class PrintfStream{
public:
  virtual PrintfStream& operator <<( const char* data ) = 0;
};

class PrintfFileStream : public PrintfStream{
private:
  QFile* fp;
  QTextStream ts;
public:
  PrintfFileStream( QFile* fp_ ) : fp( fp_ ) { ts.setDevice( fp ); };
  virtual PrintfFileStream& operator <<( const char* data ){
    ts << data;
    return *this;
  };
  ~PrintfFileStream() { fp->flush(); };
};

class PrintfStringStream : public PrintfStream{
private:
  QString* str;
public:
  PrintfStringStream( QString* str_ ) : str(str_){};
  virtual PrintfStringStream& operator <<( const char* data ){
    (*str) += QString( data );
    return *this;
  };
};


bool isEscape(char *dp) {
  return ((dp[0] == '\\') &&
	  ((dp[1] == 'n') ||
	   (dp[1] == 't') ||
	   (dp[1] == 'r') ||
	   (dp[1] == '\\')));
}

static int flagChar(char c) {
  return ((c == '#') ||  (c == '0') || (c == '-') ||  
	  (c == ' ') ||  (c == '+'));
}

static int convspec(char c) {
  return ((c == 'd') || (c == 'i') || (c == 'o') || 
	  (c == 'u') || (c == 'x') || (c == 'X') ||
	  (c == 'e') || (c == 'E') || (c == 'f') || 
	  (c == 'F') || (c == 'g') || (c == 'G') ||
	  (c == 'a') || (c == 'A') || (c == 'c') || 
	  (c == 's'));
}

static char* validateFormatSpec(char* cp) {
  if (*cp == '%') return cp+1;
  while ((*cp) && flagChar(*cp)) cp++;
  while ((*cp) && isdigit(*cp)) cp++;
  while ((*cp) && (*cp == '.')) cp++;
  while ((*cp) && isdigit(*cp)) cp++;
  if ((*cp) && convspec(*cp)) 
    return cp+1;
  else
    return 0;
}

QString ConvertEscapeSequences(const QString &src) {
  QString dest;
  int i=0;
  while (i < src.size()) {
    if ((src[i] != '\\') || (i == (src.size()-1))) {
      dest += src[i];
    } else {
      if (src[i+1] == 'n') {
	dest += '\n';
	i++;
      } else if (src[i+1] == 't') {
	dest += '\t';
	i++;
      } else if (src[i+1] == 'r') {
	dest += '\r';
	i++;
      } else {
	dest += src[i+1];
	i++;
      }
    }
    i++;
  }
  return dest;
}

class PrintfDataServer{
private:
  const ArrayVector arg;
  int vec_ind;
  int elem_ind;
  bool hasMoreData;
  void IncDataPtr(void){
    if( ++elem_ind >= arg[ vec_ind ].length() ){
      if( ++vec_ind < arg.size() ){
	elem_ind = 0;
      }
      else{
	hasMoreData = false;
      }
    }
  };

public:
  PrintfDataServer( const ArrayVector& arg_ ):arg(arg_),vec_ind(1),elem_ind(0){
    //vec_ind starts with 1, because zeroth argument is format string
    hasMoreData = (arg.size() > 1); //( (arg.size() > 1) && (arg[1].getLength() > 0));
  };

  void GetNextAsDouble(double& data){
    if( !hasMoreData )
      throw Exception("Error: no more data");
    if( arg[vec_ind].isEmpty()) {
      data = 0;
    } else {
      if( arg[ vec_ind ].isScalar() )
	data = arg[ vec_ind ].asDouble();
      else
	data = arg[ vec_ind ].get( elem_ind+1 ).asDouble();
    }
    IncDataPtr();
  };

  void GetNextAsString(std::string& str){
    if( !hasMoreData )
      throw Exception("Error: no more data");
    Array d(arg[ vec_ind ]);
    if (!d.isEmpty()) {
      if( d.isString() ){
	QString s = d.asString();
	QChar* data = s.data();
	while( elem_ind < s.length() ){
	  str.push_back((data + elem_ind++)->toAscii());
	}
      }else{
	str.push_back(d.get(elem_ind+1).asInteger());
      }
    }
    IncDataPtr();
  };
  bool HasMoreData(void){ return hasMoreData; };
};

//Common routine used by sprintf,printf,fprintf.  They all
//take the same inputs, and output either to a string, the
//console or a file.  For output to a console or a file, 
//we want escape-translation on.  For output to a string, we
//want escape-translation off.  So this common routine prints
//the contents to a string, which is then processed by each 
//subroutine.
void PrintfHelperFunction(int nargout, const ArrayVector& arg, PrintfStream& output, QByteArray& errmsg, Array& ret, bool convEscape = false ) 
{
  Array format(arg[0]);
  QString frmt = format.asString();

  std::vector<char> buff( frmt.length()+1 ); //vectors are contiguous in memory. we'll use it instead of char[]
  strncpy(&buff[0], frmt.toStdString().c_str(), frmt.length()+1 );

  // Search for the start of a format subspec
  char *dp = &buff[0];
  char *np;
  char sv;
  int nprn = 0;
  int noutput = 0;
  // Buffer to hold each sprintf result
#define BUFSIZE 65534
  char nbuff[BUFSIZE+1];
  memset( nbuff, 0, BUFSIZE+1 );

  // Buffer to hold the output
  //output.clear();
  errmsg.clear();

  PrintfDataServer ps( arg );

  //do while there is still data to output or format string to save
  while( (*dp) || ps.HasMoreData() ) {
    if ( !(*dp) && ps.HasMoreData() ) //still have arguments, need to rewind format.
      dp = &buff[0];

    np = dp;
    int nbuf_ind = 0;
    //copy string upto formatting character and do escape conversion in the process
    while ((*dp) && (*dp != '%') && nbuf_ind < BUFSIZE ){ 
      if (convEscape && isEscape(dp)) {
	switch (*(dp+1)) {
	case '\\':
	  *(nbuff+nbuf_ind) = '\\';
	  break;
	case 'n':
	  *(nbuff+nbuf_ind) = '\n';
	  break;
	case 't':
	  *(nbuff+nbuf_ind) = '\t';
	  break;
	case 'r':
	  *(nbuff+nbuf_ind) = '\r';
	  break;
	}
	dp += 2; ++nbuf_ind;
      } else
	*(nbuff+nbuf_ind++) = *(dp++);
    }

    // Print out the formatless segment
    *(nbuff+nbuf_ind) = 0;
    nprn = nbuf_ind; noutput += nbuf_ind;
    output << nbuff;    


    // Process the format spec
    if (*dp == '%' && *(dp+1)) {
      np = validateFormatSpec(dp+1);
      if (!np)
	throw Exception("erroneous format specification " + QString(dp));
      else {
	if (*(np-1) == '%') {
	  nprn = snprintf(nbuff,BUFSIZE,"%%"); nbuff[std::min(nprn+1,BUFSIZE-1)]='\0'; noutput += nbuf_ind;
	  output << nbuff;
	  sv=0;
	} else 
	  if( *(np-1) == 's') {
	    std::string str;
	    ps.GetNextAsString( str );
	    const char* pStr = str.c_str();
	    sv = *np;
	    *np = 0;
	    nprn = snprintf(nbuff,BUFSIZE,dp,pStr); nbuff[std::min(nprn+1,BUFSIZE-1)]='\0'; noutput += nbuf_ind;
	    output << nbuff;
	  } else{
	    sv = *np;
	    *np = 0;

	    double data;
	    ps.GetNextAsDouble( data );

	    switch (*(np-1)) 
	      {
	      case 'd':
	      case 'i':
	      case 'o':
	      case 'u':
	      case 'x':
	      case 'X':
	      case 'c':
		nprn = snprintf(nbuff,BUFSIZE,dp,(int32)data); nbuff[nprn+1]='\0'; noutput += nbuf_ind;
		output << nbuff;
		break;
	      case 'e':
	      case 'E':
	      case 'f':
	      case 'F':
	      case 'g':
	      case 'G':
		nprn = snprintf(nbuff,BUFSIZE,dp,data); nbuff[nprn+1]='\0'; noutput += nbuf_ind;
		output << nbuff;
		break;
	      }
	  }
	if( sv )
	  *np = sv;
	dp = np;
      }
    }
  }
  ret = Array( static_cast<double>(noutput) );
}

//!
//@Module SPRINTF Formated String Output Function (C-Style)
//@@Section IO
//@@Usage
//Prints values to a string.  The general syntax for its use is
//@[
//  y = sprintf(format,a1,a2,...).
//@]
//Here @|format| is the format string, which is a string that
//controls the format of the output.  The values of the variables
//@|a_i| are substituted into the output as required.  It is
//an error if there are not enough variables to satisfy the format
//string.  Note that this @|sprintf| command is not vectorized!  Each
//variable must be a scalar.  The returned value @|y| contains the
//string that would normally have been printed. For
//more details on the format string, see @|printf|.  
//@@Examples
//Here is an example of a loop that generates a sequence of files based on
//a template name, and stores them in a cell array.
//@<
//l = {}; for i = 1:5; s = sprintf('file_%d.dat',i); l(i) = {s}; end;
//l
//@>
//@@Tests
//@$exact#y1=sprintf('hello %d',5)
//@$exact#y1=sprintf('%d aa %s',5,'bcd')
//@$exact#y1=sprintf('%d %%aa %s %f',5,'bcd',5)
//@$exact#y1=sprintf('%d aa ',[5 6; 7 8])
//@@Signature
//function sprintf SprintfFunction
//inputs varargin
//outputs string
//!
ArrayVector SprintfFunction(int nargout, const ArrayVector& arg) {
  if (arg.size() == 0)
    throw Exception("sprintf requires at least one (string) argument");
  if (!arg[0].isString())
    throw Exception("sprintf format argument must be a string");

  QString outf;
  PrintfStringStream textstream( &outf );
  QByteArray errmsg;
  Array output;

  PrintfHelperFunction( nargout, arg, textstream, errmsg, output, true );
  ArrayVector ret;

  ret << Array( outf );
  ret << output;
  return ret;
}

//!
//@Module PRINTF Formated Output Function (C-Style)
//@@Section IO
//@@Usage
//Prints values to the output.  The general syntax for its use is
//@[
//  printf(format,a1,a2,...)
//@]
//Here @|format| is the format string, which is a string that
//controls the format of the output.  The values of the variables
//@|a_i| are substituted into the output as required.  It is
//an error if there are not enough variables to satisfy the format
//string.  Note that this @|printf| command is not vectorized!  Each
//variable must be a scalar.
//
//It is important to point out that the @|printf| function does not
//add a newline (or carriage return) to the output by default.  That
//can lead to some confusing behavior if you do not know what to expect.
//For example, the command @|printf('Hello')| does not appear to
//produce any output.  In fact, it does produce the text, but it then
//gets overwritten by the prompt.  To see the text, you need 
//@|printf('Hello\n')|.  This seems odd, but allows you to assemble a
//line using multiple @|printf| commands, including the @|'\n'| when
//you are done with the line.  You can also use the @|'\r'| character
//as an explicit carriage return (with no line feed).  This allows you
//to write to the same line many times (to show a progress string, for
//example).
//
//@@Format of the format string:
//
//The  format  string  is a character string, beginning and ending in its
//initial shift state, if any.  The format string is composed of zero  or
//more   directives:  ordinary  characters  (not  %),  which  are  copied
//unchanged to the output stream; and conversion specifications, each  of
//which results in fetching zero or more subsequent arguments.  Each 
//conversion specification is introduced by the character %, and ends with a
//conversion  specifier.  In between there may be (in this order) zero or
//more flags, an optional minimum field width, and an optional precision.
//
//The  arguments must correspond properly (after type promotion) with the
//conversion specifier, and are used in the order given.
//
//@@The flag characters:
//The character @|%| is followed by zero or more of the following flags:
//\begin{itemize}
//  \item @|\#|   The  value  should be converted to an ``alternate form''.  For @|o| conversions, the first character of the output  string  is  made  zero (by prefixing a @|0| if it was not zero already).  For @|x| and @|X| conversions, a nonzero result has the string @|'0x'| (or @|'0X'| for  @|X|  conversions) prepended to it.  For @|a, A, e, E, f, F, g,| and @|G|  conversions, the result will always  contain  a  decimal  point,  even  if  no digits follow it (normally, a decimal point appears  in the results of those conversions only if  a  digit  follows).  For @|g| and @|G| conversions, trailing zeros are not removed from the  result as they would otherwise be.  For other  conversions,  the  result is undefined.
//  \item @|0|   The value should be zero padded.  For @|d, i, o, u, x, X, a, A, e, E, f, F, g,| and @|G| conversions, the converted value is padded  on the  left  with  zeros rather than blanks.  If the @|0| and @|-| flags  both appear, the @|0| flag is ignored.  If  a  precision  is  given  with  a numeric conversion @|(d, i, o, u, x, and X)|, the @|0| flag is  ignored.  For other conversions, the behavior is undefined.
//  \item @|-|   The converted value is to be left adjusted on the  field  boundary.  (The default is right justification.) Except for @|n| conversions, the converted value is padded on the right  with  blanks, rather than on the left with blanks or zeros.  A @|-| overrides a @|0| if both are given.
//  \item @|' '| (a space) A blank should be left before a  positive  number  (or empty string) produced by a signed conversion.
//  \item @|+| A  sign  (@|+| or @|-|) always be placed before a number produced by a signed conversion.  By default a sign is used only for  negative numbers. A @|+| overrides a space if both are used.
//\end{itemize}
//@@The field width:
//An  optional decimal digit string (with nonzero first digit) specifying a 
//minimum field width.  If the converted  value  has  fewer  characters than 
//the  field  width,  it will be padded with spaces on the left (or right, 
//if the left-adjustment flag has been given).  A  negative  field width is 
//taken as a @|'-'| flag followed by a positive field  width. In no case does 
//a non-existent or small field width cause truncation of a field; if the 
//result of a conversion is wider than the  field  width, the field is 
//expanded to contain the conversion result.
//
//@@The precision:
//
//An  optional  precision,  in the form of a period (@|'.'|)  followed by an optional decimal digit string.  If the precision is given as just @|'.'|, or the precision is negative, the precision is  taken  to  be zero.   This  gives the minimum number of digits to appear for @|d, i, o, u, x|, and @|X| conversions, the number of digits to appear after the radix character  for  @|a, A, e, E, f|, and @|F| conversions, the maximum number of significant digits for @|g| and @|G| conversions, or the  maximum  number  of  characters to be printed from a string for s conversions.
//
//@@The conversion specifier:
//
//A character that specifies the type of conversion to be  applied.   The
//conversion specifiers and their meanings are:
//\begin{itemize}
//\item @|d,i|   The  int  argument is converted to signed decimal notation.  The  precision, if any, gives the minimum number of digits that  must   appear;  if  the  converted  value  requires fewer digits, it is    padded on the left with zeros. The default precision is @|1|.  When @|0|  is printed with an explicit precision @|0|, the output is empty.
//\item @|o,u,x,X|   The unsigned int argument is converted to  unsigned  octal  (@|o|),  unsigned  decimal  (@|u|),  or unsigned hexadecimal (@|x| and @|X|) notation.  The letters @|abcdef| are used for @|x| conversions;  the  letters @|ABCDEF| are used for @|X| conversions.  The precision, if any,  gives the minimum number of digits that must appear; if the converted  value  requires  fewer  digits, it is padded on the left  with zeros. The default precision is @|1|.  When @|0| is printed  with  an explicit precision @|0|, the output is empty.
//\item @|e,E|    The  double  argument  is  rounded  and  converted  in the style  @|[-]d.ddde dd| where there is one digit before  the  decimal-point  character and the number of digits after it is equal to the precision; if the precision is missing, it is taken as  @|6|;  if  the    precision  is  zero,  no  decimal-point character appears.  An @|E|  conversion uses the letter @|E| (rather than @|e|)  to  introduce  the  exponent.   The exponent always contains at least two digits; if  the value is zero, the exponent is @|00|.
//\item @|f,F|   The double argument is rounded and converted to decimal notation  in  the  style  @|[-]ddd.ddd|, where the number of digits after the decimal-point character is equal to the precision specification.  If  the precision is missing, it is taken as @|6|; if the precision  is explicitly zero, no decimal-point character  appears.   If  a   decimal point appears, at least one digit appears before it.
//\item @|g,G|   The double argument is converted in style @|f| or @|e| (or @|F| or @|E|  for  @|G|  conversions).  The precision specifies the number of significant digits.  If the precision is missing, @|6| digits  are  given;  if  the  precision is zero, it is treated as @|1|.  Style e is used   if the exponent from its conversion is less than @|-4|  or  greater than or equal to the precision.  Trailing zeros are removed from  the fractional part of the result; a decimal point appears  only  if it is followed by at least one digit.
//\item @|c| The int argument is  converted  to  an  unsigned  char, and  the resulting character is written.
//\item @|s| The string argument is printed.
//\item @|%|   A @|'%'| is written. No argument is converted. The complete conversion specification is @|'%%'|.
//\end{itemize}
//@@Example
//Here are some examples of the use of @|printf| with various arguments.  First we print out an integer and double value.
//@<
//printf('intvalue is %d, floatvalue is %f\n',3,1.53);
//@>
//Next, we print out a string value.
//@<
//printf('string value is %s\n','hello');
//@>
//Now, we print out an integer using 12 digits, zeros up front.
//@<
//printf('integer padded is %012d\n',32);
//@>
//Print out a double precision value with a sign, a total of 18 characters (zero prepended if necessary), a decimal point, and 12 digit precision.
//@<
//printf('float value is %+018.12f\n',pi);
//@>
//@@Signature
//sfunction printf PrintfFunction
//inputs varargin
//outpus none
//!
ArrayVector PrintfFunction(int nargout, const ArrayVector& arg, 
			   Interpreter* eval) {
  if (arg.size() == 0)
    throw Exception("printf requires at least one (string) argument");
  Array format(arg[0]);
  if (!format.isString())
    throw Exception("printf format argument must be a string");
  
  QString outf;
  PrintfStringStream textstream( &outf );
  
  QByteArray errmsg;
  Array output;
  
  PrintfHelperFunction( nargout, arg, textstream, errmsg, output, true );
  ArrayVector ret;
  
  eval->outputMessage( outf );
  return ArrayVector();
}

//!
//@Module FPRINTF Formated File Output Function (C-Style)
//@@Section IO
//@@Usage
//Prints values to a file.  The general syntax for its use is
//@[
//  fprintf(fp,format,a1,a2,...).
//@]
//or, 
//@[
//  fprintf(format,a1,a2,...).
//@]
//Here @|format| is the format string, which is a string that
//controls the format of the output.  The values of the variables
//@|ai| are substituted into the output as required.  It is
//an error if there are not enough variables to satisfy the format
//string.  Note that this @|fprintf| command is not vectorized!  Each
//variable must be a scalar.  The value @|fp| is the file handle.  If @|fp| is omitted,
//file handle @|1| is assumed, and the behavior of @|fprintf| is effectively equivalent to @|printf|. For
//more details on the format string, see @|printf|.
//@@Examples
//A number of examples are present in the Examples section of the @|printf| command.
//@@Signature
//sfunction fprintf FprintfFunction
//inputs varargin
//outputs varargout
//!
ArrayVector FprintfFunction(int nargout, const ArrayVector& arg, 
			    Interpreter* eval) {
  if (arg.size() == 0)
    throw Exception("fprintf requires at least one (string) argument");
  ArrayVector argCopy(arg);
  int handle = 1;
  if (arg.size() > 1) {
    Array tmp(arg[0]);
    if (tmp.isScalar()) {
      handle = tmp.asInteger();
      argCopy.pop_front();
    }
    else {
      handle=1;
    }
  }
  if (handle == 1)
    return PrintfFunction(nargout,argCopy,eval);
  Array format(argCopy[0]);
  if (!format.isString())
    throw Exception("fprintf format argument must be a string");
  ArrayVector argcopy(arg);
  argcopy.pop_front();

  FilePtr *fptr=(fileHandles.lookupHandle(handle+1));

  PrintfFileStream textstream( fptr->fp );
  QByteArray errmsg;
  Array output;

  PrintfHelperFunction( nargout, argcopy, textstream, errmsg, output, true );
  return ArrayVector() << output;
}

//!
//@Module DISP Display a Variable or Expression
//@@Section IO
//@@Usage
//Displays the result of a set of expressions.  The @|disp| function
//takes a variable number of arguments, each of which is an expression
//to output:
//@[
//  disp(expr1,expr2,...,exprn)
//@]
//This is functionally equivalent to evaluating each of the expressions
//without a semicolon after each.
//@@Example
//Here are some simple examples of using @|disp|.
//@<
//a = 32;
//b = 1:4;
//disp(a,b,pi)
//@>
//@@Signature
//sfunction disp DispFunction
//inputs varargin
//outputs none
//!
ArrayVector DispFunction(int nargout, const ArrayVector& arg, Interpreter* eval) {
  for (int i=0;i<arg.size();i++) 
    PrintArrayClassic(arg[i],eval->getPrintLimit(),eval);
  return ArrayVector();
}