# HG changeset patch # User Michael Goffioul # Date 1220902445 14400 # Node ID 4e7527a7b3f9c7043f0ebafee66a7a74706bc490 # Parent 3cc1ca1b15763610fa534b23a9c4fd70c280785e mkoctfile.cc.in, octave-config.cc.in, octave-bug.cc.in: new files diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-09-08 Michael Goffioul + + * mkoctfile.cc.in, octave-bug.cc.in, octave-config.cc.in: New files. + 2008-08-28 David Bateman * NEWS: Update for some of the graphics changes diff --git a/mkoctfile.cc.in b/mkoctfile.cc.in new file mode 100644 --- /dev/null +++ b/mkoctfile.cc.in @@ -0,0 +1,702 @@ +#if defined (HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) +#include +#ifdef _MSC_VER +#define popen _popen +#define pclose _pclose +#endif +#endif + +using namespace std; + +static bool initialized = false; +static map vars; + +static string OCTAVE_VERSION = %OCTAVE_CONF_VERSION%; + +static std::string substitute_prefix(const std::string& s, const std::string& prefix, const std::string& new_prefix) +{ + std::string retval = s; + + if (!prefix.empty() && new_prefix != prefix) + { + int len = prefix.length(); + if (retval.find(prefix) == 0) + retval.replace(0, len, new_prefix); + } + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + std::replace(retval.begin(), retval.end(), '/', '\\'); +#endif + + return retval; +} + +static string get_line(FILE *fp) +{ + static vector buf(100); + int idx = 0; + char c; + + while (1) + { + c = (char)fgetc(fp); + if (c == '\n' || c == EOF) + break; + if (buf.size() <= idx) + buf.resize(buf.size() + 100); + buf[idx++] = c; + } + if (idx == 0) + return string(""); + else + return string(&buf[0], idx); +} + + +static string get_variable(const char *name, const string& defval) +{ + const char *val = getenv(name); + if (val == NULL || val[0] == '\0') + return defval; + else + return string(val); +} + +static string quote_path(const string& s) +{ + if (s.find(' ') != string::npos && s[0] != '"') + return "\"" + s + "\""; + return s; +} + +static void initialize(void) +{ + if (initialized) + return; + + initialized = true; + + vars["OCTAVE_HOME"] = get_variable("OCTAVE_HOME", ""); + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + int n = 1024; + + std::string bin_dir (n, '\0'); + + while (true) + { + int status = GetModuleFileName (0, &bin_dir[0], n); + + if (status < n) + { + bin_dir.resize (status); + break; + } + else + { + n *= 2; + bin_dir.resize (n); + } + } + + if (! bin_dir.empty ()) + { + size_t pos = bin_dir.rfind ("\\bin\\"); + + if (pos != string::npos) + vars["OCTAVE_HOME"] = bin_dir.substr (0, pos); + } +#endif + + vars["SED"] = get_variable("SED", %OCTAVE_CONF_SED%); + + vars["OCTAVE_PREFIX"] = %OCTAVE_CONF_PREFIX%; + + std::string DEFAULT_OCTINCLUDEDIR = %OCTAVE_CONF_OCTINCLUDEDIR%; + std::string DEFAULT_INCLUDEDIR = %OCTAVE_CONF_INCLUDEDIR%; + std::string DEFAULT_LIBDIR = %OCTAVE_CONF_LIBDIR%; + std::string DEFAULT_OCTLIBDIR = %OCTAVE_CONF_OCTLIBDIR%; + + if (! vars["OCTAVE_HOME"].empty()) + { + DEFAULT_OCTINCLUDEDIR = substitute_prefix(DEFAULT_OCTINCLUDEDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + DEFAULT_INCLUDEDIR = substitute_prefix(DEFAULT_INCLUDEDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + DEFAULT_LIBDIR = substitute_prefix(DEFAULT_LIBDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + DEFAULT_OCTLIBDIR = substitute_prefix(DEFAULT_OCTLIBDIR, vars["OCTAVE_PREFIX"], vars["OCTAVE_HOME"]); + } + + vars["OCTINCLUDEDIR"] = get_variable("OCTINCLUDEDIR", DEFAULT_OCTINCLUDEDIR); + vars["INCLUDEDIR"] = get_variable("INCLUDEDIR", DEFAULT_INCLUDEDIR); + vars["LIBDIR"] = get_variable("LIBDIR", DEFAULT_LIBDIR); + vars["OCTLIBDIR"] = get_variable("OCTLIBDIR", DEFAULT_OCTLIBDIR); + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + std::string DEFAULT_INCFLAGS = "-I" + quote_path(vars["OCTINCLUDEDIR"]) + " -I" + quote_path(vars["OCTINCLUDEDIR"] + "\\octave"); +#else + std::string DEFAULT_INCFLAGS = "-I" + quote_path(vars["OCTINCLUDEDIR"]) + " -I" + quote_path(vars["OCTINCLUDEDIR"] + "/octave"); +#endif + if (vars["INCLUDEDIR"] != "/usr/include") + DEFAULT_INCFLAGS += " -I" + quote_path(vars["INCLUDEDIR"]); + + std::string DEFAULT_LFLAGS = "-L" + quote_path(vars["OCTLIBDIR"]); + if (vars["LIBDIR"] != "/usr/lib") + DEFAULT_LFLAGS += " -L" + quote_path(vars["LIBDIR"]); + + vars["CPPFLAGS"] = get_variable("CPPFLAGS", %OCTAVE_CONF_CPPFLAGS%); + vars["INCFLAGS"] = get_variable("INCFLAGS", DEFAULT_INCFLAGS); + vars["F2C"] = get_variable("F2C", %OCTAVE_CONF_F2C%); + vars["F2CFLAGS"] = get_variable("F2CFLAGS", %OCTAVE_CONF_F2CFLAGS%); + vars["F77"] = get_variable("F77", %OCTAVE_CONF_F77%); + vars["FFLAGS"] = get_variable("FFLAGS", %OCTAVE_CONF_FFLAGS%); + vars["FPICFLAG"] = get_variable("FPICFLAG", %OCTAVE_CONF_FPICFLAG%); + vars["CC"] = get_variable("CC", %OCTAVE_CONF_CC%); + vars["CFLAGS"] = get_variable("CFLAGS", %OCTAVE_CONF_CFLAGS%); + vars["CPICFLAG"] = get_variable("CPICFLAG", %OCTAVE_CONF_CPICFLAG%); + vars["CXX"] = get_variable("CXX", %OCTAVE_CONF_CXX%); + vars["CXXFLAGS"] = get_variable("CXXFLAGS", %OCTAVE_CONF_CXXFLAGS%); + vars["CXXPICFLAG"] = get_variable("CXXPICFLAG", %OCTAVE_CONF_CXXPICFLAG%); + vars["XTRA_CFLAGS"] = get_variable("XTRA_CFLAGS", %OCTAVE_CONF_XTRA_CFLAGS%); + vars["XTRA_CXXFLAGS"] = get_variable("XTRA_CXXFLAGS", %OCTAVE_CONF_XTRA_CXXFLAGS%); + + vars["DEPEND_FLAGS"] = get_variable("DEPEND_FLAGS", %OCTAVE_CONF_DEPEND_FLAGS%); + vars["DEPEND_EXTRA_SED_PATTERN"] = get_variable("DEPEND_EXTRA_SED_PATTERN", %OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%); + + vars["DL_LD"] = get_variable("DL_LD", %OCTAVE_CONF_DL_LD%); + vars["DL_LDFLAGS"] = get_variable("DL_LDFLAGS", %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%); + + vars["RLD_FLAG"] = get_variable("RLD_FLAG", %OCTAVE_CONF_RLD_FLAG%); + vars["RDYNAMIC_FLAG"] = get_variable("RDYNAMIC_FLAG", %OCTAVE_CONF_RDYNAMIC_FLAG%); + vars["LIBOCTAVE"] = "-loctave"; + vars["LIBOCTINTERP"] = "-loctinterp"; + vars["LIBREADLINE"] = "-lreadline"; + vars["LIBCRUFT"] = "-lcruft"; + vars["BLAS_LIBS"] = get_variable("BLAS_LIBS", %OCTAVE_CONF_BLAS_LIBS%); + vars["FFTW_LIBS"] = get_variable("FFTW_LIBS", %OCTAVE_CONF_FFTW_LIBS%); + vars["LIBS"] = get_variable("LIBS", %OCTAVE_CONF_LIBS%); + vars["FLIBS"] = get_variable("FLIBS", %OCTAVE_CONF_FLIBS%); + vars["LD_CXX"] = get_variable("LD_CXX", %OCTAVE_CONF_LD_CXX%); + vars["LDFLAGS"] = get_variable("LDFLAGS", %OCTAVE_CONF_LDFLAGS%); + vars["LD_STATIC_FLAG"] = get_variable("LD_STATIC_FLAG", %OCTAVE_CONF_LD_STATIC_FLAG%); + vars["LFLAGS"] = get_variable("LFLAGS", DEFAULT_LFLAGS); + + vars["ALL_FFLAGS"] = vars["FFLAGS"]; + + vars["ALL_CFLAGS"] = vars["INCFLAGS"] + " " + vars["XTRA_CFLAGS"] + " " + vars["CFLAGS"]; + + vars["ALL_CXXFLAGS"] = vars["INCFLAGS"] + " " + vars["XTRA_CXXFLAGS"] + " " + vars["CXXFLAGS"]; + + vars["ALL_LDFLAGS"] = vars["LD_STATIC_FLAG"] + " " + vars["CPICFLAG"] + " " + vars["LDFLAGS"]; + + vars["OCTAVE_LIBS"] = vars["LIBOCTINTERP"] + " " + vars["LIBOCTAVE"] + " " + vars["SPECIAL_MATH_LIB"] + " " + vars["LIBCRUFT"]; +} + +static string usage_msg = "usage: mkoctfile [options] file ..."; +static string version_msg = "mkoctfile, version " + OCTAVE_VERSION; +static bool debug = false; +static string help_msg = +"\n" +"Options:\n" +"\n" +" -h, -?, --help Print this message.\n" +"\n" +" -IDIR Add -IDIR to compile commands.\n" +"\n" +" -idirafter DIR Add -idirafter DIR to compile commands.\n" +"\n" +" -DDEF Add -DDEF to compile commands.\n" +"\n" +" -lLIB Add library LIB to link command.\n" +"\n" +" -LDIR Add -LDIR to link command.\n" +"\n" +" -M, --depend Generate dependency files (.d) for C and C++\n" +" source files.\n" +"\n" +" -RDIR Add -RDIR to link command.\n" +"\n" +" -Wl,... Pass flags though the linker like -Wl,-rpath=...\n" +"\n" +" -W... Pass flags though the compiler like -Wa,OPTION.\n" +"\n" +" -c, --compile Compile, but do not link.\n" +"\n" +" -o FILE, --output FILE Output file name. Default extension is .oct\n" +" (or .mex if --mex is specified) unless linking\n" +" a stand-alone executable.\n" +"\n" +" -g Enable debugging options for compilers.\n" +"\n" +" -p VAR, --print VAR Print configuration variable VAR. Recognized\n" +" variables are:\n" +"\n" +" ALL_CFLAGS FFTW_LIBS \n" +" ALL_CXXFLAGS FLIBS \n" +" ALL_FFLAGS FPICFLAG \n" +" ALL_LDFLAGS INCFLAGS \n" +" BLAS_LIBS LDFLAGS \n" +" CC LD_CXX \n" +" CFLAGS LD_STATIC_FLAG\n" +" CPICFLAG LFLAGS \n" +" CPPFLAGS LIBCRUFT \n" +" CXX LIBOCTAVE \n" +" CXXFLAGS LIBOCTINTERP \n" +" CXXPICFLAG LIBREADLINE \n" +" DEPEND_EXTRA_SED_PATTERN LIBS \n" +" DEPEND_FLAGS OCTAVE_LIBS \n" +" DL_LD RDYNAMIC_FLAG \n" +" DL_LDFLAGS RLD_FLAG \n" +" F2C SED \n" +" F2CFLAGS XTRA_CFLAGS \n" +" F77 XTRA_CXXFLAGS \n" +" FFLAGS\n" +"\n" +" --link-stand-alone Link a stand-alone executable file.\n" +"\n" +" --mex Assume we are creating a MEX file. Set the\n" +" default output extension to \".mex\".\n" +"\n" +" -s, --strip Strip output file.\n" +"\n" +" -v, --verbose Echo commands as they are executed.\n" +"\n" +" FILE Compile or link FILE. Recognized file types are:\n" +"\n" +" .c C source\n" +" .cc C++ source\n" +" .C C++ source\n" +" .cpp C++ source\n" +" .f Fortran source (fixed form)\n" +" .F Fortran source (fixed form)\n" +" .f90 Fortran source (free form)\n" +" .F90 Fortran source (free form)\n" +" .o object file\n" +" .a library file\n" +#ifdef _MSC_VER +" .lib library file\n" +#endif +"\n"; + +static string basename(const string& s, bool strip_path = false) +{ + size_t pos = s.rfind('.'); + string retval; + + if (pos == string::npos) + retval = s; + else + retval = s.substr(0, pos); + if (strip_path) + { + size_t p1 = retval.rfind('/'), p2 = retval.rfind('\\'); + pos = (p1 != string::npos && p2 != string::npos ? max(p1, p2) : (p2 != string::npos ? p2 : p1)); + if (pos != string::npos) + retval = retval.substr(0, pos); + } + return retval; +} + +inline bool starts_with(const string& s, const string& prefix) +{ + return (s.length() >= prefix.length() && s.find(prefix) == 0); +} + +inline bool ends_with(const string& s, const string& suffix) +{ + return (s.length() >= suffix.length() && s.rfind(suffix) == s.length()-suffix.length()); +} + +static int run_command(const string& cmd) +{ + if (debug) + cout << cmd << endl; + return system(cmd.c_str()); +} + +int main(int argc, char **argv) +{ + initialize(); + + string objfiles, libfiles, octfile, outputfile, incflags, defs, ldflags, pass_on_options, output_ext, file, output_option, cmd; + bool strip, no_oct_file_strip_on_this_platform, link, link_stand_alone, depend, compile; + list cfiles, ccfiles, f77files; + int result = 0; + + //cfiles = ""; + //ccfiles = ""; + //f77files = ""; + objfiles = ""; + libfiles = ""; + octfile = ""; + outputfile = ""; + incflags = ""; + defs = ""; + ldflags = ""; + pass_on_options = ""; + strip = false; + no_oct_file_strip_on_this_platform = %NO_OCT_FILE_STRIP%; + link = true; + link_stand_alone = false; + output_ext = ".oct"; + depend = false; + compile = true; + + if (argc == 1) + { + cout << usage_msg << endl; + return 1; + } + + if (argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))) + { + cout << version_msg << endl; + return 0; + } + + for (int i=1; i::const_iterator it; + + if (depend) + { + for (it=cfiles.begin(); it!=cfiles.end(); ++it) + { + string f = *it, dfile = basename(f) + ".d", line; + + unlink(dfile.c_str()); + cmd = vars["CC"] + " " + vars["DEPEND_FLAGS"] + " " + vars["CPPFLAGS"] + " " + + vars["ALL_CFLAGS"] + " " + incflags + " " + defs + " " + quote_path(f); + + FILE *fd = popen(cmd.c_str(), "r"); + ofstream fo(dfile.c_str()); + int pos; + while (!feof(fd)) + { + line = get_line(fd); + if ((pos=line.rfind(".o:")) != string::npos) + { + int spos = line.rfind('/', pos); + string ofile = (spos == string::npos ? line.substr(0, pos+2) : line.substr(spos+1, pos-spos+1)); + fo << "pic/" << ofile << " " << ofile << " " << dfile << line.substr(pos) << endl; + } + else + fo << line << endl; + } + pclose(fd); + fo.close(); + } + + for (it=ccfiles.begin(); it!=ccfiles.end(); ++it) + { + string f = *it, dfile = basename(f) + ".d", line; + + unlink(dfile.c_str()); + cmd = vars["CC"] + " " + vars["DEPEND_FLAGS"] + " " + vars["CPPFLAGS"] + " " + + vars["ALL_CXXFLAGS"] + " " + incflags + " " + defs + " " + quote_path(f); + + FILE *fd = popen(cmd.c_str(), "r"); + ofstream fo(dfile.c_str()); + int pos; + while (!feof(fd)) + { + line = get_line(fd); + if ((pos=line.rfind(".o:")) != string::npos) + { + int spos = line.rfind('/', pos); + string ofile = (spos == string::npos ? line.substr(0, pos+2) : line.substr(spos+1, pos-spos+1)); + fo << "pic/" << ofile << " " << ofile << " " << dfile << line.substr(pos+2) << endl; + } + else + fo << line << endl; + } + pclose(fd); + fo.close(); + } + + return 0; + } + + for (it=f77files.begin(); it!=f77files.end(); ++it) + { + string f = *it, b = basename(f); + if (!vars["F2C"].empty() && vars["F2C"] != "@F2C@") + { + string c = b + ".c"; + cfiles.push_back(c); + cmd = vars["F2C"] + " " + vars["F2CFLAGS"] + " < " + f + " > " + c; + result = run_command(cmd); + } + else if (!vars["F77"].empty()) + { + string o; + if (!outputfile.empty()) + { + if (link) + o = b + ".o"; + else + o = outputfile; + } + else + o = b + ".o"; + objfiles += (" " + o); + cmd = vars["F77"] + " -c " + vars["FPICFLAG"] + " " + vars["ALL_FFLAGS"] + " " + incflags + " " + defs + " " + + pass_on_options + " " + f + " -o " + o; + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to compile Fortran file " << f << endl; + return 1; + } + } + + for (it=cfiles.begin(); it!=cfiles.end(); ++it) + { + string f = *it; + if (!vars["CC"].empty()) + { + string b = basename(f), o; + if (!outputfile.empty()) + { + if (link) + o = b + ".o"; + else + o = outputfile; + } + else + o = b + ".o"; + objfiles += (" " + o); + cmd = vars["CC"] + " -c " + vars["CPPFLAGS"] + " " + vars["CPICFLAG"] + " " + vars["ALL_CFLAGS"] + " " + + pass_on_options + " " + incflags + " " + defs + " " + quote_path(f) + " -o " + quote_path(o); + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to compile C file " << f << endl; + return 1; + } + } + + for (it=ccfiles.begin(); it!=ccfiles.end(); ++it) + { + string f = *it; + if (!vars["CXX"].empty()) + { + string b = basename(f), o; + if (!outputfile.empty()) + { + if (link) + o = b + ".o"; + else + o = outputfile; + } + else + o = b + ".o"; + objfiles += (" " + o); + cmd = vars["CXX"] + " -c " + vars["CPPFLAGS"] + " " + vars["CXXPICFLAG"] + " " + vars["ALL_CXXFLAGS"] + " " + + pass_on_options + " " + incflags + " " + defs + " " + quote_path(f) + " -o " + quote_path(o); + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to compile C++ file " << f << endl; + return 1; + } + } + + if (link && !objfiles.empty()) + { + if (link_stand_alone) + { + if (!vars["LD_CXX"].empty()) + { + cmd= vars["LD_CXX"] + " " + vars["CPPFLAGS"] + " " + vars["ALL_CXXFLAGS"] + " " + vars["RDYNAMIC_FLAG"] + " " + + vars["ALL_LDFLAGS"] + " " + pass_on_options + " " + output_option + " " + objfiles + " " + libfiles + " " + + ldflags + " " + vars["LFLAGS"] + " " + vars["RLD_FLAG"] + " " + vars["OCTAVE_LIBS"] + " " + + vars["BLAS_LIBS"] + " " + vars["FFTW_LIBS"] + " " + vars["LIBREADLINE"] + " " + vars["LIBS"] + " " + + vars["FLIBS"]; + result = run_command(cmd); + } + else + { + cerr << "mkoctfile: no way to link stand-alone executable file" << endl; + return 1; + } + } + else + { + string LINK_DEPS = vars["LFLAGS"] + " " + vars["OCTAVE_LIBS"] + " " + vars["LDFLAGS"] + " " + vars["BLAS_LIBS"] + " " + + vars["FFTW_LIBS"] + " " + vars["LIBS"] + " " + vars["FLIBS"]; + cmd = vars["DL_LD"] + " " + vars["DL_LDFLAGS"] + " " + pass_on_options + " -o " + octfile + " " + objfiles + " " + + libfiles + " " + ldflags + " " + LINK_DEPS; + result = run_command(cmd); + } + + if (strip) + { + cmd = "strip " + octfile; + result = run_command(cmd); + } + } + + return result; +} diff --git a/octave-bug.cc.in b/octave-bug.cc.in new file mode 100644 --- /dev/null +++ b/octave-bug.cc.in @@ -0,0 +1,324 @@ +/* + +Copyright (C) 2008 Michael Goffioul + +This file is part of Octave. + +Octave 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. + +Octave 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 Octave; see the file COPYING. If not, see +. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; + +static map vars; + +static void +usage (void) +{ + cerr << "usage: octave-bug [-s subject]" << endl; + exit (-1); +} + +static void +error (const string& msg) +{ + cerr << "error: " << msg << endl; + exit (-1); +} + +static void +warning (const string& msg) +{ + cerr << "warning: " << msg << endl; +} + +static string +get_env_variable (char *name) +{ + char *value = ::getenv (name); + if (value) + return string (value); + else + return string (""); +} + +inline bool starts_with(const string& s, const string& prefix) +{ + return (s.length() >= prefix.length() && s.find(prefix) == 0); +} + +int main (int argc, char **argv) +{ + int arg_idx = 1; + + vars["config_optvars"]=%OCTAVE_CONF_config_opts%; + vars["VERSION"]=%OCTAVE_CONF_VERSION%; + vars["SED"]=%OCTAVE_CONF_SED%; + vars["MACHINE"]=%OCTAVE_CONF_CANONICAL_HOST_TYPE%; + vars["F77"]=%OCTAVE_CONF_F77%; + vars["FFLAGS"]=%OCTAVE_CONF_FFLAGS%; + vars["FPICFLAG"]=%OCTAVE_CONF_FPICFLAG%; + vars["FLIBS"]=%OCTAVE_CONF_FLIBS%; + vars["F2C"]=%OCTAVE_CONF_F2C%; + vars["F2CFLAGS"]=%OCTAVE_CONF_F2CFLAGS%; + vars["CPPFLAGS"]=%OCTAVE_CONF_CPPFLAGS%; + vars["INCFLAGS"]=%OCTAVE_CONF_INCFLAGS%; + vars["CC"]=%OCTAVE_CONF_CC%; + vars["CC_VERSION"]=%OCTAVE_CONF_CC_VERSION%; + vars["CFLAGS"]=%OCTAVE_CONF_CFLAGS%; + vars["CPICFLAG"]=%OCTAVE_CONF_CPICFLAG%; + vars["CXX"]=%OCTAVE_CONF_CXX%; + vars["CXX_VERSION"]=%OCTAVE_CONF_CXX_VERSION%; + vars["CXXFLAGS"]=%OCTAVE_CONF_CXXFLAGS%; + vars["CXXPICFLAG"]=%OCTAVE_CONF_CXXPICFLAG%; + vars["LD_CXX"]=%OCTAVE_CONF_LD_CXX%; + vars["LDFLAGS"]=%OCTAVE_CONF_LDFLAGS%; + vars["LIBFLAGS"]=%OCTAVE_CONF_LIBFLAGS%; + vars["RLD_FLAG"]=%OCTAVE_CONF_RLD_FLAG%; + vars["LIBS"]=%OCTAVE_CONF_LIBS%; + vars["BLAS_LIBS"]=%OCTAVE_CONF_BLAS_LIBS%; + vars["FFTW_LIBS"]=%OCTAVE_CONF_FFTW_LIBS%; + vars["LEXLIB"]=%OCTAVE_CONF_LEXLIB%; + vars["LIBGLOB"]=%OCTAVE_CONF_LIBGLOB%; + vars["DEFS"]=%OCTAVE_CONF_DEFS%; + + vars["USER"] = get_env_variable ("LOGNAME"); + if (vars["USER"].empty ()) + vars["USER"] = get_env_variable ("USERNAME"); + + vars["CC_AND_VERSION"] = (vars["CC"] + ", version" + vars["CC_VERSION"]); + + vars["CXX_AND_VERSION"] = (vars["CXX"] + ", version" + vars["CXX_VERSION"]); + + /* FIXME: could be obtain from OS */ + vars["UN"] = "Windows"; + + if (starts_with (vars["VERSION"], "ss")) + vars["BUGADDR"] = "maintainers@octave.org"; + else + { + /* FIXME: shell script contains more, but I don't get the logic */ + vars["BUGADDR"] = "bug@octave.org"; + } + + vars["SUBJECT"] = "[50 character or so descriptive subject here (for reference)]"; + if (arg_idx < argc && strcmp (argv[arg_idx], "-s") == 0) + { + arg_idx++; + if (arg_idx < argc) + vars["SUBJECT"] = argv[arg_idx++]; + else + usage (); + } + + ostringstream os; + + os << "Bug report for Octave " << vars["VERSION"] << " configured for " << vars["MACHINE"] << endl; + os << endl; + os << "Description:" << endl; + os << "-----------" << endl; + os << endl; + os << " * Please replace this item with a detailed description of the" << endl; + os << " problem. Suggestions or general comments are also welcome." << endl; + os << endl; + os << "Repeat-By:" << endl; + os << "---------" << endl; + os << endl; + os << " * Please replace this item with a description of the sequence of" << endl; + os << " events that causes the problem to occur. " << endl; + os << endl; + os << "Fix:" << endl; + os << "---" << endl; + os << endl; + os << " * If possible, replace this item with a description of how to" << endl; + os << " fix the problem (if you don't have a fix for the problem, don't" << endl; + os << " include this section, but please do submit your report anyway)." << endl; + os << endl; + os << endl; + os << endl; + os << "Configuration (please do not edit this section):" << endl; + os << "-----------------------------------------------" << endl; + os << endl; + os << "uname output: " << vars["UN"] << endl; + os << "configure opts: " << vars["config_opts"] << endl; + os << "Fortran compiler: " << vars["F77"] << endl; + os << "FFLAGS: " << vars["FFLAGS"] << endl; + os << "F2C: " << vars["F2C"] << endl; + os << "F2CFLAGS: " << vars["F2CFLAGS"] << endl; + os << "FLIBS: " << vars["FLIBS"] << endl; + os << "CPPFLAGS: " << vars["CPPFLAGS"] << endl; + os << "INCFLAGS: " << vars["INCFLAGS"] << endl; + os << "C compiler: " << vars["CC_AND_VERSION"] << endl; + os << "CFLAGS: " << vars["CFLAGS"] << endl; + os << "CPICFLAG: " << vars["CPICFLAG"] << endl; + os << "C++ compiler: " << vars["CXX_AND_VERSION"] << endl; + os << "CXXFLAGS: " << vars["CXXFLAGS"] << endl; + os << "CXXPICFLAG: " << vars["CXXPICFLAG"] << endl; + os << "LD_CXX: " << vars["LD_CXX"] << endl; + os << "LDFLAGS: " << vars["LDFLAGS"] << endl; + os << "LIBFLAGS: " << vars["LIBFLAGS"] << endl; + os << "RLD_FLAG: " << vars["RLD_FLAG"] << endl; + os << "BLAS_LIBS: " << vars["BLAS_LIBS"] << endl; + os << "FFTW_LIBS: " << vars["FFTW_LIBS"] << endl; + os << "LIBS: " << vars["LIBS"] << endl; + os << "LEXLIB: " << vars["LEXLIB"] << endl; + os << "LIBGLOB: " << vars["LIBGLOB"] << endl; + os << "SED: " << vars["SED"] << endl; + os << "DEFS:" << endl << vars["DEFS"] << endl; + os << endl; + + if (arg_idx < argc) + { + os << endl; + os << "User-preferences (please do not edit this section):" << endl; + os << endl; + + ifstream is (argv[arg_idx++]); + + if (! is.fail ()) + { + string line; + + while (! is.eof ()) + { + getline (is, line); + os << line << endl; + } + } + else + { + string msg ("unable to open file for reading: "); + + msg += argv[arg_idx-1]; + warning (msg); + } + } + + string content = os.str (), msg; + + // Now go for MAPI stuff + + HMODULE hMapi; + LHANDLE session; + LPMAPILOGON mapiLogon; + LPMAPILOGOFF mapiLogoff; + LPMAPISENDMAIL mapiSendMail; + + hMapi = LoadLibrary ("mapi32.dll"); + if (hMapi != NULL) + { + mapiLogon = (LPMAPILOGON) GetProcAddress (hMapi, "MAPILogon"); + mapiLogoff = (LPMAPILOGOFF) GetProcAddress (hMapi, "MAPILogoff"); + mapiSendMail = (LPMAPISENDMAIL) GetProcAddress (hMapi, "MAPISendMail"); + + if (mapiLogon != NULL && mapiLogoff != NULL + && mapiSendMail != NULL) + { + ULONG result = 0; + + if ((result = mapiLogon (0, "", "", MAPI_LOGON_UI, 0, &session)) == SUCCESS_SUCCESS) + { + MapiMessage mmsg; + MapiRecipDesc mrecip[2]; + + ZeroMemory (&mmsg, sizeof (mmsg)); + ZeroMemory (&mrecip, sizeof (mrecip)); + + mmsg.lpszSubject = strdup (vars["SUBJECT"].c_str ()); + mmsg.lpszNoteText = strdup (content.c_str ()); + mmsg.nRecipCount = 1; + mmsg.lpRecips = mrecip; + + mrecip[0].ulRecipClass = MAPI_TO; + mrecip[0].lpszName = "Octave"; + mrecip[0].lpszAddress = strdup (vars["BUGADDR"].c_str ()); + + if (! vars["USER"].empty ()) + { + mmsg.nRecipCount = 2; + mrecip[1].ulRecipClass = MAPI_CC; + mrecip[1].lpszName = strdup (vars["USER"].c_str ()); + } + + if ((result = mapiSendMail (session, 0, &mmsg, MAPI_DIALOG, 0)) != SUCCESS_SUCCESS + && result != MAPI_USER_ABORT) + msg = "mail not sent"; + + free (mmsg.lpszSubject); + free (mmsg.lpszNoteText); + free (mrecip[0].lpszAddress); + if (mmsg.nRecipCount > 1) + free (mrecip[1].lpszName); + + mapiLogoff (session, 0, 0, 0); + } + else + msg = "cannot logon to MAPI service"; + + if (! msg.empty ()) + { + char buf[64]; + _snprintf (buf, 63, "%08x", result); + msg += (" (result: " + string (buf) + ")"); + } + } + else + msg = "cannot find entry points in MAPI library"; + + FreeLibrary (hMapi); + } + else + msg = "unable to find MAPI service"; + + if (! msg.empty ()) + { + warning (msg); + + string tmpfile = _tempnam (NULL, "octave-"); + ofstream ofs (tmpfile.c_str ()); + + if (! ofs.fail ()) + { + ofs << content; + ofs.close (); + + warning (""); + warning ("the mail could not be sent to octave; a text editor should appear"); + warning ("with the content of the bug report; please copy it and paste it"); + warning ("manually into your mail client and send it to the following"); + warning ("address: " + vars["BUGADDR"]); + + string cmd ("notepad "); + + cmd += tmpfile; + ::system (cmd.c_str ()); + ::unlink (tmpfile.c_str ()); + } + else + error ("unable to open file for writing: " + tmpfile); + } + + return 0; +} diff --git a/octave-config.cc.in b/octave-config.cc.in new file mode 100644 --- /dev/null +++ b/octave-config.cc.in @@ -0,0 +1,197 @@ +#if defined (HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include +#include +#include + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) +#include +#endif + +static bool initialized = false; +static std::map vars; +static std::string OCTAVE_HOME, PREFIX; +static std::string usage_msg = "usage: octave-config [options]"; +static std::string help_msg = +"\n" +"Options:\n" +"\n" +" -h, -?, --help Print this message.\n" +"\n" +" --m-site-dir Print the name of the directory where Octave\n" +" expects to find locally installed .m files.\n" +"\n" +" --oct-site-dir Print the name of the directory where Octave\n" +" expects to find locally installed .oct files.\n" +"\n" +" -p VAR, --print VAR Print the value of the given configuration\n" +" variable VAR. Recognized variables are:\n" +"\n" +" API_VERSION LOCALAPIARCHLIBDIR\n" +" CANONICAL_HOST_TYPE LOCALAPIFCNFILEDIR\n" +" DEFAULT_PAGER LOCALAPIOCTFILEDIR\n" +" ARCHLIBDIR LOCALARCHLIBDIR\n" +" BINDIR LOCALFCNFILEDIR\n" +" DATADIR LOCALOCTFILEDIR\n" +" DATAROOTDIR LOCALSTARTUPFILEDIR\n" +" EXEC_PREFIX LOCALVERARCHLIBDIR\n" +" FCNFILEDIR LOCALVERFCNFILEDIR\n" +" LOCALVEROCTFILEDIR MAN1DIR\n" +" IMAGEDIR MANDIR\n" +" MAN1EXT OCTFILEDIR\n" +" INCLUDEDIR OCTINCLUDEDIR\n" +" INFODIR OCTLIBDIR\n" +" INFOFILE PREFIX\n" +" LIBDIR STARTUPFILEDIR\n" +" LIBEXECDIR VERSION\n" +"\n" +" -v, --version Print the Octave version number.\n" +"\n"; + +static std::string substitute_prefix(const std::string& s, const std::string& prefix, const std::string new_prefix) +{ + std::string retval = s; + + if (!prefix.empty() && new_prefix != prefix) + { + int len = prefix.length(); + if (retval.find(prefix) == 0) + retval.replace(0, len, new_prefix); + } + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + std::replace(retval.begin(), retval.end(), '/', '\\'); +#endif + + return retval; +} + +static void initialize(void) +{ + if (initialized) + return; + + initialized = true; + + const char *homestr = getenv("OCTAVE_HOME"); + OCTAVE_HOME = (homestr ? homestr : ""); + PREFIX = %OCTAVE_PREFIX%; + +#if defined (__WIN32__) && ! defined (_POSIX_VERSION) + int n = 1024; + + std::string bin_dir (n, '\0'); + + while (true) + { + int status = GetModuleFileName (0, &bin_dir[0], n); + + if (status < n) + { + bin_dir.resize (status); + break; + } + else + { + n *= 2; + bin_dir.resize (n); + } + } + + if (! bin_dir.empty ()) + { + size_t pos = bin_dir.rfind ("\\bin\\"); + + if (pos != std::string::npos) + OCTAVE_HOME = bin_dir.substr (0, pos); + } +#endif + + vars["API_VERSION"] = %OCTAVE_API_VERSION%; + vars["CANONICAL_HOST_TYPE"] = %OCTAVE_CANONICAL_HOST_TYPE%; + vars["DEFAULT_PAGER"] = %OCTAVE_DEFAULT_PAGER%; + vars["ARCHLIBDIR"] = substitute_prefix (%OCTAVE_ARCHLIBDIR%, PREFIX, OCTAVE_HOME); + vars["BINDIR"] = substitute_prefix (%OCTAVE_BINDIR%, PREFIX, OCTAVE_HOME); + vars["DATADIR"] =substitute_prefix (%OCTAVE_DATADIR%, PREFIX, OCTAVE_HOME); + vars["DATAROOTDIR"] =substitute_prefix (%OCTAVE_DATAROOTDIR%, PREFIX, OCTAVE_HOME); + vars["EXEC_PREFIX"] =substitute_prefix (%OCTAVE_EXEC_PREFIX%, PREFIX, OCTAVE_HOME); + vars["FCNFILEDIR"] =substitute_prefix (%OCTAVE_FCNFILEDIR%, PREFIX, OCTAVE_HOME); + vars["IMAGEDIR"] =substitute_prefix (%OCTAVE_IMAGEDIR%, PREFIX, OCTAVE_HOME); + vars["INCLUDEDIR"] =substitute_prefix (%OCTAVE_INCLUDEDIR%, PREFIX, OCTAVE_HOME); + vars["INFODIR"] =substitute_prefix (%OCTAVE_INFODIR%, PREFIX, OCTAVE_HOME); + vars["INFOFILE"] =substitute_prefix (%OCTAVE_INFOFILE%, PREFIX, OCTAVE_HOME); + vars["LIBDIR"] =substitute_prefix (%OCTAVE_LIBDIR%, PREFIX, OCTAVE_HOME); + vars["LIBEXECDIR"] =substitute_prefix (%OCTAVE_LIBEXECDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALAPIARCHLIBDIR"] =substitute_prefix (%OCTAVE_LOCALAPIARCHLIBDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALAPIFCNFILEDIR"] =substitute_prefix (%OCTAVE_LOCALAPIFCNFILEDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALAPIOCTFILEDIR"] =substitute_prefix (%OCTAVE_LOCALAPIOCTFILEDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALARCHLIBDIR"] =substitute_prefix (%OCTAVE_LOCALARCHLIBDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALFCNFILEDIR"] =substitute_prefix (%OCTAVE_LOCALFCNFILEDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALOCTFILEDIR"] =substitute_prefix (%OCTAVE_LOCALOCTFILEDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALSTARTUPFILEDIR"] =substitute_prefix (%OCTAVE_LOCALSTARTUPFILEDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALVERARCHLIBDIR"] =substitute_prefix (%OCTAVE_LOCALVERARCHLIBDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALVERFCNFILEDIR"] =substitute_prefix (%OCTAVE_LOCALVERFCNFILEDIR%, PREFIX, OCTAVE_HOME); + vars["LOCALVEROCTFILEDIR"] =substitute_prefix (%OCTAVE_LOCALVEROCTFILEDIR%, PREFIX, OCTAVE_HOME); + vars["MAN1DIR"] =substitute_prefix (%OCTAVE_MAN1DIR%, PREFIX, OCTAVE_HOME); + vars["MAN1EXT"] = %OCTAVE_MAN1EXT%; + vars["MANDIR"] =substitute_prefix (%OCTAVE_MANDIR%, PREFIX, OCTAVE_HOME); + vars["OCTFILEDIR"] =substitute_prefix (%OCTAVE_OCTFILEDIR%, PREFIX, OCTAVE_HOME); + vars["OCTINCLUDEDIR"] =substitute_prefix (%OCTAVE_OCTINCLUDEDIR%, PREFIX, OCTAVE_HOME); + vars["OCTLIBDIR"] =substitute_prefix (%OCTAVE_OCTLIBDIR%, PREFIX, OCTAVE_HOME); + vars["PREFIX"] = (OCTAVE_HOME.empty() ? PREFIX : OCTAVE_HOME); + vars["STARTUPFILEDIR"] =substitute_prefix (%OCTAVE_STARTUPFILEDIR%, PREFIX, OCTAVE_HOME); + vars["VERSION"] = %OCTAVE_VERSION%; +} + +int main(int argc, char **argv) +{ + initialize(); + + if (argc == 1) + { + std::cout << usage_msg << std::endl; + return 1; + } + + for (int i=1; i