functionend ignored

David Grundberg individ at acc.umu.se
Mon Jul 13 06:23:01 CDT 2009


Hi,

been working on lint, but I got stuck on this behavior I don't agree with.

Bug report for Octave 3.1.55 configured for i686-pc-linux-gnu

hg tip:
changeset:   9431:bfc7b000a229
tag:         tip
user:        John W. Eaton <jwe at octave.org>
date:        Sat Jul 11 12:46:10 2009 -0400
summary:     file-ops.cc (file_ops::symlink, file_ops::readlink): avoid 
incorrectly sized buffer

Description:
-----------

  * A user function may end with any number of 'functionend's, and no
    error will be given.

Repeat-By:
---------

  1. Create a file buggy.m:

cat > buggy.m << EOF
function [] = buggy()
endfunction
endfunction
EOF

  2. Run octave like

/opt/octave-head/bin/octave --eval 'addpath("."); __display_tokens__(1); 
buggy'

  3. Expected behavior is a syntax error. But the experienced behavior
     is that the function runs as normal.

       Note that running

/opt/octave-head/bin/octave  --eval '__display_tokens__(1);' buggy.m

     does raise a syntax error because of the extra endfunction.

Comments:
--------

  * Ends seems to be ignored? In the following excerpts, note that the
    end token is replaced with a '\n' in the first run.

    Running as a function from the Octave prompt:

octave:1> buggy
NAME
\n
FCN
[
]
'='
NAME
(
)
\n
\n
\n
END_OF_INPUT

parsed function end as end of input!
END_OF_INPUT

octave:2>

    Running buggy.m as an argument to octave:

FCN
[
]
'='
NAME
(
)
\n
END
parsed function end as a end token!
\n
END
parse error near line 3 of file buggy.m

  syntax error

 >>> endfunction

    For completeness, here are the changes I have done to the tip:

********************************************************************************
diff -r bfc7b000a229 src/parse.y
--- a/src/parse.y    Sat Jul 11 12:46:10 2009 -0400
+++ b/src/parse.y    Mon Jul 13 12:16:03 2009 +0200
@@ -268,7 +268,7 @@
 
 // Create a no-op statement for end_function.
 static tree_statement *
-make_end (const std::string& type, int l, int c);
+make_end (const std::string& type, int l, int c, bool implicit_end = 
false);
 
 // Do most of the work for defining a function.
 static octave_user_function *
@@ -1281,6 +1281,7 @@
 
 function_end    : END
           {
+            std::cout << "parsed function end as a end token!" << 
std::endl;
             if (end_token_ok ($1, token::function_end))
               $$ = make_end ("endfunction", $1->line (), $1->column ());
             else
@@ -1288,13 +1289,14 @@
           }
         | END_OF_INPUT
           {
+            std::cout << "parsed function end as end of input!" << 
std::endl;
             if (lexer_flags.parsing_nested_function)
               lexer_flags.parsing_nested_function = -1;
 
             if (reading_fcn_file || reading_script_file
             || get_input_from_eval_string)
               $$ = make_end ("endfunction", input_line_number,
-                     current_input_column);
+                     current_input_column, true);
             else
               YYABORT;
           }
@@ -2562,9 +2564,9 @@
 }
 
 static tree_statement *
-make_end (const std::string& type, int l, int c)
-{
-  return make_statement (new tree_no_op_command (type, l, c));
+make_end (const std::string& type, int l, int c, bool implicit_end)
+{
+  return make_statement (new tree_no_op_command (type, l, c, 
implicit_end));
 }
 
 // Do most of the work for defining a function.
diff -r bfc7b000a229 src/pt-cmd.h
--- a/src/pt-cmd.h    Sat Jul 11 12:46:10 2009 -0400
+++ b/src/pt-cmd.h    Mon Jul 13 12:16:03 2009 +0200
@@ -64,9 +64,15 @@
 {
 public:
 
-  tree_no_op_command (const std::string& cmd = "no_op", int l = -1, int 
c = -1)
-    : tree_command (l, c), eof (cmd == "endfunction" || cmd == 
"endscript"),
-      orig_cmd (cmd) { }
+  tree_no_op_command (const std::string& cmd = "no_op",
+              int l = -1,
+              int c = -1,
+              bool end_implicit = false)
+    : tree_command (l, c),
+      end_of_fcn_or_script (cmd == "endfunction" || cmd == "endscript"),
+      implicit_end (end_implicit),
+      orig_cmd (cmd)
+  { }
 
   ~tree_no_op_command (void) { }
 
@@ -75,13 +81,20 @@
 
   void accept (tree_walker& tw);
 
-  bool is_end_of_fcn_or_script (void) const { return eof; }
+  bool is_end_of_fcn_or_script (void) const { return 
end_of_fcn_or_script; }
+
+  bool is_implicit_end (void) const { return implicit_end; }
 
   std::string original_command (void) { return orig_cmd; }
 
 private:
 
-  bool eof;
+  bool end_of_fcn_or_script;
+
+  // User function ended with EOF instead of an explicit functionend.
+  // Implies end_of_fcn_or_script.
+
+  bool implicit_end;
 
   std::string orig_cmd;
 
diff -r bfc7b000a229 src/pt-pr-code.cc
--- a/src/pt-pr-code.cc    Sat Jul 11 12:46:10 2009 -0400
+++ b/src/pt-pr-code.cc    Mon Jul 13 12:16:03 2009 +0200
@@ -721,6 +721,9 @@
 void
 tree_print_code::visit_no_op_command (tree_no_op_command& cmd)
 {
+  if (cmd.is_implicit_end ())
+    return;
+
   indent ();
 
   os << cmd.original_command ();
*********************************************************************************

Configuration (please do not edit this section):
-----------------------------------------------

uname output:     Linux lack 2.6.27-14-generic #1 SMP Wed Apr 15 
18:59:16 UTC 2009 i686 GNU/Linux
configure opts:   '--prefix' '/opt/octave-head' '-C' '--disable-static' 
'--enable-shared' 'CXXFLAGS=-O0 -ggdb'
Fortran compiler: gfortran
FFLAGS:           -O -mieee-fp
FLIBS:            -L/usr/lib/gcc/i486-linux-gnu/4.3.2 
-L/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib -L/lib/../lib 
-L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.3.2/../../.. -lhdf5 
-lz -lgfortranbegin -lgfortran -lm
CPPFLAGS:         
INCFLAGS:         -I. -I/home/david/c/octave -I. -I./liboctave -I./src 
-I./libcruft/misc -I/home/david/c/octave 
-I/home/david/c/octave/liboctave -I/home/david/c/octave/src 
-I/home/david/c/octave/libcruft/misc
C compiler:       gcc, version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)
CFLAGS:           -g -O2
CPICFLAG:         -fPIC
C++ compiler:     g++, version 4.3.2
CXXFLAGS:         -O0 -ggdb
CXXPICFLAG:       -fPIC
LD_CXX:           g++
LDFLAGS:          
LIBFLAGS:         -L.
RLD_FLAG:         -Wl,-rpath -Wl,/opt/octave-head/lib/octave-3.1.55
BLAS_LIBS:        -llapack -lblas
FFTW_LIBS:        -lfftw3 -lfftw3f
LIBS:             -lreadline  -lncurses -ldl -lblas -lhdf5 -lz -lm
LEXLIB:           
LIBGLOB:          
SED:              /bin/sed
DEFS:

  -DPACKAGE_NAME="" -DPACKAGE_TARNAME="" -DPACKAGE_VERSION=""
  -DPACKAGE_STRING="" -DPACKAGE_BUGREPORT="" -DOCTAVE_SOURCE=1
  -D_GNU_SOURCE=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1
  -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1
  -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -D__EXTENSIONS__=1
  -D_POSIX_PTHREAD_SEMANTICS=1 -D_TANDEM_SOURCE=1 -DSEPCHAR=':'
  -DSEPCHAR_STR=":" -D__NO_MATH_INLINES=1 -DCXX_NEW_FRIEND_TEMPLATE_DECL=1
  -DCXX_ISO_COMPLIANT_LIBRARY=1 -DHAVE_X_WINDOWS=1 -DHAVE_LIBM=1
  -DHAVE_PCRE_COMPILE=1 -DHAVE_PCRE=1 -DHAVE_REGEXEC=1 -DHAVE_REGEX=1
  -DHAVE_ZLIB_H=1 -DHAVE_ZLIB=1 -DHAVE_HDF5_H=1 -DHAVE_HDF5=1
  -DHAVE_H5GGET_NUM_OBJS=1 -DHAVE_FFTW3=1 -DHAVE_GL_GL_H=1
  -DHAVE_GL_GLU_H=1 -DHAVE_FONTCONFIG=1 -DHAVE_IEEE754_DATA_FORMAT=1
  -DF77_FUNC(name,NAME)=name ## _ -DF77_FUNC_(name,NAME)=name ## _
  -DHAVE_BLAS=1 -DHAVE_GETHOSTNAME=1 -DHAVE_GETPWNAM=1 -DHAVE_DEV_T=1
  -DHAVE_INO_T=1 -DHAVE_NLINK_T=1 -DHAVE_NLINK_T=1 -DHAVE_LONG_LONG_INT=1
  -DHAVE_UNSIGNED_LONG_LONG_INT=1 -DHAVE_SIGSET_T=1 -DHAVE_SIG_ATOMIC_T=1
  -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8
  -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DHAVE_PLACEMENT_DELETE=1
  -DHAVE_DYNAMIC_AUTO_ARRAYS=1 -DHAVE_FAST_INT_OPS=1
  -DSIZEOF_LONG_DOUBLE=12 -DSTDC_HEADERS=1 -DHAVE_DIRENT_H=1
  -DTIME_WITH_SYS_TIME=1 -DHAVE_SYS_WAIT_H=1 -DHAVE_ASSERT_H=1
  -DHAVE_CURSES_H=1 -DHAVE_DLFCN_H=1 -DHAVE_FCNTL_H=1 -DHAVE_FLOAT_H=1
  -DHAVE_GRP_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_LIMITS_H=1 -DHAVE_LOCALE_H=1
  -DHAVE_MEMORY_H=1 -DHAVE_NCURSES_H=1 -DHAVE_POLL_H=1 -DHAVE_PTHREAD_H=1
  -DHAVE_PWD_H=1 -DHAVE_STDINT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1
  -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_POLL_H=1
  -DHAVE_SYS_RESOURCE_H=1 -DHAVE_SYS_SELECT_H=1 -DHAVE_SYS_STAT_H=1
  -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_TIMES_H=1 -DHAVE_SYS_TYPES_H=1
  -DHAVE_SYS_UTSNAME_H=1 -DHAVE_TERMCAP_H=1 -DHAVE_UNISTD_H=1
  -DHAVE_UTIME_H=1 -DHAVE_SSTREAM=1 -DHAVE_TERMIOS_H=1 -DHAVE_TERMIO_H=1
  -DHAVE_SGTTY_H=1 -DHAVE_GLOB_H=1 -DHAVE_FNMATCH_H=1 -DHAVE_FNMATCH=1
  -DHAVE_GLOB=1 -DHAVE_ATEXIT=1 -DHAVE_BASENAME=1 -DHAVE_BCOPY=1
  -DHAVE_BZERO=1 -DHAVE_CANONICALIZE_FILE_NAME=1 -DHAVE_CHMOD=1
  -DHAVE_DUP2=1 -DHAVE_ENDGRENT=1 -DHAVE_ENDPWENT=1 -DHAVE_EXECVP=1
  -DHAVE_EXPM1=1 -DHAVE_EXPM1F=1 -DHAVE_FCNTL=1 -DHAVE_FORK=1
  -DHAVE_FSTAT=1 -DHAVE_GETCWD=1 -DHAVE_GETEGID=1 -DHAVE_GETEUID=1
  -DHAVE_GETGID=1 -DHAVE_GETGRENT=1 -DHAVE_GETGRGID=1 -DHAVE_GETGRNAM=1
  -DHAVE_GETPGRP=1 -DHAVE_GETPID=1 -DHAVE_GETPPID=1 -DHAVE_GETPWENT=1
  -DHAVE_GETPWUID=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_GETUID=1 -DHAVE_GETWD=1
  -DHAVE_KILL=1 -DHAVE_LGAMMA=1 -DHAVE_LGAMMAF=1 -DHAVE_LGAMMA_R=1
  -DHAVE_LGAMMAF_R=1 -DHAVE_LINK=1 -DHAVE_LOCALTIME_R=1 -DHAVE_LOG1P=1
  -DHAVE_LOG1PF=1 -DHAVE_LSTAT=1 -DHAVE_MEMMOVE=1 -DHAVE_MKDIR=1
  -DHAVE_MKFIFO=1 -DHAVE_MKSTEMP=1 -DHAVE_ON_EXIT=1 -DHAVE_PIPE=1
  -DHAVE_POLL=1 -DHAVE_PUTENV=1 -DHAVE_RAISE=1 -DHAVE_READLINK=1
  -DHAVE_REALPATH=1 -DHAVE_RENAME=1 -DHAVE_RINDEX=1 -DHAVE_RMDIR=1
  -DHAVE_ROUNDL=1 -DHAVE_SELECT=1 -DHAVE_SETGRENT=1 -DHAVE_SETLOCALE=1
  -DHAVE_SETPWENT=1 -DHAVE_SETVBUF=1 -DHAVE_SIGACTION=1
  -DHAVE_SIGLONGJMP=1 -DHAVE_SIGPENDING=1 -DHAVE_SIGPROCMASK=1
  -DHAVE_SIGSUSPEND=1 -DHAVE_SNPRINTF=1 -DHAVE_STAT=1 -DHAVE_STRCASECMP=1
  -DHAVE_STRDUP=1 -DHAVE_STRERROR=1 -DHAVE_STRNCASECMP=1 -DHAVE_STRPTIME=1
  -DHAVE_STRSIGNAL=1 -DHAVE_SYMLINK=1 -DHAVE_TEMPNAM=1 -DHAVE_TGAMMAF=1
  -DHAVE_TRUNC=1 -DHAVE_UMASK=1 -DHAVE_UNAME=1 -DHAVE_UNLINK=1
  -DHAVE_USLEEP=1 -DHAVE_UTIME=1 -DHAVE_VFPRINTF=1 -DHAVE_VSPRINTF=1
  -DHAVE_VSNPRINTF=1 -DHAVE_WAITPID=1 -DHAVE_DECL_EXP2=1 -DHAVE_DECL_ROUND=1
  -DHAVE_DECL_TGAMMA=1 -DHAVE_EXP2=1 -DHAVE_ROUND=1 -DHAVE_TGAMMA=1
  -DHAVE_STRFTIME=1 -DHAVE_C99_VSNPRINTF=1 -DHAVE_LIBDL=1 -DHAVE_DLOPEN=1
  -DHAVE_DLSYM=1 -DHAVE_DLERROR=1 -DHAVE_DLCLOSE=1 -DHAVE_DLOPEN_API=1
  -DENABLE_DYNAMIC_LINKING=1 -DHAVE_TIMEVAL=1 -DHAVE_CMATH_ISNAN=1
  -DHAVE_CMATH_ISNANF=1 -DHAVE_CMATH_ISINF=1 -DHAVE_CMATH_ISINFF=1
  -DHAVE_CMATH_ISFINITE=1 -DHAVE_CMATH_ISFINITEF=1 -DHAVE_FINITE=1
  -DHAVE_ISNAN=1 -DHAVE_ISINF=1 -DHAVE_COPYSIGN=1 -DHAVE_DECL_SIGNBIT=1
  -DHAVE_ACOSH=1 -DHAVE_ACOSHF=1 -DHAVE_ASINH=1 -DHAVE_ASINHF=1
  -DHAVE_ATANH=1 -DHAVE_ATANHF=1 -DHAVE_ERF=1 -DHAVE_ERFF=1 -DHAVE_ERFC=1
  -DHAVE_ERFCF=1 -DHAVE_EXP2F=1 -DHAVE_LOG2=1 -DHAVE_LOG2F=1 -DHAVE_HYPOTF=1
  -DHAVE_STRUCT_STAT_ST_BLKSIZE=1 -DHAVE_STRUCT_STAT_ST_BLOCKS=1
  -DHAVE_STRUCT_STAT_ST_RDEV=1 -DHAVE_STRUCT_TM_TM_ZONE=1
  -DHAVE_TM_ZONE=1 -DUSE_READLINE=1 -DEXCEPTION_IN_MATH=1 -DRETSIGTYPE=void
  -DHAVE_DECL_SYS_SIGLIST=1 -DHAVE_POSIX_SIGNALS=1 -DRETSIGTYPE_IS_VOID=1
  -DHAVE_GETRUSAGE=1 -DHAVE_TIMES=1 -DYYTEXT_POINTER=1



More information about the Bug-octave mailing list