From: <pki...@us...> - 2008-11-04 22:22:29
|
Revision: 5402 http://octave.svn.sourceforge.net/octave/?rev=5402&view=rev Author: pkienzle Date: 2008-11-04 21:34:26 +0000 (Tue, 04 Nov 2008) Log Message: ----------- rename listen() -> server() and port to WinSock Modified Paths: -------------- trunk/octave-forge/main/miscellaneous/src/Makefile Added Paths: ----------- trunk/octave-forge/main/miscellaneous/src/server.cc Removed Paths: ------------- trunk/octave-forge/main/miscellaneous/src/listen.cc Modified: trunk/octave-forge/main/miscellaneous/src/Makefile =================================================================== --- trunk/octave-forge/main/miscellaneous/src/Makefile 2008-11-04 21:31:49 UTC (rev 5401) +++ trunk/octave-forge/main/miscellaneous/src/Makefile 2008-11-04 21:34:26 UTC (rev 5402) @@ -4,12 +4,6 @@ TERM_LIB=-ltermcap endif -ifdef HAVE_FORK - LISTEN=listen.oct -else - LISTEN= -endif - TARGETS=waitbar.oct $(LISTEN) xmlread.oct hex2num.cc \ csvexplode.oct csv2cell.oct csvconcat.oct cell2csv.oct @@ -18,11 +12,11 @@ waitbar.oct: waitbar.cc $(MKOCTFILE) $(MISCDEFS) waitbar.cc $(TERM_LIB) -listen.oct: listen.o listencanfork.o stringmatch.o - $(MKOCTFILE) listen.o listencanfork.o stringmatch.o +server.oct: server.o listencanfork.o stringmatch.o + $(MKOCTFILE) server.o listencanfork.o stringmatch.o -listen.o: listen.cc - $(MKOCTFILE) -c $(MISCDEFS) listen.cc +server.o: server.cc + $(MKOCTFILE) -c $(MISCDEFS) server.cc listencanfork.o: listencanfork.c $(MKOCTFILE) -c listencanfork.c Deleted: trunk/octave-forge/main/miscellaneous/src/listen.cc =================================================================== --- trunk/octave-forge/main/miscellaneous/src/listen.cc 2008-11-04 21:31:49 UTC (rev 5401) +++ trunk/octave-forge/main/miscellaneous/src/listen.cc 2008-11-04 21:34:26 UTC (rev 5402) @@ -1,734 +0,0 @@ -#define STATUS(x) do { if (debug) std::cout << x << std::endl << std::flush; } while (0) -#define USE_DEFUN_INTERNAL 1 -// Temporary hack (I hope). For some reason the interpreter -// is not finding the send/senderror commands, so I install -// them by hand.. - -#include <iomanip> - -#include <cstdio> -#include <cctype> -#include <cstdlib> -#include <unistd.h> -//#include <stdint.h> -#include <cerrno> -// #include <string.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/wait.h> -#include <signal.h> - -#include <octave/oct.h> -#include <octave/parse.h> -#include <octave/variables.h> -#if 0 -#include <octave/unwind-prot.h> -#endif -#include <octave/oct-syscalls.h> -#include <octave/oct-time.h> -#include <octave/lo-mappers.h> -#include <octave/symtab.h> - -static bool debug = false; -static char* context = NULL; - -static double timestamp = 0.0; -inline void tic(void) { timestamp = octave_time().double_value(); } -inline double toc(void) {return ceil(-1e6*(timestamp-octave_time().double_value()));} - -// XXX FIXME XXX --- surely this is part of the standard library? -void -lowercase (std::string& s) -{ - for (std::string::iterator i=s.begin(); i != s.end(); i++) *i = tolower(*i); -} - -#if 0 -octave_value -get_builtin_value (const std::string& nm) -{ - octave_value retval; - - symbol_record *sr = fbi_sym_tab->lookup (nm); - - if (sr) - { - octave_value sr_def = sr->def (); - - if (sr_def.is_undefined ()) - error ("get_builtin_value: undefined symbol `%s'", nm.c_str ()); - else - retval = sr_def; - } - else - error ("get_builtin_value: unknown symbol `$s'", nm.c_str ()); - - return retval; -} -#endif - -// XXX FIXME XXX autoconf stuff -#if 0 && defined(_sgi) -typedef int socklen_t; -#endif - -static void -sigchld_handler(int /* sig */) -{ - int status; - /* Reap all childrens */ - STATUS("reaping all children"); - while (waitpid(-1, &status, WNOHANG) > 0) - ; - STATUS("done reaping children"); -} - -/* Posix signal handling, based on the example from the - * Unix Programming FAQ - * Copyright (C) 2000 Andrew Gierth - */ -static void sigchld_setup(void) -{ - struct sigaction act; - - /* Assign sig_chld as our SIGCHLD handler */ - act.sa_handler = sigchld_handler; - - /* We don't want to block any other signals in this example */ - sigemptyset(&act.sa_mask); - - /* - * We're only interested in children that have terminated, not ones - * which have been stopped (eg user pressing control-Z at terminal) - */ - act.sa_flags = SA_NOCLDSTOP; - - /* - * Make these values effective. If we were writing a real - * application, we would probably save the old value instead of - * passing NULL. - */ - if (sigaction(SIGCHLD, &act, NULL) < 0) - error("listen could not set SIGCHLD"); -} - - -#if defined(__CYGWIN__) - -// Don't daemonize on cygwin just yet. -inline void daemonize(void) {} - -#else - -static RETSIGTYPE -sigterm_handler(int /* sig */) -{ - exit(0); -} - - -static void -daemonize(void) -{ - if (fork()) exit(0); - std::cout << "Octave pid: " << octave_syscalls::getpid() << std::endl; - signal(SIGTERM,sigterm_handler); - signal(SIGQUIT,sigterm_handler); - - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); -} - -#endif - - - -static octave_value get_octave_value(char *name) -{ - octave_value def; - - // Copy variable from octave -#ifdef HAVE_OCTAVE_30 - symbol_record *sr = top_level_sym_tab->lookup (name); - if (sr) def = sr->def(); -#else - def = symbol_table::varref (std::string (name), symbol_table::top_scope ()); -#endif - - return def; -} - - -static void channel_error (const int channel, const char *str) -{ - STATUS("sending error !!!e (" << strlen(str) << ") " << str); - - uint32_t len = strlen(str); - write(channel,"!!!e",4); - uint32_t t = htonl(len); write(channel,&t,4); - write(channel,str,len); -} - -static bool reads (const int channel, void * buf, int n) -{ - // STATUS("entering reads loop with size " << n); tic(); - while (1) { - int chunk = read(channel, buf, n); - if (chunk == 0) STATUS("read socket returned 0"); - if (chunk < 0) STATUS("read socket: " << strerror(errno)); - if (chunk <= 0) return false; - n -= chunk; - // if (n == 0) STATUS("done reads loop after " << toc() << "us"); - if (n == 0) return true; - // STATUS("reading remaining " << n << " characters"); - buf = (void *)((char *)buf + chunk); - } -} - -static bool writes (const int channel, const void * buf, int n) -{ - // STATUS("entering writes loop"); - while (1) { - int chunk = write(channel, buf, n); - if (chunk == 0) STATUS("write socket returned 0"); - if (chunk < 0) STATUS("write socket: " << strerror(errno)); - if (chunk <= 0) return false; - n -= chunk; - // if (n == 0) STATUS("done writes loop"); - if (n == 0) return true; - buf = (void *)((char *)buf + chunk); - } -} - -static void -process_commands(int channel) -{ - // XXX FIXME XXX check read/write return values - assert(sizeof(uint32_t) == 4); - char command[5]; - char def_context[16536]; - bool ok; - STATUS("waiting for command"); - - // XXX FIXME XXX do we need to specify the context size? - // int bufsize=sizeof(def_context); - // socklen_t ol; - // ol=sizeof(bufsize); - // setsockopt(channel,SOL_SOCKET,SO_SNDBUF,&bufsize,ol); - // setsockopt(channel,SOL_SOCKET,SO_RCVBUF,&bufsize,ol); - - // XXX FIXME XXX prepare to capture long jumps, because if - // we dont, then errors in octave might escape to the prompt - - command[4] = '\0'; - if (debug) tic(); - while (reads(channel, &command, 4)) { - // XXX FIXME XXX do whatever is require to check if function files - // have changed; do we really want to do this for _every_ command? - // Maybe we need a 'reload' command. - STATUS("received command " << command << " after " << toc() << "us"); - - // Check for magic command code - if (command[0] != '!' || command[1] != '!' || command[2] != '!') { - STATUS("communication error: closing connection"); - break; - } - - // Get command length - if (debug) tic(); // time the read - uint32_t len; - if (!reads(channel, &len, 4)) break; - len = ntohl(len); - // STATUS("read 4 byte command length in " << toc() << "us"); - - // Read the command context, allocating a new one if the default - // is too small. - if (len > (signed)sizeof(def_context)-1) { - // XXX FIXME XXX use octave allocators - // XXX FIXME XXX unwind_protect - context= new char[len+1]; - if (context== NULL) { - // Requested command is too large --- skip to the next command - // XXX FIXME XXX maybe we want to kill the connection instead? - channel_error(channel,"out of memory"); - ok = true; - STATUS("skip big command loop"); - while (ok && len > (signed)sizeof(def_context)) { - ok = reads(channel, def_context, sizeof(def_context)); - len -= sizeof(def_context); - } - STATUS("done skip big command loop"); - if (!ok) break; - ok = reads(channel, def_context, sizeof(def_context)); - if (!ok) break; - continue; - } - } else { - context = def_context; - } - // if (debug) tic(); - ok = reads(channel, context, len); - context[len] = '\0'; - STATUS("read " << len << " byte command in " << toc() << "us"); - - // Process the command - if (ok) switch (command[3]) { - case 'm': // send the named matrix - { - // XXX FIXME XXX this can be removed: app can do send(name,value) - STATUS("sending " << context); - uint32_t t; - - // read the matrix contents - octave_value def = get_octave_value(context); - if(!def.is_defined() || !def.is_real_matrix()) - channel_error(channel,"not a matrix"); - Matrix m = def.matrix_value(); - - // write the matrix transfer header - ok = writes(channel,"!!!m",4); // matrix message - t = htonl(12 + sizeof(double)*m.rows()*m.columns()); - if (ok) ok = writes(channel,&t,4); // length of message - t = htonl(m.rows()); - if (ok) ok = writes(channel,&t,4); // rows - t = htonl(m.columns()); - if (ok) ok = writes(channel,&t,4); // columns - t = htonl(len); - if (ok) ok = writes(channel, &t, 4); // name length - if (ok) ok = writes(channel,context,len); // name - - // write the matrix contents - const double *v = m.data(); // data - if (ok) ok = writes(channel,v,sizeof(double)*m.rows()*m.columns()); - if (ok) - STATUS("sent " << m.rows()*m.columns()); - else - STATUS("failed " << m.rows()*m.columns()); - } - break; - - case 'x': // silently execute the command - { - if (debug) - { - if (len > 500) - { - // XXX FIXME XXX can we limit the maximum output width for a - // string? The setprecision() io manipulator doesn't do it. - // In the meantime, a hack ... - char t = context[400]; context[400] = '\0'; - STATUS("evaluating (" << len << ") " - << context << std::endl - << "..." << std::endl - << context+len-100); - context[400] = t; - } - else - { - STATUS("evaluating (" << len << ") " << context); - } - } - - if (debug) tic(); -#if 1 - octave_value_list evalargs; - evalargs(1) = "senderror(lasterr);"; - evalargs(0) = context; - octave_value_list fret = feval("eval",evalargs,0); -#else - evalargs(0) = octave_value(0.); -#endif - STATUS("done command"); - } - STATUS("free evalargs"); - break; - - case 'c': // execute the command and capture stdin/stdout - STATUS("capture command not yet implemented"); - break; - - default: - STATUS("ignoring command " << command); - break; - } - - if (context != def_context) delete[] context; - STATUS("done " << command); - if (!ok) break; - if (debug) tic(); - } -} - - -int channel = -1; - -#if USE_DEFUN_INTERNAL -DEFUN_INTERNAL(senderror,args,,false,"\ -Send the given error message across the socket. The error context\n\ -is taken to be the last command received from the socket.") -#else -DEFUN_DLD(senderror,args,,"\ -Send the given error message across the socket. The error context\n\ -is taken to be the last command received from the socket.") -#endif -{ - std::string str; - const int nargin = args.length(); - if (nargin != 1) str="senderror not called with error"; - else str = args(0).string_value(); - - // provide a context for the error (but not too much!) - str += "when evaluating:\n"; - if (strlen(context) > 100) - { - char t=context[100]; - context[100] = '\0'; - str+=context; - context[100]=t; - } - else - str += context; - - STATUS("error is " << str); - channel_error(channel,str.c_str()); - return octave_value_list(); -} - -#if USE_DEFUN_INTERNAL -DEFUN_INTERNAL(send,args,,false,"\ -send(str)\n\ - Send a command on the current connection\n\ -send(name,value)\n\ - Send a binary value with the given name on the current connection\n\ -") -#else -DEFUN_DLD(send,args,,"\ -send(str)\n\ - Send a command on the current connection\n\ -send(name,value)\n\ - Send a binary value with the given name on the current connection\n\ -") -#endif -{ - bool ok; - uint32_t t; - octave_value_list ret; - int nargin = args.length(); - if (nargin < 1 || nargin > 2) - { - print_usage (); - return ret; - } - - if (channel < 0) { - error("Not presently listening on a port"); - return ret; - } - - std::string cmd(args(0).string_value()); - if (error_state) return ret; - - // XXX FIXME XXX perhaps process the panalopy of types? - if (nargin > 1) { - STATUS("sending !!!x(" << cmd.length() << ") " << cmd.c_str()); - - octave_value def = args(1); - if (args(1).is_string()) { - // Grab the string value from args(1). - // Can't use args(1).string_value() because that trims trailing \0 - charMatrix m(args(1).char_matrix_value()); - std::string s(m.row_as_string(0,false,true)); - ok = writes(channel,"!!!s",4); // string message - t = htonl(8 + cmd.length() + s.length()); - if (ok) ok = writes(channel,&t,4); // length of message - t = htonl(s.length()); - if (ok) ok = writes(channel, &t, 4); // string length - t = htonl(cmd.length()); - if (ok) ok = writes(channel, &t, 4); // name length - if (cmd.length() && ok) - ok = writes(channel, cmd.c_str(), cmd.length()); // name - if (s.length() && ok) - ok = writes(channel, s.c_str(), s.length()); // string - STATUS("sent string(" << s.length() << ")"); - } else if (args(1).is_real_type()) { - Matrix m(args(1).matrix_value()); - - // write the matrix transfer header - ok = writes(channel,"!!!m",4); // matrix message - t = htonl(12 + cmd.length() + sizeof(double)*m.rows()*m.columns()); - if (ok) ok = writes(channel,&t,4); // length of message - t = htonl(m.rows()); - if (ok) ok = writes(channel,&t,4); // rows - t = htonl(m.columns()); - if (ok) ok = writes(channel,&t,4); // columns - t = htonl(cmd.length()); - if (ok) ok = writes(channel, &t, 4); // name length - if (ok) ok = writes(channel, cmd.c_str(), cmd.length()); // name - - // write the matrix contents - const double *v = m.data(); // data - if (m.rows()*m.columns() && ok) - ok = writes(channel,v,sizeof(double)*m.rows()*m.columns()); - STATUS("sent matrix(" << m.rows() << "x" << m.columns() << ")"); - } else { - ok = false; - error("send expected name and matrix or string value"); - } - if (!ok) error("send could not write to channel"); - } else { - // STATUS("start writing at "<<toc()<<"us"); - ok = writes(channel, "!!!x", 4); - t = htonl(cmd.length()); writes(channel, &t, 4); - if (ok) ok = writes(channel, cmd.c_str(), cmd.length()); - if (!ok) error("send could not write to channel"); - // STATUS("stop writing at "<<toc()<<"us"); - } - - return ret; -} - -extern "C" int listencanfork(void); -extern "C" int StringCaseMatch(const char* s, const char* p, int nocase); - -bool ishostglob(const std::string& s) -{ - for (unsigned int i=0; i < s.length(); i++) { - if (! ( isdigit(s[i]) || s[i]=='*' || s[i]=='-' - || s[i]=='.' || s[i]=='[' || s[i]==']')) return false; - } - return true; -} - -bool anyhostglob(const string_vector& hostlist, const char* host) -{ - for (int j=0; j < hostlist.length(); j++) { - if (StringCaseMatch(host, hostlist[j].c_str(), 0)) return true; - } - return false; -} - -// Known bug: functions which pass or return structures use a -// different ABI for gcc and native compilers on some architectures. -// Whether this is a bug depends on the structure length. SGI's 64-bit -// architecture makes this a problem for inet_ntoa. -#if defined(__GNUC__) && defined(_sgi) -#define BROKEN_INET_NTOA -#endif - -#ifdef BROKEN_INET_NTOA - -/************************************************* -* Replacement for broken inet_ntoa() * -*************************************************/ - - -/* On IRIX systems, gcc uses a different structure passing convention to the -native libraries. This causes inet_ntoa() to always yield 0.0.0.0 or -255.255.255.255. To get round this, we provide a private version of the -function here. It is used only if USE_INET_NTOA_FIX is set, which should -happen -only when gcc is in use on an IRIX system. Code send to me by J.T. Breitner, -with these comments: - - - code by Stuart Levy - as seen in comp.sys.sgi.admin - - -Arguments: sa an in_addr structure -Returns: pointer to static text string -*/ - - -char * -inet_ntoa(struct in_addr sa) -{ -static char addr[20]; -sprintf(addr, "%d.%d.%d.%d", - (US &sa.s_addr)[0], - (US &sa.s_addr)[1], - (US &sa.s_addr)[2], - (US &sa.s_addr)[3]); - return addr; -} - -#endif /* BROKEN_INET_NTOA */ - - -DEFUN_DLD(listen,args,,"\ -listen(port,host,host,...)\n\ - Listen for connections on the given port. Normally only accepts\n\ - connections from localhost (127.0.0.1), but you can specify any\n\ - dot-separated host name globs. E.g., '128.2.20.*' or '128.2.2[012].*'\n\ - Use '?' for '[0123456789]'. Use '*.*.*.*' for any host.\n\ -listen(...,'debug'|'nodebug')\n\ - If debug, echo all commands sent across the connection. If nodebug,\n\ - detach the process and don't echo anything. You will need to use\n\ - kill directly to end the process. Nodebug is the default.\n\ -listen(...,'fork'|'nofork')\n\ - If fork, start new server for each connection. If nofork, only allow\n\ - one connection at a time. Fork is the default (depending on system).\n\ -listen(...,'loopback')\n\ - Use loopback address 127.0.0.1 rather than 0.0.0.0.\n\ -") -{ -#if USE_DEFUN_INTERNAL - install_builtin_function (Fsend, "send", "builtin send doc", false); - install_builtin_function (Fsenderror, - "senderror", "builtin senderror doc", false); -#endif - -#if defined(__CYGWIN__) - bool canfork = listencanfork(); -#else - bool canfork = true; -#endif - - octave_value_list ret; - int nargin = args.length(); - if (nargin < 1) - { - print_usage (); - return ret; - } - - int port = args(0).int_value(); - if (error_state) return ret; - - debug = false; - uint32_t inaddr = INADDR_ANY; - - string_vector hostlist; - hostlist.append(std::string("127.0.0.1")); - for (int k = 1; k < nargin; k++) { - std::string lastarg(args(k).string_value()); - if (error_state) return ret; - lowercase(lastarg); - if (lastarg == "debug") { - debug = true; - } else if (lastarg == "nodebug") { - debug = false; - } else if (lastarg == "fork") { - canfork = true; - } else if (lastarg == "nofork") { - canfork = false; - } else if (lastarg == "loopback") { - inaddr = INADDR_LOOPBACK; - } else if (ishostglob(lastarg)) { - hostlist.append(lastarg); - } else { - print_usage (); - } - } - - int sockfd; // listen on sockfd, new connection channel - struct sockaddr_in my_addr; // my address information - struct sockaddr_in their_addr; // connector's address information - socklen_t sin_size; - int yes=1; - - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - perror("socket"); - return ret; - } - - if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) == -1) { - perror("setsockopt"); - return ret; - } - - my_addr.sin_family = AF_INET; // host byte order - my_addr.sin_port = htons(port); // short, network byte order - my_addr.sin_addr.s_addr = htonl(inaddr); // automatically fill with my IP - memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct - - if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) - == -1) { - perror("bind"); - close(sockfd); - return ret; - } - - /* listen for connections (allowing one pending connection) */ - if (listen(sockfd, canfork?1:0) == -1) { - perror("listen"); - close(sockfd); - return ret; - } - -#if 0 - unwind_protect::begin_frame("Flisten"); - unwind_protect_bool (buffer_error_messages); - buffer_error_messages = true; -#endif - - sigchld_setup(); - - if (!debug && canfork) daemonize(); - - // XXX FIXME XXX want a 'sandbox' option which disables fopen, cd, pwd, - // system, popen ... Or maybe just an initial script to run for each - // connection, plus a separate command to disable specific functions. - STATUS("listening on port " << port); - while(1) { // main accept() loop - sin_size = sizeof(struct sockaddr_in); - STATUS("trying to accept"); - if ((channel = accept(sockfd, (struct sockaddr *)&their_addr, - &sin_size)) == -1) { - // XXX FIXME XXX - // Linux is returning "Interrupted system call" when the - // child terminates. Until I figure out why, I can't use - // accept errors as a basis for breaking out of the listen - // loop, so instead print the octave PID so that I can kill - // it from another terminal. - STATUS("failed to accept" << std::endl - << "Octave pid: " << octave_syscalls::getpid() ); - perror("accept"); -#if defined(_sgi) - break; -#else - continue; -#endif - } - STATUS("connected"); - - /* Simulate inet_ntoa */ - const char *them = inet_ntoa(their_addr.sin_addr); - STATUS("server: got connection from " << them); - - if (anyhostglob(hostlist,them)) { - if (canfork) { - int pid = fork(); - - if (pid == -1) { - perror("fork "); - break; - } else if (pid == 0) { - close(sockfd); // child doesn't need listener - signal(SIGCHLD,SIG_DFL); // child doesn't need SIGCHLD signal - process_commands(channel); - STATUS("child is exitting"); - exit(0); - } - } else { - process_commands(channel); - STATUS("server: connection closed"); - } - } else { - STATUS("server: connection refused."); - } - - close(channel); - channel = -1; - } - - STATUS("could not read commands; returning"); - close(sockfd); -#if 0 - unwind_protect::run_frame("Flisten"); -#endif - return ret; -} Copied: trunk/octave-forge/main/miscellaneous/src/server.cc (from rev 5383, trunk/octave-forge/main/miscellaneous/src/listen.cc) =================================================================== --- trunk/octave-forge/main/miscellaneous/src/server.cc (rev 0) +++ trunk/octave-forge/main/miscellaneous/src/server.cc 2008-11-04 21:34:26 UTC (rev 5402) @@ -0,0 +1,805 @@ +#define STATUS(x) do { if (debug) std::cout << x << std::endl << std::flush; } while (0) +#define USE_DEFUN_INTERNAL 1 +// Temporary hack (I hope). For some reason the interpreter +// is not finding the send/senderror commands, so I install +// them by hand.. + +#include <iomanip> + +#include <cstdio> +#include <cctype> +#include <cstdlib> +//#include <unistd.h> +//#include <stdint.h> +#include <cerrno> +// #include <string.h> +#include <sys/types.h> + +#if (defined(_WIN32)||defined(_WIN64)) && !defined(__CYGWIN__) +# define USE_WINSOCK +# define CAN_FORK false +# include <winsock.h> +# include <io.h> + typedef int socklen_t; +#else +# define HAVE_FORK 1 +# define USE_SIGNALS +# if defined(__CYGWIN__) +# define CAN_FORK listencanfork() +# else +# define USE_DAEMONIZE +# define CAN_FORK true +# endif +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <sys/wait.h> +# include <signal.h> +# define closesocket close +#endif + + +#include <octave/oct.h> +#include <octave/parse.h> +#include <octave/variables.h> +#if 0 +#include <octave/unwind-prot.h> +#endif +#include <octave/oct-syscalls.h> +#include <octave/oct-time.h> +#include <octave/lo-mappers.h> +#include <octave/symtab.h> + +static bool debug = false; +static char* context = NULL; + +static double timestamp = 0.0; +inline void tic(void) { timestamp = octave_time().double_value(); } +inline double toc(void) {return ceil(-1e6*(timestamp-octave_time().double_value()));} + +// XXX FIXME XXX --- surely this is part of the standard library? +void +lowercase (std::string& s) +{ + for (std::string::iterator i=s.begin(); i != s.end(); i++) *i = tolower(*i); +} + +#if 0 +octave_value +get_builtin_value (const std::string& nm) +{ + octave_value retval; + + symbol_record *sr = fbi_sym_tab->lookup (nm); + + if (sr) + { + octave_value sr_def = sr->def (); + + if (sr_def.is_undefined ()) + error ("get_builtin_value: undefined symbol `%s'", nm.c_str ()); + else + retval = sr_def; + } + else + error ("get_builtin_value: unknown symbol `$s'", nm.c_str ()); + + return retval; +} +#endif + +#ifdef USE_WINSOCK + bool init_sockets() + { + + WSADATA wsaData; + WORD version; + int error; + + version = MAKEWORD( 2, 0 ); + + error = WSAStartup( version, &wsaData ); + + /* check for error */ + if ( error != 0 ) + { + /* error occured */ + return false; + } + + /* check for correct version */ + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 0 ) + { + /* incorrect WinSock version */ + WSACleanup(); + return false; + } + return true; + } + + inline void end_sockets() { WSACleanup(); } + inline int socket_errno() { return WSAGetLastError(); } +#else // !USE_WINSOCK +# include <cerrno> + inline bool init_sockets() { return true; } + inline void end_sockets() { } + inline int socket_errno() { return errno; } +#endif // !USE_WINSOCK +inline void socket_error(const char *context) +{ + int err = socket_errno(); + char errno_str[15]; + sprintf(" %d: ",errno_str); + std::string msg = std::string(context)+errno_str+strerror(err); + error(msg.c_str()); +} + +#ifdef USE_SIGNALS +static void +sigchld_handler(int /* sig */) +{ + int status; + /* Reap all childrens */ + STATUS("reaping all children"); + while (waitpid(-1, &status, WNOHANG) > 0) + ; + STATUS("done reaping children"); +} + +/* Posix signal handling, based on the example from the + * Unix Programming FAQ + * Copyright (C) 2000 Andrew Gierth + */ +static void sigchld_setup(void) +{ + struct sigaction act; + + /* Assign sig_chld as our SIGCHLD handler */ + act.sa_handler = sigchld_handler; + + /* We don't want to block any other signals in this example */ + sigemptyset(&act.sa_mask); + + /* + * We're only interested in children that have terminated, not ones + * which have been stopped (eg user pressing control-Z at terminal) + */ + act.sa_flags = SA_NOCLDSTOP; + + /* + * Make these values effective. If we were writing a real + * application, we would probably save the old value instead of + * passing NULL. + */ + if (sigaction(SIGCHLD, &act, NULL) < 0) + error("listen could not set SIGCHLD"); +} +#else +inline void sigchld_setup(void) { } +#endif + + +#ifdef USE_DAEMONIZE + +static RETSIGTYPE +sigterm_handler(int /* sig */) +{ + exit(0); +} + +static void +daemonize(void) +{ + if (fork()) exit(0); + std::cout << "Octave pid: " << octave_syscalls::getpid() << std::endl; + signal(SIGTERM,sigterm_handler); + signal(SIGQUIT,sigterm_handler); + + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); +} + +#else +// Don't daemonize on cygwin just yet. +inline void daemonize(void) {} + +#endif // !DAEMONIZE + + + +static octave_value get_octave_value(char *name) +{ + octave_value def; + + // Copy variable from octave +#ifdef HAVE_OCTAVE_30 + symbol_record *sr = top_level_sym_tab->lookup (name); + if (sr) def = sr->def(); +#else + def = symbol_tabe::varref (std::string (name), symbol_table::top_scope ()); +#endif + + return def; +} + + +static void channel_error (const int channel, const char *str) +{ + STATUS("sending error !!!e (" << strlen(str) << ") " << str); + + uint32_t len = strlen(str); + send(channel,"!!!e",4,0); + uint32_t t = htonl(len); send(channel,(const char *)&t,4,0); + send(channel,str,len,0); +} + +static bool reads (const int channel, void * buf, int n) +{ + // STATUS("entering reads loop with size " << n); tic(); + while (1) { + int chunk = recv(channel, (char *)buf, n, 0); + if (chunk == 0) STATUS("read socket returned 0"); + if (chunk < 0) STATUS("read socket error " << socket_errno()); + if (chunk <= 0) return false; + n -= chunk; + // if (n == 0) STATUS("done reads loop after " << toc() << "us"); + if (n == 0) return true; + // STATUS("reading remaining " << n << " characters"); + buf = (void *)((char *)buf + chunk); + } +} + +static bool writes (const int channel, const void * buf, int n) +{ + // STATUS("entering writes loop"); + while (1) { + int chunk = send(channel, (const char *)buf, n, 0); + if (chunk == 0) STATUS("write socket returned 0"); + if (chunk < 0) STATUS("write socket: " << strerror(errno)); + if (chunk <= 0) return false; + n -= chunk; + // if (n == 0) STATUS("done writes loop"); + if (n == 0) return true; + buf = (void *)((char *)buf + chunk); + } +} + +static void +process_commands(int channel) +{ + // XXX FIXME XXX check read/write return values + assert(sizeof(uint32_t) == 4); + char command[5]; + char def_context[16536]; + bool ok; + STATUS("waiting for command"); + + // XXX FIXME XXX do we need to specify the context size? + // int bufsize=sizeof(def_context); + // socklen_t ol; + // ol=sizeof(bufsize); + // setsockopt(channel,SOL_SOCKET,SO_SNDBUF,&bufsize,ol); + // setsockopt(channel,SOL_SOCKET,SO_RCVBUF,&bufsize,ol); + + // XXX FIXME XXX prepare to capture long jumps, because if + // we dont, then errors in octave might escape to the prompt + + command[4] = '\0'; + if (debug) tic(); + while (reads(channel, &command, 4)) { + // XXX FIXME XXX do whatever is require to check if function files + // have changed; do we really want to do this for _every_ command? + // Maybe we need a 'reload' command. + STATUS("received command " << command << " after " << toc() << "us"); + + // Check for magic command code + if (command[0] != '!' || command[1] != '!' || command[2] != '!') { + STATUS("communication error: closing connection"); + break; + } + + // Get command length + if (debug) tic(); // time the read + uint32_t len; + if (!reads(channel, &len, 4)) break; + len = ntohl(len); + // STATUS("read 4 byte command length in " << toc() << "us"); + + // Read the command context, allocating a new one if the default + // is too small. + if (len > (signed)sizeof(def_context)-1) { + // XXX FIXME XXX use octave allocators + // XXX FIXME XXX unwind_protect + context= new char[len+1]; + if (context== NULL) { + // Requested command is too large --- skip to the next command + // XXX FIXME XXX maybe we want to kill the connection instead? + channel_error(channel,"out of memory"); + ok = true; + STATUS("skip big command loop"); + while (ok && len > (signed)sizeof(def_context)) { + ok = reads(channel, def_context, sizeof(def_context)); + len -= sizeof(def_context); + } + STATUS("done skip big command loop"); + if (!ok) break; + ok = reads(channel, def_context, sizeof(def_context)); + if (!ok) break; + continue; + } + } else { + context = def_context; + } + // if (debug) tic(); + ok = reads(channel, context, len); + context[len] = '\0'; + STATUS("read " << len << " byte command in " << toc() << "us"); + + // Process the command + if (ok) switch (command[3]) { + case 'm': // send the named matrix + { + // XXX FIXME XXX this can be removed: app can do send(name,value) + STATUS("sending " << context); + uint32_t t; + + // read the matrix contents + octave_value def = get_octave_value(context); + if(!def.is_defined() || !def.is_real_matrix()) + channel_error(channel,"not a matrix"); + Matrix m = def.matrix_value(); + + // write the matrix transfer header + ok = writes(channel,"!!!m",4); // matrix message + t = htonl(12 + sizeof(double)*m.rows()*m.columns()); + if (ok) ok = writes(channel,&t,4); // length of message + t = htonl(m.rows()); + if (ok) ok = writes(channel,&t,4); // rows + t = htonl(m.columns()); + if (ok) ok = writes(channel,&t,4); // columns + t = htonl(len); + if (ok) ok = writes(channel, &t, 4); // name length + if (ok) ok = writes(channel,context,len); // name + + // write the matrix contents + const double *v = m.data(); // data + if (ok) ok = writes(channel,v,sizeof(double)*m.rows()*m.columns()); + if (ok) + STATUS("sent " << m.rows()*m.columns()); + else + STATUS("failed " << m.rows()*m.columns()); + } + break; + + case 'x': // silently execute the command + { + if (debug) + { + if (len > 500) + { + // XXX FIXME XXX can we limit the maximum output width for a + // string? The setprecision() io manipulator doesn't do it. + // In the meantime, a hack ... + char t = context[400]; context[400] = '\0'; + STATUS("evaluating (" << len << ") " + << context << std::endl + << "..." << std::endl + << context+len-100); + context[400] = t; + } + else + { + STATUS("evaluating (" << len << ") " << context); + } + } + + if (debug) tic(); +#if 1 + octave_value_list evalargs; + evalargs(1) = "senderror(lasterr);"; + evalargs(0) = context; + octave_value_list fret = feval("eval",evalargs,0); +#else + evalargs(0) = octave_value(0.); +#endif + STATUS("done command"); + } + STATUS("free evalargs"); + break; + + case 'c': // execute the command and capture stdin/stdout + STATUS("capture command not yet implemented"); + break; + + default: + STATUS("ignoring command " << command); + break; + } + + if (context != def_context) delete[] context; + STATUS("done " << command); + if (!ok) break; + if (debug) tic(); + } +} + + +int channel = -1; + +#if USE_DEFUN_INTERNAL +DEFUN_INTERNAL(senderror,args,,false,"\ +Send the given error message across the socket. The error context\n\ +is taken to be the last command received from the socket.") +#else +DEFUN_DLD(senderror,args,,"\ +Send the given error message across the socket. The error context\n\ +is taken to be the last command received from the socket.") +#endif +{ + std::string str; + const int nargin = args.length(); + if (nargin != 1) str="senderror not called with error"; + else str = args(0).string_value(); + + // provide a context for the error (but not too much!) + str += "when evaluating:\n"; + if (strlen(context) > 100) + { + char t=context[100]; + context[100] = '\0'; + str+=context; + context[100]=t; + } + else + str += context; + + STATUS("error is " << str); + channel_error(channel,str.c_str()); + return octave_value_list(); +} + +#if USE_DEFUN_INTERNAL +DEFUN_INTERNAL(send,args,,false,"\ +send(str)\n\ + Send a command on the current connection\n\ +send(name,value)\n\ + Send a binary value with the given name on the current connection\n\ +") +#else +DEFUN_DLD(send,args,,"\ +send(str)\n\ + Send a command on the current connection\n\ +send(name,value)\n\ + Send a binary value with the given name on the current connection\n\ +") +#endif +{ + bool ok; + uint32_t t; + octave_value_list ret; + int nargin = args.length(); + if (nargin < 1 || nargin > 2) + { + print_usage (); + return ret; + } + + if (channel < 0) { + error("Not presently listening on a port"); + return ret; + } + + std::string cmd(args(0).string_value()); + if (error_state) return ret; + + // XXX FIXME XXX perhaps process the panalopy of types? + if (nargin > 1) { + STATUS("sending !!!x(" << cmd.length() << ") " << cmd.c_str()); + + octave_value def = args(1); + if (args(1).is_string()) { + // Grab the string value from args(1). + // Can't use args(1).string_value() because that trims trailing \0 + charMatrix m(args(1).char_matrix_value()); + std::string s(m.row_as_string(0,false,true)); + ok = writes(channel,"!!!s",4); // string message + t = htonl(8 + cmd.length() + s.length()); + if (ok) ok = writes(channel,&t,4); // length of message + t = htonl(s.length()); + if (ok) ok = writes(channel, &t, 4); // string length + t = htonl(cmd.length()); + if (ok) ok = writes(channel, &t, 4); // name length + if (cmd.length() && ok) + ok = writes(channel, cmd.c_str(), cmd.length()); // name + if (s.length() && ok) + ok = writes(channel, s.c_str(), s.length()); // string + STATUS("sent string(" << s.length() << ")"); + } else if (args(1).is_real_type()) { + Matrix m(args(1).matrix_value()); + + // write the matrix transfer header + ok = writes(channel,"!!!m",4); // matrix message + t = htonl(12 + cmd.length() + sizeof(double)*m.rows()*m.columns()); + if (ok) ok = writes(channel,&t,4); // length of message + t = htonl(m.rows()); + if (ok) ok = writes(channel,&t,4); // rows + t = htonl(m.columns()); + if (ok) ok = writes(channel,&t,4); // columns + t = htonl(cmd.length()); + if (ok) ok = writes(channel, &t, 4); // name length + if (ok) ok = writes(channel, cmd.c_str(), cmd.length()); // name + + // write the matrix contents + const double *v = m.data(); // data + if (m.rows()*m.columns() && ok) + ok = writes(channel,v,sizeof(double)*m.rows()*m.columns()); + STATUS("sent matrix(" << m.rows() << "x" << m.columns() << ")"); + } else { + ok = false; + error("send expected name and matrix or string value"); + } + if (!ok) error("send could not write to channel"); + } else { + // STATUS("start writing at "<<toc()<<"us"); + ok = writes(channel, "!!!x", 4); + t = htonl(cmd.length()); writes(channel, &t, 4); + if (ok) ok = writes(channel, cmd.c_str(), cmd.length()); + if (!ok) error("send could not write to channel"); + // STATUS("stop writing at "<<toc()<<"us"); + } + + return ret; +} + +extern "C" int listencanfork(void); +extern "C" int StringCaseMatch(const char* s, const char* p, int nocase); + +bool ishostglob(const std::string& s) +{ + for (unsigned int i=0; i < s.length(); i++) { + if (! ( isdigit(s[i]) || s[i]=='*' || s[i]=='-' + || s[i]=='.' || s[i]=='[' || s[i]==']')) return false; + } + return true; +} + +bool anyhostglob(const string_vector& hostlist, const char* host) +{ + for (int j=0; j < hostlist.length(); j++) { + if (StringCaseMatch(host, hostlist[j].c_str(), 0)) return true; + } + return false; +} + +// Known bug: functions which pass or return structures use a +// different ABI for gcc and native compilers on some architectures. +// Whether this is a bug depends on the structure length. SGI's 64-bit +// architecture makes this a problem for inet_ntoa. +#if defined(__GNUC__) && defined(_sgi) +#define BROKEN_INET_NTOA +#endif + +#ifdef BROKEN_INET_NTOA + +/************************************************* +* Replacement for broken inet_ntoa() * +*************************************************/ + + +/* On IRIX systems, gcc uses a different structure passing convention to the +native libraries. This causes inet_ntoa() to always yield 0.0.0.0 or +255.255.255.255. To get round this, we provide a private version of the +function here. It is used only if USE_INET_NTOA_FIX is set, which should +happen +only when gcc is in use on an IRIX system. Code send to me by J.T. Breitner, +with these comments: + + + code by Stuart Levy + as seen in comp.sys.sgi.admin + + +Arguments: sa an in_addr structure +Returns: pointer to static text string +*/ + + +char * +inet_ntoa(struct in_addr sa) +{ +static char addr[20]; +sprintf(addr, "%d.%d.%d.%d", + (US &sa.s_addr)[0], + (US &sa.s_addr)[1], + (US &sa.s_addr)[2], + (US &sa.s_addr)[3]); + return addr; +} + +#endif /* BROKEN_INET_NTOA */ + + +DEFUN_DLD(server,args,,"\ +server(port,host,host,...)\n\ + Listen for connections on the given port. Normally only accepts\n\ + connections from localhost (127.0.0.1), but you can specify any\n\ + dot-separated host name globs. E.g., '128.2.20.*' or '128.2.2[012].*'\n\ + Use '?' for '[0123456789]'. Use '*.*.*.*' for any host.\n\ +server(...,'debug'|'nodebug')\n\ + If debug, echo all commands sent across the connection. If nodebug,\n\ + detach the process and don't echo anything. You will need to use\n\ + kill directly to end the process. Nodebug is the default.\n\ +server(...,'fork'|'nofork')\n\ + If fork, start new server for each connection. If nofork, only allow\n\ + one connection at a time. Fork is the default (depending on system).\n\ +server(...,'loopback')\n\ + Use loopback address 127.0.0.1 rather than 0.0.0.0.\n\ +") +{ +#if USE_DEFUN_INTERNAL + install_builtin_function (Fsend, "send", "builtin send doc", false); + install_builtin_function (Fsenderror, + "senderror", "builtin senderror doc", false); +#endif + + bool canfork = CAN_FORK; + + octave_value_list ret; + int nargin = args.length(); + if (nargin < 1) + { + print_usage (); + return ret; + } + int port = args(0).int_value(); + if (error_state) return ret; + + // Winsock requires initialization + if (!init_sockets()) + { + socket_error("init"); + return ret; + } + + + debug = false; + uint32_t inaddr = INADDR_ANY; + + string_vector hostlist; + hostlist.append(std::string("127.0.0.1")); + for (int k = 1; k < nargin; k++) { + std::string lastarg(args(k).string_value()); + if (error_state) return ret; + lowercase(lastarg); + if (lastarg == "debug") { + debug = true; + } else if (lastarg == "nodebug") { + debug = false; + } else if (lastarg == "fork") { + canfork = true; + } else if (lastarg == "nofork") { + canfork = false; + } else if (lastarg == "loopback") { + inaddr = INADDR_LOOPBACK; + } else if (ishostglob(lastarg)) { + hostlist.append(lastarg); + } else { + print_usage (); + } + } + + int sockfd; // listen on sockfd, new connection channel + struct sockaddr_in my_addr; // my address information + struct sockaddr_in their_addr; // connector's address information + socklen_t sin_size; + int yes=1; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + socket_error("socket"); + return ret; + } + + if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char *)(&yes),sizeof(yes)) == -1) { + socket_error("setsockopt"); + return ret; + } + + my_addr.sin_family = AF_INET; // host byte order + my_addr.sin_port = htons(port); // short, network byte order + my_addr.sin_addr.s_addr = htonl(inaddr); // automatically fill with my IP + memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct + + if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) + == -1) { + socket_error("bind"); + closesocket(sockfd); + return ret; + } + + /* listen for connections (allowing one pending connection) */ + if (listen(sockfd, canfork?1:0) == -1) { + socket_error("listen"); + closesocket(sockfd); + return ret; + } + +#if 0 + unwind_protect::begin_frame("Flisten"); + unwind_protect_bool (buffer_error_messages); + buffer_error_messages = true; +#endif + + sigchld_setup(); + if (!debug && canfork) daemonize(); + + // XXX FIXME XXX want a 'sandbox' option which disables fopen, cd, pwd, + // system, popen ... Or maybe just an initial script to run for each + // connection, plus a separate command to disable specific functions. + STATUS("listening on port " << port); + while(1) { // main accept() loop + sin_size = sizeof(struct sockaddr_in); + STATUS("trying to accept"); + if ((channel = accept(sockfd, (struct sockaddr *)&their_addr, + &sin_size)) == -1) { + // XXX FIXME XXX + // Linux is returning "Interrupted system call" when the + // child terminates. Until I figure out why, I can't use + // accept errors as a basis for breaking out of the listen + // loop, so instead print the octave PID so that I can kill + // it from another terminal. + STATUS("failed to accept" << std::endl + << "Octave pid: " << octave_syscalls::getpid() ); + perror("accept"); +#if defined(_sgi) + break; +#else + continue; +#endif + } + STATUS("connected"); + + /* Simulate inet_ntoa */ + const char *them = inet_ntoa(their_addr.sin_addr); + STATUS("server: got connection from " << them); + + if (anyhostglob(hostlist,them)) { +#ifdef HAVE_FORK + if (canfork) { + int pid = fork(); + if (pid == -1) { + socket_error("fork"); + break; + } else if (pid == 0) { + closesocket(sockfd); // child doesn't need listener + signal(SIGCHLD,SIG_DFL); // child doesn't need SIGCHLD signal + process_commands(channel); + STATUS("child is exitting"); + exit(0); + } + } else { + process_commands(channel); + STATUS("server: connection closed"); + } +#else // !HAVE_FORK + process_commands(channel); + STATUS("server: connection closed"); +#endif // !HAVE_FORK + } else { + STATUS("server: connection refused."); + } + + closesocket(channel); + channel = -1; + } + + STATUS("could not read commands; returning"); + closesocket(sockfd); + end_sockets(); +#if 0 + unwind_protect::run_frame("Flisten"); +#endif + return ret; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ha...@us...> - 2010-03-05 23:41:37
|
Revision: 6998 http://octave.svn.sourceforge.net/octave/?rev=6998&view=rev Author: hauberg Date: 2010-03-05 23:41:29 +0000 (Fri, 05 Mar 2010) Log Message: ----------- Remove hex2num as it has been in core for quite a while Modified Paths: -------------- trunk/octave-forge/main/miscellaneous/src/Makefile Removed Paths: ------------- trunk/octave-forge/main/miscellaneous/src/hex2num.cc Modified: trunk/octave-forge/main/miscellaneous/src/Makefile =================================================================== --- trunk/octave-forge/main/miscellaneous/src/Makefile 2010-03-05 23:28:11 UTC (rev 6997) +++ trunk/octave-forge/main/miscellaneous/src/Makefile 2010-03-05 23:41:29 UTC (rev 6998) @@ -4,7 +4,7 @@ TERM_LIB=-ltermcap endif -TARGETS=waitbar.oct $(LISTEN) xmlread.oct hex2num.oct \ +TARGETS=waitbar.oct $(LISTEN) xmlread.oct \ csvexplode.oct csv2cell.oct csvconcat.oct cell2csv.oct all: $(TARGETS) @@ -60,7 +60,4 @@ cell2csv.oct: cell2csv.cc $(MKOCTFILE) $(MISCDEFS) $< -hex2num.oct: hex2num.cc - $(MKOCTFILE) $(MISCDEFS) $< - clean: ; -$(RM) *.o octave-core core *.oct *~ $(t2.1.58) Deleted: trunk/octave-forge/main/miscellaneous/src/hex2num.cc =================================================================== --- trunk/octave-forge/main/miscellaneous/src/hex2num.cc 2010-03-05 23:28:11 UTC (rev 6997) +++ trunk/octave-forge/main/miscellaneous/src/hex2num.cc 2010-03-05 23:41:29 UTC (rev 6998) @@ -1,178 +0,0 @@ -/* - -Copyright (C) 2008 David Bateman - -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 3 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; see the file COPYING. If not, see -<http://www.gnu.org/licenses/>. - -*/ - -#include <config.h> -#include <algorithm> - -#include <octave/defun-dld.h> -#include <octave/error.h> -#include <octave/gripes.h> -#include <octave/oct-obj.h> -#include <octave/utils.h> - -DEFUN_DLD (hex2num, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{n} =} hex2num (@var{s})\n\ -Typecast the 16 character hexadecimal character matrix to an IEEE 754\n\ -double precision number. If fewer than 16 characters are given the\n\ -strings are right padded with '0' characters.\n\ -\n\ -Given a string matrix, @code{hex2num} treats each row as a separate\n\ -number.\n\ -\n\ -@example\n\ -hex2num ([\"4005bf0a8b145769\";\"4024000000000000\"])\n\ -@result{} [2.7183; 10.000]\n\ -@end example\n\ -@seealso{num2hex, hex2dec, dec2hex}\n\ -@end deftypefn") -{ - int nargin = args.length (); - octave_value retval; - - if (nargin != 1) - print_usage (); - else - { - const charMatrix cmat = args(0).char_matrix_value (); - - if (cmat.columns () > 16) - error ("hex2num: expecting no more than a 16 character string"); - else if (! error_state) - { - octave_idx_type nr = cmat.rows (); - octave_idx_type nc = cmat.columns (); - ColumnVector m (nr); - - for (octave_idx_type i = 0; i < nr; i++) - { - uint64_t num = 0; - for (octave_idx_type j = 0; j < nc; j++) - { - unsigned char ch = cmat.elem (i, j); - - if (isxdigit (ch)) - { - num <<= 4; - if (ch >= 'a') - num += static_cast<uint64_t> (ch - 'a' + 10); - else if (ch >= 'A') - num += static_cast<uint64_t> (ch - 'A' + 10); - else - num += static_cast<uint64_t> (ch - '0'); - } - else - { - error ("hex2num: illegal character found in string"); - break; - } - } - - if (error_state) - break; - else - { - if (nc < 16) - num <<= (16 - nc) * 4; - - m (i) = *reinterpret_cast<double *>(&num); - - } - } - - if (! error_state) - retval = m; - } - } - - return retval; -} - -/* - -%!assert (hex2num(['c00';'bff';'000';'3ff';'400']),[-2:2]') - - */ - - -// PKG_ADD: autoload ("num2hex", "hex2num.oct"); -DEFUN_DLD (num2hex, args, , - "-*- texinfo -*-\n\ -@deftypefn {Loadable Function} {@var{s} =} num2hex (@var{n})\n\ -Typecast a double precision number or vector to a 16 character hexadecimal\n\ -string of the IEEE 754 representation of the number. For example\n\ -\n\ -@example\n\ -num2hex ([-1, 1, e, Inf, NaN, NA]);\n\ -@result{} \"bff0000000000000\n\ - 3ff0000000000000\n\ - 4005bf0a8b145769\n\ - 7ff0000000000000\n\ - fff8000000000000\n\ - 7ff00000000007a2\"\n\ -@end example\n\ -@seealso{hex2num, hex2dec, dec2hex}\n\ -@end deftypefn") -{ - int nargin = args.length (); - octave_value retval; - - if (nargin != 1) - print_usage (); - else - { - const ColumnVector v (args(0).vector_value ()); - - if (! error_state) - { - octave_idx_type nr = v.length (); - charMatrix m (nr, 16); - const double *pv = v.fortran_vec (); - - for (octave_idx_type i = 0; i < nr; i++) - { - const uint64_t num = *reinterpret_cast<const uint64_t *> (pv++); - for (octave_idx_type j = 0; j < 16; j++) - { - unsigned char ch = - static_cast<char> (num >> ((15 - j) * 4) & 0xF); - if (ch >= 10) - ch += 'a' - 10; - else - ch += '0'; - - m.elem (i, j) = ch; - } - } - - retval = octave_value (m, true); - } - } - - return retval; -} - -/* - -%!assert (num2hex (-2:2),['c000000000000000';'bff0000000000000';'0000000000000000';'3ff0000000000000';'4000000000000000']) - - */ - - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pki...@us...> - 2010-10-25 17:15:08
|
Revision: 7873 http://octave.svn.sourceforge.net/octave/?rev=7873&view=rev Author: pkienzle Date: 2010-10-25 17:15:00 +0000 (Mon, 25 Oct 2010) Log Message: ----------- server(): use eval_string directly; remove compiler warnings Modified Paths: -------------- trunk/octave-forge/main/miscellaneous/src/server.cc trunk/octave-forge/main/miscellaneous/src/stringmatch.c Modified: trunk/octave-forge/main/miscellaneous/src/server.cc =================================================================== --- trunk/octave-forge/main/miscellaneous/src/server.cc 2010-10-25 13:42:49 UTC (rev 7872) +++ trunk/octave-forge/main/miscellaneous/src/server.cc 2010-10-25 17:15:00 UTC (rev 7873) @@ -127,7 +127,7 @@ { int err = socket_errno(); char errno_str[15]; - sprintf(" %d: ",errno_str); + snprintf(errno_str, sizeof(errno_str), " %d: ", err); std::string msg = std::string(context) + std::string(errno_str) + std::string (strerror(err)); error(msg.c_str()); @@ -189,14 +189,17 @@ static void daemonize(void) { - if (fork()) exit(0); + if (fork()) exit(0); // Stop parent + // Show child PID std::cout << "Octave pid: " << octave_syscalls::getpid() << std::endl; + std::cout.flush(); signal(SIGTERM,sigterm_handler); signal(SIGQUIT,sigterm_handler); - freopen("/dev/null", "r", stdin); - freopen("/dev/null", "w", stdout); - freopen("/dev/null", "w", stderr); + // Exit silently if I/O redirect fails. + if (freopen("/dev/null", "r", stdin) == NULL + || freopen("/dev/null", "w", stdout) == NULL + || freopen("/dev/null", "w", stderr)) exit(0); } #else @@ -395,6 +398,12 @@ if (debug) tic(); #if 1 + error_state = 0; + int parse_status = 0; + eval_string(context, true, parse_status, 0); + if (parse_status != 0 || error_state) + eval_string("senderror(lasterr);", true, parse_status, 0); +#elif 0 octave_value_list evalargs; evalargs(1) = "senderror(lasterr);"; evalargs(0) = context; @@ -479,7 +488,6 @@ // XXX FIXME XXX perhaps process the panalopy of types? if (nargin > 1) { - STATUS("sending !!!x(" << cmd.length() << ") " << cmd.c_str()); octave_value def = args(1); if (args(1).is_string()) { @@ -487,6 +495,7 @@ // Can't use args(1).string_value() because that trims trailing \0 charMatrix m(args(1).char_matrix_value()); std::string s(m.row_as_string(0,false,true)); + STATUS("sending string(" << cmd.c_str() << " len " << s.length() << ")"); ok = writes(channel,"!!!s",4); // string message t = htonl(8 + cmd.length() + s.length()); if (ok) ok = writes(channel,&t,4); // length of message @@ -498,9 +507,10 @@ ok = writes(channel, cmd.c_str(), cmd.length()); // name if (s.length() && ok) ok = writes(channel, s.c_str(), s.length()); // string - STATUS("sent string(" << s.length() << ")"); } else if (args(1).is_real_type()) { Matrix m(args(1).matrix_value()); + STATUS("sending matrix(" << cmd.c_str() << " " + << m.rows() << "x" << m.columns() << ")"); // write the matrix transfer header ok = writes(channel,"!!!m",4); // matrix message @@ -518,13 +528,13 @@ const double *v = m.data(); // data if (m.rows()*m.columns() && ok) ok = writes(channel,v,sizeof(double)*m.rows()*m.columns()); - STATUS("sent matrix(" << m.rows() << "x" << m.columns() << ")"); } else { ok = false; error("send expected name and matrix or string value"); } if (!ok) error("send could not write to channel"); } else { + STATUS("sending command(" << cmd.length() << ") " << cmd.c_str()); // STATUS("start writing at "<<toc()<<"us"); ok = writes(channel, "!!!x", 4); t = htonl(cmd.length()); writes(channel, &t, 4); Modified: trunk/octave-forge/main/miscellaneous/src/stringmatch.c =================================================================== --- trunk/octave-forge/main/miscellaneous/src/stringmatch.c 2010-10-25 13:42:49 UTC (rev 7872) +++ trunk/octave-forge/main/miscellaneous/src/stringmatch.c 2010-10-25 17:15:00 UTC (rev 7873) @@ -69,6 +69,7 @@ *---------------------------------------------------------------------- */ +#include <ctype.h> /* PAK: need tolower declaration */ #define CONST const #define UCHAR (unsigned char) @@ -82,8 +83,8 @@ * characters. */ int nocase; /* 0 for case sensitive, 1 for insensitive */ { - int p, charLen; - CONST char *pstart = pattern; + int p /*, charLen*/; /* PAK: unused */ + /* CONST char *pstart = pattern; */ /* PAK: unused */ char ch1, ch2; while (1) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2012-03-24 19:55:09
|
Revision: 10044 http://octave.svn.sourceforge.net/octave/?rev=10044&view=rev Author: carandraug Date: 2012-03-24 19:54:57 +0000 (Sat, 24 Mar 2012) Log Message: ----------- miscellaneous: simpler Makefile Modified Paths: -------------- trunk/octave-forge/main/miscellaneous/src/Makefile Removed Paths: ------------- trunk/octave-forge/main/miscellaneous/src/Makeconf.in trunk/octave-forge/main/miscellaneous/src/autogen.sh trunk/octave-forge/main/miscellaneous/src/configure.base Deleted: trunk/octave-forge/main/miscellaneous/src/Makeconf.in =================================================================== --- trunk/octave-forge/main/miscellaneous/src/Makeconf.in 2012-03-24 19:53:23 UTC (rev 10043) +++ trunk/octave-forge/main/miscellaneous/src/Makeconf.in 2012-03-24 19:54:57 UTC (rev 10044) @@ -1,71 +0,0 @@ - -## Makeconf is automatically generated from Makeconf.base and Makeconf.add -## in the various subdirectories. To regenerate, use ./autogen.sh to -## create a new ./Makeconf.in, then use ./configure to generate a new -## Makeconf. - -OCTAVE_FORGE = 1 - -SHELL = @SHELL@ - -canonical_host_type = @canonical_host_type@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -mandir = @mandir@ -libdir = @libdir@ -datadir = @datadir@ -infodir = @infodir@ -includedir = @includedir@ -datarootdir = @datarootdir@ -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALLOCT=octinst.sh - -DESTDIR = - -RANLIB = @RANLIB@ -STRIP = @STRIP@ -LN_S = @LN_S@ - -AWK = @AWK@ - -# Most octave programs will be compiled with $(MKOCTFILE). Those which -# cannot use mkoctfile directly can request the flags that mkoctfile -# would use as follows: -# FLAG = $(shell $(MKOCTFILE) -p FLAG) -# The following flags are for compiling programs that are independent -# of Octave. How confusing. -CC = @CC@ -CFLAGS = @CFLAGS@ -CPPFLAGS = @CPPFLAGS@ -CPICFLAG = @CPICFLAG@ -CXX = @CXX@ -CXXFLAGS = @CXXFLAGS@ -CXXPICFLAG = @CXXPICFLAG@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -FPICFLAG = @FPICFLAG@ - -OCTAVE = @OCTAVE@ -OCTAVE_VERSION = @OCTAVE_VERSION@ -MKOCTFILE = @MKOCTFILE@ -DHAVE_OCTAVE_$(ver) -v -SHLEXT = @SHLEXT@ - -ver = @ver@ -MPATH = @mpath@ -OPATH = @opath@ -XPATH = @xpath@ -ALTMPATH = @altmpath@ -ALTOPATH = @altopath@ - -HAVE_LIB_TERMCAP = @HAVE_LIB_TERMCAP@ -MISCDEFS = @MISCDEFS@ -HAVE_FORK = @have_fork@ - -%.o: %.c ; $(MKOCTFILE) -c $< -%.o: %.f ; $(MKOCTFILE) -c $< -%.o: %.cc ; $(MKOCTFILE) -c $< -%.oct: %.cc ; $(MKOCTFILE) $< Modified: trunk/octave-forge/main/miscellaneous/src/Makefile =================================================================== --- trunk/octave-forge/main/miscellaneous/src/Makefile 2012-03-24 19:53:23 UTC (rev 10043) +++ trunk/octave-forge/main/miscellaneous/src/Makefile 2012-03-24 19:54:57 UTC (rev 10044) @@ -1,35 +1,9 @@ -sinclude Makeconf +all: cell2cell.oct partarray.oct sample.oct text_waitbar.oct -ifdef HAVE_LIB_TERMCAP - TERM_LIB=-ltermcap -endif +MKOCTFILE = mkoctfile -Wall -TARGETS=text_waitbar.oct $(LISTEN) cell2cell.oct sample.oct partarray.oct +%.oct: %.cc + $(MKOCTFILE) $< -all: $(TARGETS) - -text_waitbar.oct: text_waitbar.cc - $(MKOCTFILE) $(MISCDEFS) text_waitbar.cc $(TERM_LIB) - -server.oct: server.o listencanfork.o stringmatch.o - $(MKOCTFILE) server.o listencanfork.o stringmatch.o - -server.o: server.cc - $(MKOCTFILE) -c $(MISCDEFS) server.cc - -listencanfork.o: listencanfork.c - $(MKOCTFILE) -c listencanfork.c - -stringmatch.o: stringmatch.c - $(MKOCTFILE) -c stringmatch.c - -cell2cell.oct: cell2cell.cc - $(MKOCTFILE) $(MISCDEFS) $< - -partarray.oct: partarray.cc - $(MKOCTFILE) $(MISCDEFS) $< - -sample.oct: sample.cc - $(MKOCTFILE) $(MISCDEFS) $< - -clean: ; -$(RM) *.o octave-core core *.oct *~ $(t2.1.58) +clean: + rm -f *.o octave-core core *.oct *~ Deleted: trunk/octave-forge/main/miscellaneous/src/autogen.sh =================================================================== --- trunk/octave-forge/main/miscellaneous/src/autogen.sh 2012-03-24 19:53:23 UTC (rev 10043) +++ trunk/octave-forge/main/miscellaneous/src/autogen.sh 2012-03-24 19:54:57 UTC (rev 10044) @@ -1,27 +0,0 @@ -#! /bin/sh - -## Generate ./configure -rm -f configure.in -echo "dnl --- DO NOT EDIT --- Automatically generated by autogen.sh" > configure.in -cat configure.base >> configure.in -cat <<EOF >> configure.in - AC_OUTPUT(\$CONFIGURE_OUTPUTS) - dnl XXX FIXME XXX chmod is not in autoconf's list of portable functions - - echo " " - echo " \"\\\$prefix\" is \$prefix" - echo " \"\\\$exec_prefix\" is \$exec_prefix" - AC_MSG_RESULT([\$STATUS_MSG - -find . -name NOINSTALL -print # shows which toolboxes won't be installed -]) -EOF - -autoconf configure.in > configure.tmp -if [ diff configure.tmp configure > /dev/null 2>&1 ]; then - rm -f configure.tmp; -else - mv -f configure.tmp configure - chmod 0755 configure -fi -rm -f configure.in Deleted: trunk/octave-forge/main/miscellaneous/src/configure.base =================================================================== --- trunk/octave-forge/main/miscellaneous/src/configure.base 2012-03-24 19:53:23 UTC (rev 10043) +++ trunk/octave-forge/main/miscellaneous/src/configure.base 2012-03-24 19:54:57 UTC (rev 10044) @@ -1,376 +0,0 @@ -dnl The configure script is generated by autogen.sh from configure.base -dnl and the various configure.add files in the source tree. Edit -dnl configure.base and reprocess rather than modifying ./configure. - -dnl autoconf 2.13 certainly doesn't work! What is the minimum requirement? -AC_PREREQ(2.2) - -AC_INIT(configure.base) - -PACKAGE=octave-forge -MAJOR_VERSION=0 -MINOR_VERSION=1 -PATCH_LEVEL=0 - -dnl Kill caching --- this ought to be the default -define([AC_CACHE_LOAD], )dnl -define([AC_CACHE_SAVE], )dnl - -dnl uncomment to put support files in another directory -dnl AC_CONFIG_AUX_DIR(admin) - -VERSION=$MAJOR_VERSION.$MINOR_VERSION.$PATCH_LEVEL -AC_SUBST(PACKAGE) -AC_SUBST(VERSION) - -dnl need to find admin files, so keep track of the top dir. -TOPDIR=`pwd` -AC_SUBST(TOPDIR) - -dnl if mkoctfile doesn't work, then we need the following: -dnl AC_PROG_CXX -dnl AC_PROG_F77 - -dnl Need C compiler regardless so define it in a way that -dnl makes autoconf happy and we can override whatever we -dnl need with mkoctfile -p. -dnl XXX FIXME XXX should use mkoctfile to get CC and CFLAGS -AC_PROG_CC - -dnl XXX FIXME XXX need tests for -p -c -s in mkoctfile. - -dnl ******************************************************************* -dnl Sort out mkoctfile version number and install paths - -dnl XXX FIXME XXX latest octave has octave-config so we don't -dnl need to discover things here. Doesn't have --exe-site-dir -dnl but defines --oct-site-dir and --m-site-dir - -dnl Check for mkoctfile -AC_CHECK_PROG(MKOCTFILE,mkoctfile,mkoctfile) -test -z "$MKOCTFILE" && AC_MSG_WARN([no mkoctfile found on path]) - -AC_SUBST(ver) -AC_SUBST(subver) -AC_SUBST(mpath) -AC_SUBST(opath) -AC_SUBST(xpath) -AC_SUBST(altpath) -AC_SUBST(altmpath) -AC_SUBST(altopath) - -AC_ARG_WITH(path, - [ --with-path install path prefix], - [ path=$withval ]) -AC_ARG_WITH(mpath, - [ --with-mpath override path for m-files], - [mpath=$withval]) -AC_ARG_WITH(opath, - [ --with-opath override path for oct-files], - [opath=$withval]) -AC_ARG_WITH(xpath, - [ --with-xpath override path for executables], - [xpath=$withval]) -AC_ARG_WITH(altpath, - [ --with-altpath alternative functions install path prefix], - [ altpath=$withval ]) -AC_ARG_WITH(altmpath, - [ --with-altmpath override path for alternative m-files], - [altmpath=$withval]) -AC_ARG_WITH(altopath, - [ --with-altopath override path for alternative oct-files], - [altopath=$withval]) - -if test -n "$path" ; then - test -z "$mpath" && mpath=$path - test -z "$opath" && opath=$path/oct - test -z "$xpath" && xpath=$path/bin - test -z "$altpath" && altpath=$path-alternatives -fi - -if test -n "$altpath" ; then - test -z "$altmpath" && altmpath=$altpath - test -z "$altopath" && altopath=$altpath/oct -fi - -dnl Don't query if path/ver are given in the configure environment -#if test -z "$mpath" || test -z "$opath" || test -z "$xpath" || test -z "$altmpath" || test -z "$altopath" || test -z "$ver" ; then -if test -z "$mpath" || test -z "$opath" || test -z "$xpath" || test -z "$ver" ; then - dnl Construct program to get mkoctfile version and local install paths - cat > conftest.cc <<EOF -#include <octave/config.h> -#include <octave/version.h> -#include <octave/defaults.h> - -#define INFOV "\nINFOV=" OCTAVE_VERSION "\n" - -#define INFOH "\nINFOH=" OCTAVE_CANONICAL_HOST_TYPE "\n" - -#ifdef OCTAVE_LOCALVERFCNFILEDIR -# define INFOM "\nINFOM=" OCTAVE_LOCALVERFCNFILEDIR "\n" -#else -# define INFOM "\nINFOM=" OCTAVE_LOCALFCNFILEPATH "\n" -#endif - -#ifdef OCTAVE_LOCALVEROCTFILEDIR -# define INFOO "\nINFOO=" OCTAVE_LOCALVEROCTFILEDIR "\n" -#else -# define INFOO "\nINFOO=" OCTAVE_LOCALOCTFILEPATH "\n" -#endif - -#ifdef OCTAVE_LOCALVERARCHLIBDIR -# define INFOX "\nINFOX=" OCTAVE_LOCALVERARCHLIBDIR "\n" -#else -# define INFOX "\nINFOX=" OCTAVE_LOCALARCHLIBDIR "\n" -#endif - -const char *infom = INFOM; -const char *infoo = INFOO; -const char *infox = INFOX; -const char *infoh = INFOH; -const char *infov = INFOV; -EOF - - dnl Compile program perhaps with a special version of mkoctfile - $MKOCTFILE conftest.cc || AC_MSG_ERROR(Could not run $MKOCTFILE) - - dnl Strip the config info from the compiled file - eval `strings conftest.o | grep "^INFO.=" | sed -e "s,//.*$,,"` - rm -rf conftest* - - dnl set the appropriate variables if they are not already set - ver=`echo $INFOV | sed -e "s/\.//" -e "s/\..*$//"` - subver=`echo $INFOV | sed -e "[s/^[^.]*[.][^.]*[.]//]"` - alt_mbase=`echo $INFOM | sed -e "[s,\/[^\/]*$,,]"` - alt_obase=`echo $INFOO | sed -e "[s,/site.*$,/site,]"` - test -z "$mpath" && mpath=$INFOM/octave-forge - test -z "$opath" && opath=$INFOO/octave-forge - test -z "$xpath" && xpath=$INFOX - test -z "$altmpath" && altmpath=$alt_mbase/octave-forge-alternatives/m - test -z "$altopath" && altopath=$alt_obase/octave-forge-alternatives/oct/$INFOH -fi - -dnl ******************************************************************* - -dnl XXX FIXME XXX Should we allow the user to override these? -dnl Do we even need them? The individual makefiles can call mkoctfile -p -dnl themselves, so the only reason to keep them is for configure, and -dnl for those things which are not built using mkoctfile (e.g., aurecord) -dnl but it is not clear we should be using octave compile flags for those. - -dnl C compiler and flags -AC_MSG_RESULT([retrieving compile and link flags from $MKOCTFILE]) -CC=`$MKOCTFILE -p CC` -CFLAGS=`$MKOCTFILE -p CFLAGS` -CPPFLAGS=`$MKOCTFILE -p CPPFLAGS` -CPICFLAG=`$MKOCTFILE -p CPICFLAG` -LDFLAGS=`$MKOCTFILE -p LDFLAGS` -LIBS=`$MKOCTFILE -p LIBS` -AC_SUBST(CC) -AC_SUBST(CFLAGS) -AC_SUBST(CPPFLAGS) -AC_SUBST(CPICFLAG) - -dnl Fortran compiler and flags -F77=`$MKOCTFILE -p F77` -FFLAGS=`$MKOCTFILE -p FFLAGS` -FPICFLAG=`$MKOCTFILE -p FPICFLAG` -AC_SUBST(F77) -AC_SUBST(FFLAGS) -AC_SUBST(FPICFLAG) - -dnl C++ compiler and flags -CXX=`$MKOCTFILE -p CXX` -CXXFLAGS=`$MKOCTFILE -p CXXFLAGS` -CXXPICFLAG=`$MKOCTFILE -p CXXPICFLAG` -AC_SUBST(CXX) -AC_SUBST(CXXFLAGS) -AC_SUBST(CXXPICFLAG) - -dnl ******************************************************************* - -dnl Check for features of your version of mkoctfile. -dnl All checks should be designed so that the default -dnl action if the tests are not performed is to do whatever -dnl is appropriate for the most recent version of Octave. - -dnl Define the following macro: -dnl OF_CHECK_LIB(lib,fn,true,false,helpers) -dnl This is just like AC_CHECK_LIB, but it doesn't update LIBS -AC_DEFUN(OF_CHECK_LIB, -[save_LIBS="$LIBS" -AC_CHECK_LIB($1,$2,$3,$4,$5) -LIBS="$save_LIBS" -]) - -dnl Define the following macro: -dnl TRY_MKOCTFILE(msg,program,action_if_true,action_if_false) -dnl -AC_DEFUN(TRY_MKOCTFILE, -[AC_MSG_CHECKING($1) -cat > conftest.cc << EOF -#include <octave/config.h> -$2 -EOF -ac_try="$MKOCTFILE -c conftest.cc" -if AC_TRY_EVAL(ac_try) ; then - AC_MSG_RESULT(yes) - $3 -else - AC_MSG_RESULT(no) - $4 -fi -]) - -dnl -dnl Check if F77_FUNC works with MKOCTFILE -dnl -TRY_MKOCTFILE([for F77_FUNC], -[int F77_FUNC (hello, HELLO) (const int &n);],, -[MKOCTFILE="$MKOCTFILE -DF77_FUNC=F77_FCN"]) - -dnl ********************************************************** - -dnl Evaluate an expression in octave -dnl -dnl OCTAVE_EVAL(expr,var) -> var=expr -dnl -AC_DEFUN(OCTAVE_EVAL, -[AC_MSG_CHECKING([for $1 in Octave]) -$2=`echo "disp($1)" | $OCTAVE -qf` -AC_MSG_RESULT($$2) -AC_SUBST($2) -]) - -dnl Check status of an octave variable -dnl -dnl OCTAVE_CHECK_EXIST(variable,action_if_true,action_if_false) -dnl -AC_DEFUN(OCTAVE_CHECK_EXIST, -[AC_MSG_CHECKING([for $1 in Octave]) -if test `echo 'disp(exist("$1"))' | $OCTAVE -qf`X != 0X ; then - AC_MSG_RESULT(yes) - $2 -else - AC_MSG_RESULT(no) - $3 -fi -]) - -dnl should check that $(OCTAVE) --version matches $(MKOCTFILE) --version -AC_CHECK_PROG(OCTAVE,octave,octave) -OCTAVE_EVAL(OCTAVE_VERSION,OCTAVE_VERSION) - -dnl grab canonical host type so we can write system specific install stuff -OCTAVE_EVAL(octave_config_info('canonical_host_type'),canonical_host_type) - -dnl grab SHLEXT from octave config -OCTAVE_EVAL(octave_config_info('SHLEXT'),SHLEXT) - -AC_PROG_LN_S - -AC_PROG_RANLIB - -dnl Use $(COPY_FLAGS) to set options for cp when installing .oct files. -COPY_FLAGS="-Rfp" -case "$canonical_host_type" in - *-*-linux*) - COPY_FLAGS="-fdp" - ;; -esac -AC_SUBST(COPY_FLAGS) - -dnl Use $(STRIP) in the makefile to strip executables. If not found, -dnl STRIP expands to ':', which in the makefile does nothing. -dnl Don't need this for .oct files since mkoctfile handles them directly -STRIP=${STRIP-strip} -AC_CHECK_PROG(STRIP,$STRIP,$STRIP,:) - -dnl Strip on windows, don't strip on Mac OS/X or IRIX -dnl For the rest, you can force strip using MKOCTFILE="mkoctfile -s" -dnl or avoid strip using STRIP=: before ./configure -case "$canonical_host_type" in - powerpc-apple-darwin*|*-sgi-*) - STRIP=: - ;; - *-cygwin-*|*-mingw-*) - MKOCTFILE="$MKOCTFILE -s" - ;; -esac - -AC_SUBST(MISCDEFS) -AC_SUBST(HAVE_LIB_TERMCAP) - -AC_CHECK_FUNCS(fork, [have_fork=yes], [have_fork=]) -AC_SUBST(have_fork) - -dnl In modern autoconf, we should be able to replace this with something -dnl the CHECK_TYPE macro -AC_DEFUN([TYPE_SOCKLEN_T], -[AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t, -[ - AC_TRY_COMPILE( - [#include <sys/types.h> - #include <sys/socket.h>], - [socklen_t len = 42; return 0;], - ac_cv_type_socklen_t=yes, - ac_cv_type_socklen_t=no) -]) - if test $ac_cv_type_socklen_t != yes; then - MISCDEFS="$MISCDEFS -Dsocklen_t=int" - fi -]) - -dnl Check for socklen_t -TYPE_SOCKLEN_T - -dnl Check if octave_function(void) fails -TRY_MKOCTFILE([for octave_function(void)], - [#include <octave/ov-fcn.h> - class myfun:octave_function {myfun():octave_function(){}};], - [],[MISCDEFS="$MISCDEFS -DOCTAVE_FUNCTION_VOID_FAILS"]) - -dnl Check for term.h -case "$canonical_host_type" in - *-sgi-*) - have_term=no - have_termcap=no - ;; - *) - AC_CHECK_HEADER(term.h, have_term=yes, have_term=no) - AC_CHECK_HEADER(termcap.h, have_termcap=yes, have_termcap=no) - ;; -esac - -if test $have_termcap = yes; then - MISCDEFS="$MISCDEFS -DUSE_TERM -DHAVE_TERMCAP_H" - OF_CHECK_LIB(termcap, tgetnum, HAVE_LIB_TERMCAP=yes) - TERMSTATUS=yes -elif test $have_term = yes; then - MISCDEFS="$MISCDEFS -DUSE_TERM -DHAVE_TERM_H" - TERMSTATUS=yes - OF_CHECK_LIB(termcap, tgetnum, HAVE_LIB_TERMCAP=yes) -else - TERMSTATUS=no -fi - -CONFIGURE_OUTPUTS="Makeconf" -STATUS_MSG=" -octave commands will install into the following directories: - m-files: $mpath - oct-files: $opath - binaries: $xpath -alternatives: - m-files: $altmpath - oct-files: $altopath - -shell commands will install into the following directories: - binaries: $bindir - man pages: $mandir - libraries: $libdir - headers: $includedir - -octave-forge is configured with - octave: $OCTAVE (version $OCTAVE_VERSION) - mkoctfile: $MKOCTFILE for Octave $subver - have term.h or termcap.h: $TERMSTATUS" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <car...@us...> - 2012-02-22 15:09:15
|
Revision: 9647 http://octave.svn.sourceforge.net/octave/?rev=9647&view=rev Author: carandraug Date: 2012-02-22 15:09:03 +0000 (Wed, 22 Feb 2012) Log Message: ----------- text_waitbar: renamed waitbar to text_waitbar to not shadow core function Modified Paths: -------------- trunk/octave-forge/main/miscellaneous/src/Makefile Added Paths: ----------- trunk/octave-forge/main/miscellaneous/src/text_waitbar.cc Removed Paths: ------------- trunk/octave-forge/main/miscellaneous/src/waitbar.cc Modified: trunk/octave-forge/main/miscellaneous/src/Makefile =================================================================== --- trunk/octave-forge/main/miscellaneous/src/Makefile 2012-02-22 10:03:24 UTC (rev 9646) +++ trunk/octave-forge/main/miscellaneous/src/Makefile 2012-02-22 15:09:03 UTC (rev 9647) @@ -4,14 +4,14 @@ TERM_LIB=-ltermcap endif -TARGETS=waitbar.oct $(LISTEN) xmlread.oct \ +TARGETS=text_waitbar.oct $(LISTEN) xmlread.oct \ csvexplode.oct csv2cell.oct csvconcat.oct cell2csv.oct \ cell2cell.oct sample.oct all: $(TARGETS) -waitbar.oct: waitbar.cc - $(MKOCTFILE) $(MISCDEFS) waitbar.cc $(TERM_LIB) +text_waitbar.oct: text_waitbar.cc + $(MKOCTFILE) $(MISCDEFS) text_waitbar.cc $(TERM_LIB) server.oct: server.o listencanfork.o stringmatch.o $(MKOCTFILE) server.o listencanfork.o stringmatch.o Copied: trunk/octave-forge/main/miscellaneous/src/text_waitbar.cc (from rev 9646, trunk/octave-forge/main/miscellaneous/src/waitbar.cc) =================================================================== --- trunk/octave-forge/main/miscellaneous/src/text_waitbar.cc (rev 0) +++ trunk/octave-forge/main/miscellaneous/src/text_waitbar.cc 2012-02-22 15:09:03 UTC (rev 9647) @@ -0,0 +1,265 @@ +/************************************************************************** + * Waitbar function -- displays progress of lengthy calculations + * ------------------------------------------------------------- + * Copyright (c) 2002 Quentin Spencer <qsp...@ie...> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + *************************************************************************/ + +#include <octave/oct.h> + +// Note the extern "C" is need for mingw with a version of termcap.h +// without the extern "C" explicitly included. Doing it twice should be +// harmless. +extern "C" { +#if defined (HAVE_TERM_H) +# include <term.h> +#elif defined (HAVE_TERMCAP_H) +# include <termcap.h> +#endif +}; + +#define BUF_SIZE 256 +#define MAX_LEN 240 +#define DEFAULT_LEN 50 +#define BAR_CHAR '#' +#define SPACING 3 + +static bool no_terminal=false; + +DEFUN_DLD(text_waitbar, args, nargout, +"text_waitbar(...);\n\ + TEXT_WAITBAR displays a text-based wait bar. This function\n\ + is similar to the Matlab waitbar command, but it is\n\ + a text, rather than graphical function.\n\n\ + A typical usage of TEXT_WAITBAR in a lengthy computation\n\ + (inside a FOR loop, for example) is as follows:\n\n\ + for i=1:1000\n\ + ## computation\n\ + text_waitbar(i/1000);\n\ + end\n\n\ + TEXT_WAITBAR(X,TITLE), where 0 <= X <= 1, sets the position of\n\ + the waitbar to the fractional length X. Values of X exactly\n\ + equal to 0 or 1 clear the waitbar. The optional second\n\ + argument TITLE sets the waitbar caption to TITLE.\n\n\ + If Octave is running in a smart terminal, the width is\n\ + automatically detected, and the title is displayed in the\n\ + waitbar (and truncated if it is too long). Otherwise, the\n\ + title is not displayed and the width is initialized to a\n\ + default of 50 characters, or it can be set to N characters\n\ + with TEXT_WAITBAR(0,N). If no terminal is detected (such as when\n\ + Octave is run in batch mode and output is redirected), no\n\ + output is generated.\n\n\ + For compatibility with the Matlab version of this function\n\ + (which is graphical rather than text-based), additional\n\ + arguments are ignored, but there are no guarantees of perfect\n\ + compatibility.") +{ + static char print_buf[BUF_SIZE]; + static int n_chars_old; + static int pct_int_old; + static int length; +#if defined(USE_TERM) + static char term_buffer[1024]; + static char *begin_rv, *end_rv; + static int brvlen, ervlen, pct_pos; + static bool smart_term; + static bool newtitle = false; + static charMatrix title; + int j; +#endif + static char *term; + static bool init; + + double pct; + int i; + + octave_value_list retval; + retval(0) = Matrix(0,0); + int nargin = args.length(); + if (nargin < 1) { + print_usage (); + return retval; + } + + if(no_terminal) + return retval; + + pct = args(0).double_value(); + if(pct>1.0) pct = 1.0; // to prevent overflow + +#if defined(USE_TERM) + if(nargin==2 && args(1).is_string()) + { + newtitle = true; + title = args(1).string_value(); + } + if(nargin==3) + { + newtitle = true; + title = args(2).string_value(); + } +#endif + + if(pct==0.0 || pct==1.0) + { + init = true; + term = getenv("TERM"); + if(!term) + { + no_terminal = true; + return retval; + } +#if defined (USE_TERM) + i = tgetnum("co"); + smart_term = i ? true : false; + if(nargin==1 || args(1).is_string()) + length = smart_term ? i-1 : DEFAULT_LEN; +#else + if(nargin==1) + length = DEFAULT_LEN; +#endif + else + if(nargin==2 && !(args(1).is_string())) + { + length = args(1).int_value(); + if(length>MAX_LEN) length = MAX_LEN; + if(length<=0) length = DEFAULT_LEN; + } +#if defined (USE_TERM) + pct_pos = length/2-2; + if(smart_term) + { + // get terminal strings ("rv"="reverse video") + char* buf_ptr = term_buffer; + begin_rv = tgetstr("so", &buf_ptr); + end_rv = tgetstr("se", &buf_ptr); + + // Display a progress bar, but only if the current terminal has a + // standout mode + if (begin_rv && end_rv) + { + brvlen = 0; + buf_ptr = begin_rv; + while(buf_ptr[++brvlen]); + ervlen = 0; buf_ptr = end_rv; + while(buf_ptr[++ervlen]); + } + + // initialize print buffer + for(i=0; i<BUF_SIZE; ++i) + print_buf[i] = ' '; + print_buf[length+brvlen+ervlen+1] = '\r'; + print_buf[length+brvlen+ervlen+2] = '\0'; + for(i=0; i<brvlen; ++i) + print_buf[i] = begin_rv[i]; + for(i=0; i<ervlen; ++i) + print_buf[i+brvlen] = end_rv[i]; + fputs(print_buf,stdout); + if(title.length()) + newtitle = true; + } + else + { +#endif + for(i=0; i<BUF_SIZE; ++i) + print_buf[i] = ' '; + print_buf[length+8] = '\r'; + print_buf[length+9] = '\0'; + fputs(print_buf,stdout); + print_buf[0] = '['; + print_buf[length+1] = ']'; +#if defined (USE_TERM) + } +#endif + n_chars_old = 0; + fflush(stdout); + return retval; + } + else + { + // calculate position + int n_chars=(int)(pct*length+0.5); + int pct_int=(int)(pct*100.0+0.5); + + // check to see if we got this far without initialization + if(init==false) + { + Ftext_waitbar(octave_value(0.0),0); + fputs(print_buf,stdout); + fflush(stdout); + } + + // check to see of output needs to be updated +#if !defined (USE_TERM) + if(n_chars!=n_chars_old || pct_int!=pct_int_old) + { +#else + if(n_chars!=n_chars_old || pct_int!=pct_int_old || newtitle) + { + if(smart_term) + { + static char pct_str[5]; + sprintf(pct_str,"%3i%%",pct_int); + + // Insert the title + if(newtitle) + { + pct_pos = length-SPACING*2; + for(i=SPACING+brvlen; i<pct_pos+brvlen-SPACING; ++i) + print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = ' '; + for(i=SPACING+brvlen, j=0; j<title.length(); ++i, ++j) + if(i<pct_pos+brvlen-SPACING) + print_buf[ i>=n_chars_old ? i+ervlen : i ] = title(0,j); + newtitle = false; + } + + // Insert the percentage string + for(i=pct_pos+brvlen, j=0; j<4; ++i, ++j) + print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = pct_str[j]; + + // Move print_buf characters + if(n_chars_old<n_chars) + for(i=n_chars_old+brvlen; i<n_chars+brvlen; ++i) + print_buf[i] = print_buf[i+ervlen]; + else + for(i=n_chars_old+brvlen-1; i>=n_chars+brvlen; --i) + print_buf[i+ervlen] = print_buf[i]; + + // Insert end of reverse video + for(i=n_chars+brvlen, j=0; j<ervlen; ++i, ++j) + print_buf[i] = end_rv[j]; + } + else + { +#endif + if(n_chars>=n_chars_old) + for(int i=n_chars_old+1; i<=n_chars; ++i) + print_buf[i] = BAR_CHAR; + else + for(int i=n_chars+1; i<=n_chars_old; ++i) + print_buf[i] = ' '; + sprintf(&(print_buf[length+3])," %3i%%\r",pct_int); +#if defined (USE_TERM) + } +#endif + fputs(print_buf,stdout); + fflush(stdout); + n_chars_old = n_chars; + pct_int_old = pct_int; + } + } + return retval; +} Deleted: trunk/octave-forge/main/miscellaneous/src/waitbar.cc =================================================================== --- trunk/octave-forge/main/miscellaneous/src/waitbar.cc 2012-02-22 10:03:24 UTC (rev 9646) +++ trunk/octave-forge/main/miscellaneous/src/waitbar.cc 2012-02-22 15:09:03 UTC (rev 9647) @@ -1,265 +0,0 @@ -/************************************************************************** - * Waitbar function -- displays progress of lengthy calculations - * ------------------------------------------------------------- - * Copyright (c) 2002 Quentin Spencer <qsp...@ie...> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - *************************************************************************/ - -#include <octave/oct.h> - -// Note the extern "C" is need for mingw with a version of termcap.h -// without the extern "C" explicitly included. Doing it twice should be -// harmless. -extern "C" { -#if defined (HAVE_TERM_H) -# include <term.h> -#elif defined (HAVE_TERMCAP_H) -# include <termcap.h> -#endif -}; - -#define BUF_SIZE 256 -#define MAX_LEN 240 -#define DEFAULT_LEN 50 -#define BAR_CHAR '#' -#define SPACING 3 - -static bool no_terminal=false; - -DEFUN_DLD(waitbar, args, nargout, -"waitbar(...);\n\ - WAITBAR displays a text-based wait bar. This function\n\ - is similar to the Matlab waitbar command, but it is\n\ - a text, rather than graphical function.\n\n\ - A typical usage of WAITBAR in a lengthy computation\n\ - (inside a FOR loop, for example) is as follows:\n\n\ - for i=1:1000\n\ - ## computation\n\ - waitbar(i/1000);\n\ - end\n\n\ - WAITBAR(X,TITLE), where 0 <= X <= 1, sets the position of\n\ - the waitbar to the fractional length X. Values of X exactly\n\ - equal to 0 or 1 clear the waitbar. The optional second\n\ - argument TITLE sets the waitbar caption to TITLE.\n\n\ - If Octave is running in a smart terminal, the width is\n\ - automatically detected, and the title is displayed in the\n\ - waitbar (and truncated if it is too long). Otherwise, the\n\ - title is not displayed and the width is initialized to a\n\ - default of 50 characters, or it can be set to N characters\n\ - with WAITBAR(0,N). If no terminal is detected (such as when\n\ - Octave is run in batch mode and output is redirected), no\n\ - output is generated.\n\n\ - For compatibility with the Matlab version of this function\n\ - (which is graphical rather than text-based), additional\n\ - arguments are ignored, but there are no guarantees of perfect\n\ - compatibility.") -{ - static char print_buf[BUF_SIZE]; - static int n_chars_old; - static int pct_int_old; - static int length; -#if defined(USE_TERM) - static char term_buffer[1024]; - static char *begin_rv, *end_rv; - static int brvlen, ervlen, pct_pos; - static bool smart_term; - static bool newtitle = false; - static charMatrix title; - int j; -#endif - static char *term; - static bool init; - - double pct; - int i; - - octave_value_list retval; - retval(0) = Matrix(0,0); - int nargin = args.length(); - if (nargin < 1) { - print_usage (); - return retval; - } - - if(no_terminal) - return retval; - - pct = args(0).double_value(); - if(pct>1.0) pct = 1.0; // to prevent overflow - -#if defined(USE_TERM) - if(nargin==2 && args(1).is_string()) - { - newtitle = true; - title = args(1).string_value(); - } - if(nargin==3) - { - newtitle = true; - title = args(2).string_value(); - } -#endif - - if(pct==0.0 || pct==1.0) - { - init = true; - term = getenv("TERM"); - if(!term) - { - no_terminal = true; - return retval; - } -#if defined (USE_TERM) - i = tgetnum("co"); - smart_term = i ? true : false; - if(nargin==1 || args(1).is_string()) - length = smart_term ? i-1 : DEFAULT_LEN; -#else - if(nargin==1) - length = DEFAULT_LEN; -#endif - else - if(nargin==2 && !(args(1).is_string())) - { - length = args(1).int_value(); - if(length>MAX_LEN) length = MAX_LEN; - if(length<=0) length = DEFAULT_LEN; - } -#if defined (USE_TERM) - pct_pos = length/2-2; - if(smart_term) - { - // get terminal strings ("rv"="reverse video") - char* buf_ptr = term_buffer; - begin_rv = tgetstr("so", &buf_ptr); - end_rv = tgetstr("se", &buf_ptr); - - // Display a progress bar, but only if the current terminal has a - // standout mode - if (begin_rv && end_rv) - { - brvlen = 0; - buf_ptr = begin_rv; - while(buf_ptr[++brvlen]); - ervlen = 0; buf_ptr = end_rv; - while(buf_ptr[++ervlen]); - } - - // initialize print buffer - for(i=0; i<BUF_SIZE; ++i) - print_buf[i] = ' '; - print_buf[length+brvlen+ervlen+1] = '\r'; - print_buf[length+brvlen+ervlen+2] = '\0'; - for(i=0; i<brvlen; ++i) - print_buf[i] = begin_rv[i]; - for(i=0; i<ervlen; ++i) - print_buf[i+brvlen] = end_rv[i]; - fputs(print_buf,stdout); - if(title.length()) - newtitle = true; - } - else - { -#endif - for(i=0; i<BUF_SIZE; ++i) - print_buf[i] = ' '; - print_buf[length+8] = '\r'; - print_buf[length+9] = '\0'; - fputs(print_buf,stdout); - print_buf[0] = '['; - print_buf[length+1] = ']'; -#if defined (USE_TERM) - } -#endif - n_chars_old = 0; - fflush(stdout); - return retval; - } - else - { - // calculate position - int n_chars=(int)(pct*length+0.5); - int pct_int=(int)(pct*100.0+0.5); - - // check to see if we got this far without initialization - if(init==false) - { - Fwaitbar(octave_value(0.0),0); - fputs(print_buf,stdout); - fflush(stdout); - } - - // check to see of output needs to be updated -#if !defined (USE_TERM) - if(n_chars!=n_chars_old || pct_int!=pct_int_old) - { -#else - if(n_chars!=n_chars_old || pct_int!=pct_int_old || newtitle) - { - if(smart_term) - { - static char pct_str[5]; - sprintf(pct_str,"%3i%%",pct_int); - - // Insert the title - if(newtitle) - { - pct_pos = length-SPACING*2; - for(i=SPACING+brvlen; i<pct_pos+brvlen-SPACING; ++i) - print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = ' '; - for(i=SPACING+brvlen, j=0; j<title.length(); ++i, ++j) - if(i<pct_pos+brvlen-SPACING) - print_buf[ i>=n_chars_old ? i+ervlen : i ] = title(0,j); - newtitle = false; - } - - // Insert the percentage string - for(i=pct_pos+brvlen, j=0; j<4; ++i, ++j) - print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = pct_str[j]; - - // Move print_buf characters - if(n_chars_old<n_chars) - for(i=n_chars_old+brvlen; i<n_chars+brvlen; ++i) - print_buf[i] = print_buf[i+ervlen]; - else - for(i=n_chars_old+brvlen-1; i>=n_chars+brvlen; --i) - print_buf[i+ervlen] = print_buf[i]; - - // Insert end of reverse video - for(i=n_chars+brvlen, j=0; j<ervlen; ++i, ++j) - print_buf[i] = end_rv[j]; - } - else - { -#endif - if(n_chars>=n_chars_old) - for(int i=n_chars_old+1; i<=n_chars; ++i) - print_buf[i] = BAR_CHAR; - else - for(int i=n_chars+1; i<=n_chars_old; ++i) - print_buf[i] = ' '; - sprintf(&(print_buf[length+3])," %3i%%\r",pct_int); -#if defined (USE_TERM) - } -#endif - fputs(print_buf,stdout); - fflush(stdout); - n_chars_old = n_chars; - pct_int_old = pct_int; - } - } - return retval; -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |