diff --git a/Allwmake.mingw b/Allwmake.mingw new file mode 100644 index 000000000..4e269f909 --- /dev/null +++ b/Allwmake.mingw @@ -0,0 +1,76 @@ +#!/bin/sh +#----------------------------------*-sh-*-------------------------------------- +# ========= | +# \\ / F ield | foam-extend: Open Source CFD +# \\ / O peration | Version: 3.2 +# \\ / A nd | Web: http://www.foam-extend.org +# \\/ M anipulation | For copyright notice see file Copyright +#------------------------------------------------------------------------------ +# License +# This file is part of foam-extend. +# +# foam-extend 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. +# +# foam-extend 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 foam-extend. If not, see . +# +# Script +# Allwmake.mingw +# +# Description +# Top-level build script for use with MSYS shell for MinGW-based builds on Windows. +# +# Author: +# Cesare Guardino, Alstom Power Ltd., (2015) +# +#------------------------------------------------------------------------------ + +cd ${0%/*} || exit 1 # run from this directory + +echo +echo "======================== FOAM-EXTEND MINGW WINDOWS TOP-LEVEL BUILD SCRIPT ========================" + +if [ "$PWD" != "$WM_PROJECT_DIR" ] +then + echo "Error: Current directory is not \$WM_PROJECT_DIR" + echo " The environment variable are not consistent with the installation." + echo " Check the OpenFOAM entries in your dot-files and source them." + exit 1 +fi + +cd $WM_PROJECT_DIR/ThirdParty/mingwBuild +echo +echo "In directory `pwd`" +echo "Configuring your OpenMPI installation ..." +./configure_OpenMPI.sh +PACKAGES_DIR=$WM_PROJECT_DIR/ThirdParty/packages +if [ -d $PACKAGES_DIR ] ; then + echo "Third-party dependencies packages $PACKAGES_DIR already exists." +else + echo "Building third-party dependencies ... (see `pwd`/build.log)" + ./build.sh > build.log 2>&1 + echo "Installing third-party dependencies ..." + rm -rf $PACKAGES_DIR + mv x64/install $PACKAGES_DIR +fi + +cd $WM_PROJECT_DIR +echo +echo "In directory `pwd`" +echo "Build foam-extend ... (see `pwd`/Allwmake.log)" +./Allwmake > Allwmake.log 2>&1 +echo "Copying MinGW dependencies to $FOAM_APPBIN ..." +cp -p $MINGW_HOME/bin/libgcc_s_seh-1.dll $FOAM_APPBIN +cp -p $MINGW_HOME/bin/libstdc++-6.dll $FOAM_APPBIN +cp -p $MINGW_HOME/bin/libwinpthread-1.dll $FOAM_APPBIN + +echo +echo "All done!" diff --git a/ThirdParty/mingwBuild/build.sh b/ThirdParty/mingwBuild/build.sh new file mode 100644 index 000000000..96919484d --- /dev/null +++ b/ThirdParty/mingwBuild/build.sh @@ -0,0 +1,293 @@ +#!/bin/sh +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | foam-extend: Open Source CFD +# \\ / O peration | Version: 3.2 +# \\ / A nd | Web: http://www.foam-extend.org +# \\/ M anipulation | For copyright notice see file Copyright +#------------------------------------------------------------------------------ +# License +# This file is part of foam-extend. +# +# foam-extend 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. +# +# foam-extend 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 foam-extend. If not, see . +# +# Script +# build.sh +# +# Description +# Downloads, extracts, builds and installs thirdy-party dependencies. +# +# Author: +# Cesare Guardino, Alstom Power Ltd., (2015) +# +#------------------------------------------------------------------------------ + +# {{{ DEFINE UTILITY FUNCTIONS +download() { + file=$1 + url=$2 + + if [ -f $BUILD_HOME/downloads/$file ] ; then + echo "Using already existing file $BUILD_HOME/downloads/$file" + else + wget --no-check-certificate $url -O $BUILD_HOME/downloads/$file + fi +} + +extract() { + file=$1 + program=$2 + + cp -p $BUILD_HOME/downloads/$file . + package=`basename $file` + if [ "$program" = "7zip" ] ; then + "$ZIP_EXE" x $package + else + $program -cd $package | tar xvf - + fi + rm $package +} + +unzip_dir() { + dir=$1 + + mkdir $dir + cd $dir + extract $dir.zip 7zip + cd .. +} + +patch() { + dir=$1 + + cp -rp $BUILD_HOME/$ARCH/patches/$dir . +} + +mkchk() { + dir=$1 + + if [ ! -d $dir ] ; then + mkdir $dir + fi +} + +mkdel() { + dir=$1 + + rm -rf $dir > /dev/null 2>&1 + mkdir $dir +} +# }}} + +# {{{ DEFINE PROCESS FUNCTIONS +start() { + echo "======================== FOAM-EXTEND THIRD-PARTY DEPENDENCIES WINDOWS BUILD SCRIPT ========================" +} + +initialise() { + echo "" + + if [ ! "$MINGW_HOME" ] ; then + echo "*** ERROR: MINGW_HOME environment variable not specified." + exit 1 + else + echo "Using MINGW_HOME=$MINGW_HOME" + fi + + BUILD_HOME=`pwd` + ZIP_EXE="7z.exe" + ARCH="x64" + + BUILD_DIR=$BUILD_HOME/$ARCH/build + INSTALL_DIR=$BUILD_HOME/$ARCH/install + OUT_DIR=$BUILD_HOME/$ARCH/output + + mkchk $BUILD_HOME/downloads + + echo "" + echo "All stdout/stderr output is redirected to the directory $OUT_DIR" + echo "All builds occur in the directory $BUILD_DIR" + echo "The script will install the completed builds in the directory $INSTALL_DIR" +} + +cleanup() { + echo "" + echo "Removing previous builds ..." + + mkdel $BUILD_DIR + mkdel $INSTALL_DIR + mkdel $OUT_DIR +} + +build_library() { + PACKAGE=$1 + + echo "- Building $PACKAGE ..." + LOG_FILE=$OUT_DIR/$PACKAGE.log + cd $BUILD_DIR + + case $PACKAGE in + + dlfcn-win32-master) + download $PACKAGE.zip https://github.com/dlfcn-win32/dlfcn-win32/archive/master.zip > $LOG_FILE 2>&1 + extract $PACKAGE.zip 7zip >> $LOG_FILE 2>&1 + cd $PACKAGE + ./configure --prefix=$INSTALL_DIR/system >> $LOG_FILE 2>&1 + make >> $LOG_FILE 2>&1 + mkdir $INSTALL_DIR/system + make install >> $LOG_FILE 2>&1 + ;; + + system) + cd $INSTALL_DIR + patch system + ;; + + pthreads-w32-2-9-1-release) + download $PACKAGE.zip ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-9-1-release.zip > $LOG_FILE 2>&1 + unzip_dir $PACKAGE >> $LOG_FILE 2>&1 + patch $PACKAGE + ;; + + metis-5.1.0) + download $PACKAGE.tar.gz http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/$PACKAGE.tar.gz > $LOG_FILE 2>&1 + extract "$PACKAGE.tar.gz" gzip >> $LOG_FILE 2>&1 + patch $PACKAGE + cd $PACKAGE + mkdir build/windows + cd build/windows + cmake -G "MSYS Makefiles" -DCMAKE_CONFIGURATION-TYPES="Release" -DGKLIB_PATH="../../GKlib" ../.. >> $LOG_FILE 2>&1 + make >> $LOG_FILE 2>&1 + mkdir $INSTALL_DIR/$PACKAGE + mkdir $INSTALL_DIR/$PACKAGE/bin + mkdir $INSTALL_DIR/$PACKAGE/include + mkdir $INSTALL_DIR/$PACKAGE/lib + cp -p programs/*.exe $INSTALL_DIR/$PACKAGE/bin + cp -p ../../include/metis.h $INSTALL_DIR/$PACKAGE/include + cp -p libmetis/libmetis.a $INSTALL_DIR/$PACKAGE/lib + ;; + + parmetis-4.0.3) + download $PACKAGE.tar.gz http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/$PACKAGE.tar.gz > $LOG_FILE 2>&1 + extract "$PACKAGE.tar.gz" gzip >> $LOG_FILE 2>&1 + patch $PACKAGE + cd $PACKAGE + mkdir build/windows + cd build/windows + cmake -G "MSYS Makefiles" -DCMAKE_CONFIGURATION-TYPES="Release" -DGKLIB_PATH="../../metis/GKlib" ../.. >> $LOG_FILE 2>&1 + $BUILD_HOME/parmetis_includes_hack.pl + make >> $LOG_FILE 2>&1 + mkdir $INSTALL_DIR/$PACKAGE + mkdir $INSTALL_DIR/$PACKAGE/bin + mkdir $INSTALL_DIR/$PACKAGE/include + mkdir $INSTALL_DIR/$PACKAGE/lib + cp -p programs/*.exe $INSTALL_DIR/$PACKAGE/bin + cp -p ../../metis/include/metis.h $INSTALL_DIR/$PACKAGE/include + cp -p ../../include/parmetis.h $INSTALL_DIR/$PACKAGE/include + cp -p libmetis/libmetis.a $INSTALL_DIR/$PACKAGE/lib + cp -p libparmetis/libparmetis.a $INSTALL_DIR/$PACKAGE/lib + ;; + + ParMGridGen-1.0) + export EXTRA_SYSTEM_HOME=$INSTALL_DIR/system + download $PACKAGE.tar.gz http://www.mgnet.org/mgnet/Codes/parmgridgen/$PACKAGE.tar.gz > $LOG_FILE 2>&1 + extract "$PACKAGE.tar.gz" gzip >> $LOG_FILE 2>&1 + patch $PACKAGE + cd $PACKAGE + make serial >> $LOG_FILE 2>&1 + make parallel >> $LOG_FILE 2>&1 + mkdir $INSTALL_DIR/$PACKAGE + mkdir $INSTALL_DIR/$PACKAGE/bin + mkdir $INSTALL_DIR/$PACKAGE/include + mkdir $INSTALL_DIR/$PACKAGE/lib + cp -p *.exe $INSTALL_DIR/$PACKAGE/bin + cp -p libmgrid.a $INSTALL_DIR/$PACKAGE/lib + cp -p libparmgrid.a $INSTALL_DIR/$PACKAGE/lib + cp -p MGridGen/IMlib/libIMlib.a $INSTALL_DIR/$PACKAGE/lib + cp -p ParMGridGen/IMParMetis-2.0/libIMparmetis.a $INSTALL_DIR/$PACKAGE/lib + cp -p MGridGen/IMlib/*.h $INSTALL_DIR/$PACKAGE/include + cp -p MGridGen/Lib/*.h $INSTALL_DIR/$PACKAGE/include + export EXTRA_SYSTEM_HOME= + ;; + + scotch_6.0.0) + export PTHREADS_HOME=$BUILD_DIR/pthreads-w32-2-9-1-release + download $PACKAGE.tar.gz https://gforge.inria.fr/frs/download.php/31831 > $LOG_FILE 2>&1 + extract "$PACKAGE.tar.gz" gzip >> $LOG_FILE 2>&1 + patch $PACKAGE + cd $PACKAGE/src + make scotch >> $LOG_FILE 2>&1 + make ptscotch >> $LOG_FILE 2>&1 + mkdir $INSTALL_DIR/$PACKAGE + make install prefix=$INSTALL_DIR/$PACKAGE >> $PACKAGE.log 2>&1 + export PTHREADS_HOME= + ;; + + mesquite-2.1.2) + export CPPFLAGS=-fpermissive + download $PACKAGE.tar.gz http://downloads.sourceforge.net/project/openfoam-extend/foam-extend-3.0/ThirdParty/$PACKAGE.tar.gz > $LOG_FILE 2>&1 + extract "$PACKAGE.tar.gz" gzip >> $LOG_FILE 2>&1 + cd $PACKAGE + cp -p $MINGW_HOME/bin/libstdc++-6.dll utils + ./configure --prefix=$INSTALL_DIR >> $LOG_FILE 2>&1 + make >> $LOG_FILE 2>&1 + mkdir $INSTALL_DIR/$PACKAGE + make install prefix=$INSTALL_DIR/$PACKAGE >> $LOG_FILE 2>&1 + export CPPFLAGS= + ;; + + *) + echo "*** ERROR: Unknown package '$PACKAGE'" + exit 1 + ;; + esac +} + +build_libraries() { + echo "" + echo "Building libraries ..." + build_library dlfcn-win32-master + build_library system + build_library pthreads-w32-2-9-1-release + build_library metis-5.1.0 + build_library parmetis-4.0.3 + build_library ParMGridGen-1.0 + build_library scotch_6.0.0 + build_library mesquite-2.1.2 +} + +create_dirs() { + echo "" + echo "Checking for build directories and creating them if required ..." + + mkchk $BUILD_DIR + mkchk $INSTALL_DIR + mkchk $OUT_DIR +} + +finish() { + echo "" + echo "All done!" +} +# }}} + +# {{{ MAIN EXECUTION +cd ${0%/*} || exit 1 # run from this directory +start +initialise +mkchk $ARCH +cleanup +build_libraries +finish +# }}} diff --git a/ThirdParty/mingwBuild/clean.sh b/ThirdParty/mingwBuild/clean.sh new file mode 100644 index 000000000..e49724843 --- /dev/null +++ b/ThirdParty/mingwBuild/clean.sh @@ -0,0 +1,82 @@ +#!/bin/sh +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | foam-extend: Open Source CFD +# \\ / O peration | Version: 3.2 +# \\ / A nd | Web: http://www.foam-extend.org +# \\/ M anipulation | For copyright notice see file Copyright +#------------------------------------------------------------------------------ +# License +# This file is part of foam-extend. +# +# foam-extend 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. +# +# foam-extend 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 foam-extend. If not, see . +# +# Script +# build.sh +# +# Description +# Removes previous thirdy-party dependencies build directories (does not remove installed packages directory) +# +# Author: +# Cesare Guardino, Alstom Power Ltd., (2015) +# +#------------------------------------------------------------------------------ + +# {{{ DEFINE UTILITY FUNCTIONS +remove_dir() { + dir=$1 + + rm -rf $dir > /dev/null 2>&1 +} +# }}} + +# {{{ DEFINE PROCESS FUNCTIONS +start() { + echo "======================== FOAM-EXTEND THIRD-PARTY DEPENDENCIES WINDOWS CLEAN SCRIPT ========================" +} + +initialise() { + echo "" + + BUILD_HOME=`pwd` + ARCH="x64" + + BUILD_DIR=$BUILD_HOME/$ARCH/build + INSTALL_DIR=$BUILD_HOME/$ARCH/install + OUT_DIR=$BUILD_HOME/$ARCH/output +} + +cleanup() { + echo "" + echo "Removing previous builds ..." + + remove_dir $BUILD_DIR + remove_dir $INSTALL_DIR + remove_dir $OUT_DIR + remove_dir $BUILD_HOME/downloads +} + +finish() { + echo "" + echo "All done!" +} +# }}} + +# {{{ MAIN EXECUTION +cd ${0%/*} || exit 1 # run from this directory +start +initialise +cleanup +finish +# }}} diff --git a/ThirdParty/mingwBuild/configure_OpenMPI.sh b/ThirdParty/mingwBuild/configure_OpenMPI.sh new file mode 100644 index 000000000..fe4a83d23 --- /dev/null +++ b/ThirdParty/mingwBuild/configure_OpenMPI.sh @@ -0,0 +1,67 @@ +#!/bin/sh +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | foam-extend: Open Source CFD +# \\ / O peration | Version: 3.2 +# \\ / A nd | Web: http://www.foam-extend.org +# \\/ M anipulation | For copyright notice see file Copyright +#------------------------------------------------------------------------------ +# License +# This file is part of foam-extend. +# +# foam-extend 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. +# +# foam-extend 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 foam-extend. If not, see . +# +# Script +# configure_OpenMPI.sh +# +# Description +# Generates static OpenMPI library to enable compilation with MINGW toolchain. +# +# Author: +# Cesare Guardino, Alstom Power Ltd., (2015) +# +#------------------------------------------------------------------------------ + +if [ -f "$MPI_ROOTDIR/lib/libmpi.a" ] ; then + echo "$MPI_ROOTDIR/lib/libmpi.a already exists." + exit 1 +fi + +INSTALL=1 +if [ $1 ] ; then + if [ $1 = "--no-install" ] ; then + INSTALL=0 + echo "*** WARNING: Will not install exported libmpi.a and libmpi.def" + fi +fi + +tmp=`echo $RANDOM$RANDOM$RANDOM` +current_dir=`pwd` +mkdir -p /tmp/$tmp +cd /tmp/$tmp + +pexports $MPI_ROOTDIR/bin/libmpi.dll > libmpi.def +dlltool --dllname libmpi.dll --def libmpi.def --output-lib libmpi.a + +if [ $INSTALL -eq 1 ] ; then + mv libmpi.a $MPI_ROOTDIR/lib + mv libmpi.def $MPI_ROOTDIR/lib + cd $current_dir + rm -rf /tmp/$tmp + echo "Installed exported libraries into $MPI_ROOTDIR/lib" +else + cd $current_dir + echo "Exported libraries left in directory /tmp/$tmp" +fi + diff --git a/ThirdParty/mingwBuild/parmetis_includes_hack.pl b/ThirdParty/mingwBuild/parmetis_includes_hack.pl new file mode 100644 index 000000000..787146a8a --- /dev/null +++ b/ThirdParty/mingwBuild/parmetis_includes_hack.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | foam-extend: Open Source CFD +# \\ / O peration | Version: 3.2 +# \\ / A nd | Web: http://www.foam-extend.org +# \\/ M anipulation | For copyright notice see file Copyright +#------------------------------------------------------------------------------ +# License +# This file is part of foam-extend. +# +# foam-extend 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. +# +# foam-extend 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 foam-extend. If not, see . +# +# Script +# parmetis_includes_hack.pl +# +# Description +# Adds OpenMPI lib/includes dirs to CMake-generated GCC options. +# +# Author: +# Cesare Guardino, Alstom Power Ltd., (2015) +# +#------------------------------------------------------------------------------ + +use strict; +use warnings; + +use File::Find; + +my $MPI_ROOTDIR = $ENV{"MPI_ROOTDIR"}; +$MPI_ROOTDIR =~ s/^\/\w//; +my $drive_letter = $&; +$drive_letter =~ s/\///; +$MPI_ROOTDIR = uc($drive_letter) . ":" . $MPI_ROOTDIR; + +my @dirs = ("."); +find(\&wanted, @dirs); + +sub wanted +{ + my $file = $_; + my $path = $File::Find::name; + + if ($file eq "linklibs.rsp" or $file eq "includes_C.rsp") + { + open (FILE, '<', $file) or die ("ERROR: Can't open '$path' [$!]"); + my @contents = ; + close (FILE); + + my $string = ($file eq "linklibs.rsp") ? "-L$MPI_ROOTDIR/lib -lmpi" : "-I$MPI_ROOTDIR/include"; + open (FILE, '>', $file) or die ("ERROR: Can't open '$path' [$!]"); + foreach my $line (@contents) + { + chomp($line); + print FILE $line . $string; + } + close (FILE); + } +} diff --git a/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/MGridGen/IMlib/IMlib.h b/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/MGridGen/IMlib/IMlib.h new file mode 100644 index 000000000..29733b2e1 --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/MGridGen/IMlib/IMlib.h @@ -0,0 +1,285 @@ +/* + * IMlib.h + * + * Irene's library of most frequently used routines + * + */ + +#ifndef _IMLIB_H_ +#define _IMLIB_H_ + + +/* Undefine the following #define in order to use short int as the idxtype */ +#define IDXTYPE_INT +/* Undefine the following #define in order to use float as the realtype */ +/*#define TYPE_REAL*/ + +/* Indexes are as long as integers for now */ +#ifdef IDXTYPE_INT +typedef int idxtype; +#else +typedef short idxtype; +#endif + +/* floats for now */ +#ifdef TYPE_REAL +typedef float realtype; +#else +typedef double realtype; +#endif + + +/************************************************************************* +* Header file inclusion section +**************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include "rand48.h" + +#ifdef DMALLOC +#include +#else +#include +#endif + +/************************************************************************* +* Data structure definition section +**************************************************************************/ +/*------------------------------------------------------------- + * The following data structure stores int key-value pairs + *-------------------------------------------------------------*/ +struct IKeyValueType { + int key; + int val; +}; + +typedef struct IKeyValueType IKeyValueType; + + +/*------------------------------------------------------------- + * The following data structure stores int key-value pairs + *-------------------------------------------------------------*/ +struct idxKeyValueType { + idxtype key; + idxtype val; +}; + +typedef struct idxKeyValueType idxKeyValueType; + + +/*------------------------------------------------------------- + * The following data structure stores int-key - double-value pairs + *-------------------------------------------------------------*/ +struct FKeyValueType { + double key; + int val, val1, val2; +}; + +typedef struct FKeyValueType FKeyValueType; + + +/*------------------------------------------------------------- + * The following data structure stores int-key - double-value pairs + *-------------------------------------------------------------*/ +struct realKeyValueType { + realtype key; + int val, val1, val2; +}; + +typedef struct realKeyValueType realKeyValueType; + +/************************************************************************* +* Definition Section +**************************************************************************/ +#define LTERM (void **) 0 /* List terminator for IMfree() */ + + + +/************************************************************************* +* Macros Section +**************************************************************************/ +/*------------------------------------------------------------- + * Usefull commands + *-------------------------------------------------------------*/ +#define sign(a, b) ((b) >= 0 ? ((a) >= 0.0 ? a : -a) : ((a) >= 0.0 ? -a : a)) +#define amax(a, b) ((a) >= (b) ? (a) : (b)) +#define amin(a, b) ((a) >= (b) ? (b) : (a)) +#define RandomInRange(u) ((int)(drand48()*((double)(u)))) +#define RandomInRangeFast(u) ((rand()>>3)%(u)) +#define SWAP(a, b, tmp) do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0) +#define INC_DEC(a, b, val) do {(a) += (val); (b) -= (val);} while(0) +#define icopy(n, a, b) (int *)memcpy((void *)(b), (void *)(a), sizeof(int)*(n)) +#define idxcopy(n, a, b) (idxtype *)memcpy((void *)(b), (void *)(a), sizeof(idxtype)*(n)) +#define scopy(n, a, b) (double *)memcpy((void *)(b), (void *)(a), sizeof(double)*(n)) +#define fcopy(n, a, b) (double *)memcpy((void *)(b), (void *)(a), sizeof(double)*(n)) +#define realcopy(n, a, b) (realtype *)memcpy((void *)(b), (void *)(a), sizeof(realtype)*(n)) + + +/*------------------------------------------------------------- + * Timing macros + *-------------------------------------------------------------*/ +#define cleartimer(tmr) (tmr = 0.0) +#define starttimer(tmr) (tmr -= seconds()) +#define stoptimer(tmr) (tmr += seconds()) +#define gettimer(tmr) (tmr) + + +/*------------------------------------------------------------- + * Debuging memory leaks + *-------------------------------------------------------------*/ +#ifdef DMALLOC +#define imalloc(n, msg) (malloc(sizeof(int)*(n))) +#define fmalloc(n, msg) (malloc(sizeof(double)*(n))) +#define idxmalloc(n, msg) ((idxtype *)malloc(sizeof(idxtype)*(n))) +#define realmalloc(n, msg) ((realtype *)malloc(sizeof(realtype)*(n))) +#define ismalloc(n, val, msg) (iset((n), (val), malloc(sizeof(int)*(n)))) +#define idxsmalloc(n, val, msg) (idxset((n), (val), (idxtype *)malloc(sizeof(idxtype)*(n)))) +#define fsmalloc(n, val, msg) (fset((n), (val), malloc(sizeof(double)*(n)))) +#define realsmalloc(n, val, msg) (realset((n), (val), (realtype *)malloc(sizeof(realtype)*(n)))) +#define IMmalloc(a, b) (malloc((a))) +#endif + +#ifdef DMALLOC +# define MALLOC_CHECK(ptr) \ + if (malloc_verify((ptr)) == DMALLOC_VERIFY_ERROR) { \ + printf("***MALLOC_CHECK failed on line %d of file %s: " #ptr "\n", \ + __LINE__, __FILE__); \ + abort(); \ + } +#else +# define MALLOC_CHECK(ptr) ; +#endif + + +/*------------------------------------------------------------- + * CSR conversion macros + *-------------------------------------------------------------*/ +#define MAKECSR(i, n, a) \ + do { \ + for (i=1; i0; i--) a[i] = a[i-1]; \ + a[0] = 0; \ + } while(0) + + +/*------------------------------------------------------------- + * Program Assertions + *-------------------------------------------------------------*/ +#ifdef DEBUG +# define ASSERT(expr) \ + if (!(expr)) { \ + printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + abort(); \ + } +#else +# define ASSERT(expr) ; +#endif + +#ifdef DEBUG +# define ASSERTP(expr,msg) \ + if (!(expr)) { \ + printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + printf msg ; \ + printf("\n"); \ + abort(); \ + } +#else +# define ASSERTP(expr,msg) ; +#endif + + +/************************************************************************* +* Function prototypes +**************************************************************************/ +/*------------------------------------------------------------- + * blas.c + *-------------------------------------------------------------*/ +int *iset(int, int, int *); +idxtype *idxset(int, idxtype, idxtype *); +double *fset(int, double, double *); +realtype *realset(int, realtype, realtype *); +int iamax(int, int *); +int idxamax(int, idxtype *); +int famax(int, double *); +int iamin(int, int *); +int idxamin(int, idxtype *); +int famin(int, double *); +int charsum(int, char *); +int isum(int, int *); +int idxsum(int, idxtype *); +double ssum(int, double *); +double ssum_strd(int, double *, int); +void sscale(int, double, double *); +double snorm2(int, double *); +double sdot(int, double *, double *); +void saxpy(int, double, double *, int, double *, int); + + +/*------------------------------------------------------------- + * file.c + *-------------------------------------------------------------*/ +FILE *IMfopen(char *, char *, char *); +void IMfclose(FILE *); + +/*------------------------------------------------------------- + * memory.c + *-------------------------------------------------------------*/ +#ifndef DMALLOC +int *imalloc(int, char *); +idxtype *idxmalloc(int, char *); +double *fmalloc(int, char *); +realtype *realmalloc(int, char *); +int *ismalloc(int, int, char *); +idxtype *idxsmalloc(int, idxtype, char *); +double *fsmalloc(int, double, char *); +realtype *realsmalloc(int, realtype, char *); +void *IMmalloc(int, char *); +#endif +/* void IMfree(void **, ...); */ + + +/*------------------------------------------------------------- + * util.c + *-------------------------------------------------------------*/ +void *errexit(char *,...); +int IMlog2(int); +double flog2(double); +int ispow2(int); +double seconds(void); + + +/*------------------------------------------------------------- + * Sorting routines + *-------------------------------------------------------------*/ +void dfkeysort(int, FKeyValueType *); +void dkeysort(int, IKeyValueType *); +void ifkeysort(int, FKeyValueType *); +void ifkeysort2(int, FKeyValueType *); +void ifloatsort(int, double *); +void iintsort(int, int *); +void ikeysort(int, IKeyValueType *); +void idxkeysort(int, idxKeyValueType *); +void ikeysort2(int, IKeyValueType *); +void idxkeysort2(int, idxKeyValueType *); + +/*------------------------------------------------------------- + * sort.c + *-------------------------------------------------------------*/ +void ikeyvalsort_org(int, IKeyValueType *); +int IncKeyValueCmp(const void *, const void *); +void dkeyvalsort(int, IKeyValueType *); +void BucketSortKeysInc(int, idxtype, idxtype *, int *, int *); +int DecKeyValueCmp(const void *, const void *); +int BSearch(int, idxtype *, int); +void RandomPermute(int, idxtype *, int); +void RandomPermuteFine(int, int *, int); +void FastRandomPermute(int, idxtype *, int); + +#endif diff --git a/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/MGridGen/Lib/mgridgen.c b/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/MGridGen/Lib/mgridgen.c new file mode 100644 index 000000000..6ee11c58a --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/MGridGen/Lib/mgridgen.c @@ -0,0 +1,111 @@ +/* + * Copyright 2001, Regents of the University of Minnesota + * + * mgridgen.c + * + * This file contains the top level routines for the sparse hierarchical + * clustering algorithm. + * + * George Irene + */ + +#include "mgridgen.h" +#include "rand48.h" + + +/************************************************************************* +* This function is the entry point for the SHCluster() routine. +**************************************************************************/ +void MGridGen(int nvtxs, idxtype *xadj, realtype *vvol, realtype *vsurf, + idxtype *adjncy, realtype *adjwgt, int minsize, int maxsize, + int *options, int *nmoves, int *nparts, idxtype *part) +{ + GraphType graph; + CtrlType ctrl; + + srand(4321); + srand48(7654321L); + + /*------------------------------------------------------------ + * Set up the various control structures + *------------------------------------------------------------*/ + ctrl.CType = options[OPTION_CTYPE]; + ctrl.RType = options[OPTION_RTYPE]; + ctrl.dbglvl = options[OPTION_DBGLVL]; + ctrl.dim = options[OPTION_DIM]; + ctrl.minsize = minsize; + ctrl.maxsize = maxsize; + ctrl.nparts = -1; + + /*------------------------------------------------------------ + * Set up the graph + *------------------------------------------------------------*/ + SetUpGraph(&graph, nvtxs, xadj, vvol, vsurf, adjncy, adjwgt); + + CreateGrid(&ctrl, &graph); + + *nparts = ctrl.nparts; + icopy(nvtxs, graph.where, part); + *nmoves = graph.nmoves; + + FreeGraph(&graph); +} + + +/************************************************************************* +* This function is the entry point for performing refinement +**************************************************************************/ +void MGridGenRefine(int nvtxs, idxtype *xadj, realtype *vvol, realtype *vsurf, + idxtype *adjncy, idxtype *fusedinfo, realtype *adjwgt, + int minsize, int maxsize, int *options, int *nmoves, + int *nparts, idxtype *part) +{ + int i; + GraphType graph; + CtrlType ctrl; + + srand(4321); + srand48(7654321L); + + /*------------------------------------------------------------ + * Set up the various control structures + *------------------------------------------------------------*/ + ctrl.CType = options[OPTION_CTYPE]; + ctrl.RType = options[OPTION_RTYPE]; + ctrl.dbglvl = options[OPTION_DBGLVL]; + ctrl.dim = options[OPTION_DIM]; + ctrl.minsize = minsize; + ctrl.maxsize = maxsize; + ctrl.nparts = -1; + + /*------------------------------------------------------------ + * Set up the graph + *------------------------------------------------------------*/ + SetUpGraph(&graph, nvtxs, xadj, vvol, vsurf, adjncy, adjwgt); + graph.cmap = NULL; + + graph.where = idxmalloc(graph.nvtxs, "graph.where"); + for (i=0; i>2)%(u)) + +#define amax(a, b) ((a) >= (b) ? (a) : (b)) +#define amin(a, b) ((a) >= (b) ? (b) : (a)) + +#define AND(a, b) ((a) < 0 ? ((-(a))&(b)) : ((a)&(b))) +#define OR(a, b) ((a) < 0 ? -((-(a))|(b)) : ((a)|(b))) +#define XOR(a, b) ((a) < 0 ? -((-(a))^(b)) : ((a)^(b))) + +#define SWAP(a, b, tmp) \ + do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0) + +#define INC_DEC(a, b, val) \ + do {(a) += (val); (b) -= (val);} while(0) + + +#define scopy(n, a, b) memcpy((b), (a), sizeof(float)*(n)) +#define idxcopy(n, a, b) memcpy((b), (a), sizeof(idxtype)*(n)) +#define realcopy(n, a, b) memcpy((b), (a), sizeof(realtype)*(n)) + + +#define HASHFCT(key, size) ((key)%(size)) + + +/************************************************************************* +* Timer macros +**************************************************************************/ +#define cleartimer(tmr) (tmr = 0.0) +#define starttimer(tmr) (tmr -= MPI_Wtime()) +#define stoptimer(tmr) (tmr += MPI_Wtime()) +#define gettimer(tmr) (tmr) + + +/************************************************************************* +* This macro is used to handle dbglvl +**************************************************************************/ +#define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd); + +/************************************************************************* +* These macros are used for debuging memory leaks +**************************************************************************/ +#ifdef DMALLOC +#define imalloc(n, msg) (malloc(sizeof(int)*(n))) +#define fmalloc(n, msg) (malloc(sizeof(float)*(n))) +#define idxmalloc(n, msg) (malloc(sizeof(idxtype)*(n))) +#define realmalloc(n, msg) ((realtype *)malloc(sizeof(realtype)*(n))) +#define ismalloc(n, val, msg) (iset((n), (val), malloc(sizeof(int)*(n)))) +#define idxsmalloc(n, val, msg) (idxset((n), (val), malloc(sizeof(idxtype)*(n)))) +#define realsmalloc(n, val, msg) (realset((n), (val), (realtype *)malloc(sizeof(realtype)*(n)))) +#define IMmalloc(a, b) (malloc(a)) +#endif + +#ifdef DMALLOC +# define MALLOC_CHECK(ptr) \ + if (malloc_verify((ptr)) == DMALLOC_VERIFY_ERROR) { \ + printf("***MALLOC_CHECK failed on line %d of file %s: " #ptr "\n", \ + __LINE__, __FILE__); \ + abort(); \ + } +#else +# define MALLOC_CHECK(ptr) ; +#endif + +/************************************************************************* +* This macro converts a length array in a CSR one +**************************************************************************/ +#define MAKECSR(i, n, a) \ + do { \ + for (i=1; i0; i--) a[i] = a[i-1]; \ + a[0] = 0; \ + } while(0) + + + + +#ifdef DEBUG +# define ASSERT(ctrl, expr) \ + if (!(expr)) { \ + myprintf(ctrl, "***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + abort(); \ + } +#else +# define ASSERT(ctrl, expr) ; +#endif + +#ifdef DEBUG +# define ASSERTP(ctrl, expr,msg) \ + if (!(expr)) { \ + myprintf(ctrl, "***ASSERTION failed on line %d of file %s:" #expr "\n", \ + __LINE__, __FILE__); \ + myprintf msg ; \ + abort(); \ + } +#else +# define ASSERTP(ctrl, expr,msg) ; +#endif + +#ifdef DEBUGS +# define ASSERTS(expr) \ + if (!(expr)) { \ + printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + abort(); \ + } +#else +# define ASSERTS(expr) ; +#endif + +#ifdef DEBUGS +# define ASSERTSP(expr, msg) \ + if (!(expr)) { \ + printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + printf msg ; \ + abort(); \ + } +#else +# define ASSERTSP(expr, msg) ; +#endif diff --git a/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/ParMGridGen/ParLib/macros.h b/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/ParMGridGen/ParLib/macros.h new file mode 100644 index 000000000..37b66c306 --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/ParMGridGen-1.0/ParMGridGen/ParLib/macros.h @@ -0,0 +1,108 @@ +/* + * Copyright 2001, Regents of the University of Minnesota + * + * macros.h + * + * This file contains macros used in multilevel + * + * George Irene + */ + +#include "rand48.h" + +/************************************************************************* +* This macro is used to normalize the weights of two nodes +**************************************************************************/ +#define ARATIO1(dim, surf, vol) ((dim == 2) ? (pow((surf), 2)/(vol)) : (pow((surf), 1.5)/(vol))) +#define ARATIO(dim, surf, vol) ((dim == 2) ? ((surf)*(surf)/(vol)) : (sqrt((surf)*(surf)*(surf))/(vol))) +#define ARATIO2(dim, surf, vol) ((dim == 2) ? ((surf)*(surf)*(surf)*(surf)/(vol)*(vol)) : ((surf)*(surf)*(surf)/((vol)*(vol)))) + + +/************************************************************************* +* The following macro returns a random number in the specified range +**************************************************************************/ +#define RandomInRange(u) ((int)(drand48()*((double)(u)))) + +#define amax(a, b) ((a) >= (b) ? (a) : (b)) +#define amin(a, b) ((a) >= (b) ? (b) : (a)) + +#define AND(a, b) ((a) < 0 ? ((-(a))&(b)) : ((a)&(b))) +#define OR(a, b) ((a) < 0 ? -((-(a))|(b)) : ((a)|(b))) +#define XOR(a, b) ((a) < 0 ? -((-(a))^(b)) : ((a)^(b))) + +#define SWAP(a, b, tmp) \ + do {(tmp) = (a); (a) = (b); (b) = (tmp);} while(0) + +#define INC_DEC(a, b, val) \ + do {(a) += (val); (b) -= (val);} while(0) + + +#define HASHFCT(key, size) ((key)%(size)) + + +/************************************************************************* +* Timer macros +**************************************************************************/ +#undef cleartimer +#undef starttimer +#undef stoptimer +#undef gettimer +#define cleartimer(tmr) (tmr = 0.0) +#define starttimer(tmr) (tmr -= MPI_Wtime()) +#define stoptimer(tmr) (tmr += MPI_Wtime()) +#define gettimer(tmr) (tmr) + + +/************************************************************************* +* This macro is used to handle dbglvl +**************************************************************************/ +#define IFSET(a, flag, cmd) if ((a)&(flag)) (cmd); + +#undef ASSERT +#undef ASSERTP + +#ifdef DEBUG +# define ASSERT(ctrl, expr) \ + if (!(expr)) { \ + MGridmyprintf(ctrl, "***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + abort(); \ + } +#else +# define ASSERT(ctrl, expr) ; +#endif + +#ifdef DEBUG +# define ASSERTP(ctrl, expr,msg) \ + if (!(expr)) { \ + MGridmyprintf(ctrl, "***ASSERTION failed on line %d of file %s:" #expr "\n", \ + __LINE__, __FILE__); \ + MGridmyprintf msg ; \ + abort(); \ + } +#else +# define ASSERTP(ctrl, expr,msg) ; +#endif + +#ifdef DEBUGS +# define ASSERTS(expr) \ + if (!(expr)) { \ + printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + abort(); \ + } +#else +# define ASSERTS(expr) ; +#endif + +#ifdef DEBUGS +# define ASSERTSP(expr, msg) \ + if (!(expr)) { \ + printf("***ASSERTION failed on line %d of file %s: " #expr "\n", \ + __LINE__, __FILE__); \ + printf msg ; \ + abort(); \ + } +#else +# define ASSERTSP(expr, msg) ; +#endif diff --git a/ThirdParty/mingwBuild/x64/patches/metis-5.1.0/GKlib/gk_arch.h b/ThirdParty/mingwBuild/x64/patches/metis-5.1.0/GKlib/gk_arch.h new file mode 100644 index 000000000..1f9bef352 --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/metis-5.1.0/GKlib/gk_arch.h @@ -0,0 +1,71 @@ +/*! +\file gk_arch.h +\brief This file contains various architecture-specific declerations + +\date Started 3/27/2007 +\author George +\version\verbatim $Id: gk_arch.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim +*/ + +#ifndef _GK_ARCH_H_ +#define _GK_ARCH_H_ + +/************************************************************************* +* Architecture-specific differences in header files +**************************************************************************/ +#ifdef LINUX +#if !defined(__USE_XOPEN) +#define __USE_XOPEN +#endif +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#endif +#if !defined(__USE_XOPEN2K) +#define __USE_XOPEN2K +#endif +#endif + + +#ifdef HAVE_EXECINFO_H +#include +#endif + + +#ifdef __MSC__ + #include "ms_stdint.h" + #include "ms_inttypes.h" + #include "ms_stat.h" +#else +#ifndef SUNOS + #include +#endif + #include + #include +// #include + #include +#endif + + +/************************************************************************* +* Architecture-specific modifications +**************************************************************************/ +#ifdef WIN32 +typedef ptrdiff_t ssize_t; +#endif + + +#ifdef SUNOS +#define PTRDIFF_MAX INT64_MAX +#endif + +#ifdef __MSC__ +/* MSC does not have rint() function */ +#define rint(x) ((int)((x)+0.5)) + +/* MSC does not have INFINITY defined */ +#ifndef INFINITY +#define INFINITY FLT_MAX +#endif +#endif + +#endif diff --git a/ThirdParty/mingwBuild/x64/patches/metis-5.1.0/GKlib/gk_getopt.h b/ThirdParty/mingwBuild/x64/patches/metis-5.1.0/GKlib/gk_getopt.h new file mode 100644 index 000000000..e53f97d81 --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/metis-5.1.0/GKlib/gk_getopt.h @@ -0,0 +1,64 @@ +/*! +\file gk_getopt.h +\brief This file contains GNU's externs/structs/prototypes + +\date Started 3/27/2007 +\author George +\version\verbatim $Id: gk_getopt.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim +*/ + +#ifndef _GK_GETOPT_H_ +#define _GK_GETOPT_H_ + + +/* Externals from getopt.c */ +//extern char *gk_optarg; +//extern int gk_optind; +//extern int gk_opterr; +//extern int gk_optopt; + + +/*! \brief The structure that stores the information about the command-line options + +This structure describes a single long option name for the sake of +gk_getopt_long(). The argument long_options must be an array +of these structures, one for each long option. Terminate the array with +an element containing all zeros. +*/ +struct gk_option { + char *name; /*!< This field is the name of the option. */ + int has_arg; /*!< This field says whether the option takes an argument. + It is an integer, and there are three legitimate values: + no_argument, required_argument and optional_argument. + */ + int *flag; /*!< See the discussion on ::gk_option#val */ + int val; /*!< These fields control how to report or act on the option + when it occurs. + + If flag is a null pointer, then the val is a value which + identifies this option. Often these values are chosen + to uniquely identify particular long options. + + If flag is not a null pointer, it should be the address + of an int variable which is the flag for this option. + The value in val is the value to store in the flag to + indicate that the option was seen. */ +}; + +/* Names for the values of the `has_arg' field of `struct gk_option'. */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + + +/* Function prototypes */ +//extern int gk_getopt(int __argc, char **__argv, char *__shortopts); +//extern int gk_getopt_long(int __argc, char **__argv, char *__shortopts, +// struct gk_option *__longopts, int *__longind); +//extern int gk_getopt_long_only (int __argc, char **__argv, +// char *__shortopts, struct gk_option *__longopts, int *__longind); + + + +#endif + diff --git a/ThirdParty/mingwBuild/x64/patches/parmetis-4.0.3/metis/GKlib/gk_arch.h b/ThirdParty/mingwBuild/x64/patches/parmetis-4.0.3/metis/GKlib/gk_arch.h new file mode 100644 index 000000000..1f9bef352 --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/parmetis-4.0.3/metis/GKlib/gk_arch.h @@ -0,0 +1,71 @@ +/*! +\file gk_arch.h +\brief This file contains various architecture-specific declerations + +\date Started 3/27/2007 +\author George +\version\verbatim $Id: gk_arch.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim +*/ + +#ifndef _GK_ARCH_H_ +#define _GK_ARCH_H_ + +/************************************************************************* +* Architecture-specific differences in header files +**************************************************************************/ +#ifdef LINUX +#if !defined(__USE_XOPEN) +#define __USE_XOPEN +#endif +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#endif +#if !defined(__USE_XOPEN2K) +#define __USE_XOPEN2K +#endif +#endif + + +#ifdef HAVE_EXECINFO_H +#include +#endif + + +#ifdef __MSC__ + #include "ms_stdint.h" + #include "ms_inttypes.h" + #include "ms_stat.h" +#else +#ifndef SUNOS + #include +#endif + #include + #include +// #include + #include +#endif + + +/************************************************************************* +* Architecture-specific modifications +**************************************************************************/ +#ifdef WIN32 +typedef ptrdiff_t ssize_t; +#endif + + +#ifdef SUNOS +#define PTRDIFF_MAX INT64_MAX +#endif + +#ifdef __MSC__ +/* MSC does not have rint() function */ +#define rint(x) ((int)((x)+0.5)) + +/* MSC does not have INFINITY defined */ +#ifndef INFINITY +#define INFINITY FLT_MAX +#endif +#endif + +#endif diff --git a/ThirdParty/mingwBuild/x64/patches/parmetis-4.0.3/metis/GKlib/gk_getopt.h b/ThirdParty/mingwBuild/x64/patches/parmetis-4.0.3/metis/GKlib/gk_getopt.h new file mode 100644 index 000000000..e53f97d81 --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/parmetis-4.0.3/metis/GKlib/gk_getopt.h @@ -0,0 +1,64 @@ +/*! +\file gk_getopt.h +\brief This file contains GNU's externs/structs/prototypes + +\date Started 3/27/2007 +\author George +\version\verbatim $Id: gk_getopt.h 10711 2011-08-31 22:23:04Z karypis $ \endverbatim +*/ + +#ifndef _GK_GETOPT_H_ +#define _GK_GETOPT_H_ + + +/* Externals from getopt.c */ +//extern char *gk_optarg; +//extern int gk_optind; +//extern int gk_opterr; +//extern int gk_optopt; + + +/*! \brief The structure that stores the information about the command-line options + +This structure describes a single long option name for the sake of +gk_getopt_long(). The argument long_options must be an array +of these structures, one for each long option. Terminate the array with +an element containing all zeros. +*/ +struct gk_option { + char *name; /*!< This field is the name of the option. */ + int has_arg; /*!< This field says whether the option takes an argument. + It is an integer, and there are three legitimate values: + no_argument, required_argument and optional_argument. + */ + int *flag; /*!< See the discussion on ::gk_option#val */ + int val; /*!< These fields control how to report or act on the option + when it occurs. + + If flag is a null pointer, then the val is a value which + identifies this option. Often these values are chosen + to uniquely identify particular long options. + + If flag is not a null pointer, it should be the address + of an int variable which is the flag for this option. + The value in val is the value to store in the flag to + indicate that the option was seen. */ +}; + +/* Names for the values of the `has_arg' field of `struct gk_option'. */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + + +/* Function prototypes */ +//extern int gk_getopt(int __argc, char **__argv, char *__shortopts); +//extern int gk_getopt_long(int __argc, char **__argv, char *__shortopts, +// struct gk_option *__longopts, int *__longind); +//extern int gk_getopt_long_only (int __argc, char **__argv, +// char *__shortopts, struct gk_option *__longopts, int *__longind); + + + +#endif + diff --git a/ThirdParty/mingwBuild/x64/patches/pthreads-w32-2-9-1-release/Pre-built.2/include/sched.h b/ThirdParty/mingwBuild/x64/patches/pthreads-w32-2-9-1-release/Pre-built.2/include/sched.h new file mode 100644 index 000000000..2372bb65b --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/pthreads-w32-2-9-1-release/Pre-built.2/include/sched.h @@ -0,0 +1,183 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(_SCHED_H) +#define _SCHED_H + +#undef PTW32_SCHED_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_SCHED_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_SCHED_LEVEL +#define PTW32_SCHED_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_SCHED_LEVEL +#define PTW32_SCHED_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_SCHED_LEVEL_MAX 3 + +#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL) +#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX +/* Include everything */ +#endif + + +#if defined(__GNUC__) && !defined(__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the library, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the library, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#if !defined(PTW32_STATIC_LIB) +# if defined(PTW32_BUILD) +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#if !defined(PTW32_CONFIG_H) +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(__MINGW64__) +# define HAVE_STRUCT_TIMESPEC +# define HAVE_MODE_T +# elif defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX +#if defined(NEED_ERRNO) +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ + +#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) +# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +# else + typedef __int64 pid_t; +# endif +#else + typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#if defined(__cplusplus) +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#if defined(__cplusplus) +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_SCHED_LEVEL +#undef PTW32_SCHED_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/ThirdParty/mingwBuild/x64/patches/scotch_6.0.0/src/Makefile.inc b/ThirdParty/mingwBuild/x64/patches/scotch_6.0.0/src/Makefile.inc new file mode 100644 index 000000000..8fc051b5d --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/scotch_6.0.0/src/Makefile.inc @@ -0,0 +1,70 @@ +# This make include file is intended for building under MinGW32. As is, +# it relies on : +# - pthread-win32 (http://sourceware.org/pthreads-win32/), +# - zlib (http://www.zlib.net/) +# - mpich2 (http://www.mcs.anl.gov/research/projects/mpich2/). +# It must be adapted to reflect your environment, in particular +# installation root directories, include path and library name. +# Since all files are linked with the MPI libraries, this file is +# for compiling PT-Scotch only. To compile Scotch, remove the +# -DSCOTCH_PTSCOTCH flag, as well as all references to MPI in the +# CFLAGS and CLIBFLAGS = +#LDFLAGS variables. + +#MPI_ROOTDIR = /c/Programs/OpenMPI_v1.6.1-x64 + +EXE = +LIB = .a +OBJ = .o + +MAKE = make +AR = ar +ARFLAGS = -ruv +CAT = cat +CCS = gcc +CCP = mpicc +CCD = mpicc -I$(MPI_ROOTDIR)/include + +#--- Compiler/loader flags +CFLAGS_CPL = -O0 -g3 --std=c99 +CFLAGS_INC = +CFLAGS_DEF = -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_STUB_FORK -DSCOTCH_PTSCOTCH -DSCOTCH_RENAME -D'pipe(pfds)=_pipe(pfds,1024,0x8000)' -DHAVE_STDINT_H=0 -DHAVE_UINT_T=1 +CLIBFLAGS = +LDFLAGS = + +PGMFILES=$(PROGRAMFILES) + +#--- MPI +CFLAGS_INC += -I$(MPI_ROOTDIR)/include +#--- Comment/Uncomment for threaded MPI +CLIBFLAGS = +LDFLAGS += -L$(MPI_ROOTDIR)/bin -lm -lmpi -lmpid +#CLIBFLAGS = +#LDFLAGS += -L$(MPI_ROOTDIR)/lib -lm -lmpich2mt + +#--- Pthread : Uncomment for pthread support +#PTHREAD_ROOTDIR = $(PGMFILES)/pthread-win32 +#CFLAGS_INC += -I$(PTHREAD_ROOTDIR)/include +#CLIBFLAGS = +LDFLAGS += -L$(PTHREADS_HOME)/Pre-built.2/lib/x64 -lpthreadGC2 + +#--- zlib: Uncomment for compressed files +#ZLIB_ROOTDIR = $(PGMFILES)/zlib-1.2.3 +#CFLAGS_INC += -I$(ZLIB_ROOTDIR)/include +#CLIBFLAGS = +LDFLAGS += -lz + +#--- COMMON_PTHREAD: Uncomment for compressed files +#CFLAGS_DEF += -DCOMMON_PTHREAD -DCOMMON_FILE_COMPRESS_GZ + +#--- SCOTCH_PTHREAD: Uncomment for threaded MPI +#CFLAGS_DEF += -DSCOTCH_PTHREAD + +CFLAGS = $(CFLAGS_CPL) $(CFLAGS_INC) $(CFLAGS_DEF) +CP = cp +LEX = flex -Pscotchyy -olex.yy.c +LN = cp +MKDIR = mkdir +MV = mv +RANLIB = ranlib +YACC = bison -pscotchyy -y -b y diff --git a/ThirdParty/mingwBuild/x64/patches/system/include/rand48.h b/ThirdParty/mingwBuild/x64/patches/system/include/rand48.h new file mode 100644 index 000000000..cb3694a7e --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/system/include/rand48.h @@ -0,0 +1,19 @@ +#ifndef RAND48_H +#define RAND48_H + +#define drand48() (rand()*(1./RAND_MAX)) +static long _rand = 1; + +static __inline__ void srand48(long seed) +{ + _rand = seed; +} + +static __inline__ long lrand48(void) +{ + long val = (int)(abs(10000.0*sin(_rand))); + _rand++; + return val; +} + +#endif //RAND48_H diff --git a/ThirdParty/mingwBuild/x64/patches/system/include/sys/times.h b/ThirdParty/mingwBuild/x64/patches/system/include/sys/times.h new file mode 100644 index 000000000..d04a32c19 --- /dev/null +++ b/ThirdParty/mingwBuild/x64/patches/system/include/sys/times.h @@ -0,0 +1,40 @@ +// From http://www.linuxjournal.com/article/5574 + +#ifndef _TIMES_H +#define _TIMES_H + +#ifdef _WIN32 +#include +#include +#include + +int gettimeofday(struct timeval* t,void* timezone); + +// from linux's sys/times.h + +//#include + +#define __need_clock_t +#include + + +/* Structure describing CPU time used by a process and its children. */ +struct tms + { + clock_t tms_utime; /* User CPU time. */ + clock_t tms_stime; /* System CPU time. */ + + clock_t tms_cutime; /* User CPU time of dead children. */ + clock_t tms_cstime; /* System CPU time of dead children. */ + }; + +/* Store the CPU time used by this process and all its + dead children (and their dead children) in BUFFER. + Return the elapsed real time, or (clock_t) -1 for errors. + All times are in CLK_TCKths of a second. */ +clock_t times (struct tms *__buffer); + +typedef long long suseconds_t ; + +#endif +#endif \ No newline at end of file diff --git a/applications/solvers/compressible/rhoCentralFoam/BCs/Make/options b/applications/solvers/compressible/rhoCentralFoam/BCs/Make/options index 87f38a6a0..999e0466c 100644 --- a/applications/solvers/compressible/rhoCentralFoam/BCs/Make/options +++ b/applications/solvers/compressible/rhoCentralFoam/BCs/Make/options @@ -3,7 +3,7 @@ EXE_INC = \ -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude -EXE_LIBS = \ +LIB_LIBS = \ -lfiniteVolume \ -lbasicThermophysicalModels \ -lspecie diff --git a/applications/solvers/compressible/rhoCentralFoam/Make/options b/applications/solvers/compressible/rhoCentralFoam/Make/options index 6b901e96d..9c63e2d73 100644 --- a/applications/solvers/compressible/rhoCentralFoam/Make/options +++ b/applications/solvers/compressible/rhoCentralFoam/Make/options @@ -4,6 +4,7 @@ EXE_INC = \ -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \ -IBCs/lnInclude \ -I$(LIB_SRC)/sampling/lnInclude + EXE_LIBS = \ -lfiniteVolume \ -lbasicThermophysicalModels \ diff --git a/applications/solvers/multiphase/twoPhaseEulerFoam/interfacialModels/Make/options b/applications/solvers/multiphase/twoPhaseEulerFoam/interfacialModels/Make/options index 42c2cb54c..f64e1701f 100644 --- a/applications/solvers/multiphase/twoPhaseEulerFoam/interfacialModels/Make/options +++ b/applications/solvers/multiphase/twoPhaseEulerFoam/interfacialModels/Make/options @@ -3,4 +3,5 @@ EXE_INC = \ -I../phaseModel/lnInclude LIB_LIBS = \ + -lfiniteVolume \ -lphaseModel diff --git a/applications/solvers/multiphase/twoPhaseEulerFoam/kineticTheoryModels/Make/options b/applications/solvers/multiphase/twoPhaseEulerFoam/kineticTheoryModels/Make/options index 2fcce9913..feffca4e5 100644 --- a/applications/solvers/multiphase/twoPhaseEulerFoam/kineticTheoryModels/Make/options +++ b/applications/solvers/multiphase/twoPhaseEulerFoam/kineticTheoryModels/Make/options @@ -3,3 +3,7 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ -I../phaseModel/lnInclude \ -I../interfacialModels/lnInclude + +LIB_LIBS = \ + -lfiniteVolume \ + -lphaseModel diff --git a/applications/solvers/multiphase/twoPhaseEulerFoam/phaseModel/Make/options b/applications/solvers/multiphase/twoPhaseEulerFoam/phaseModel/Make/options index 0ec113920..64e4b542f 100644 --- a/applications/solvers/multiphase/twoPhaseEulerFoam/phaseModel/Make/options +++ b/applications/solvers/multiphase/twoPhaseEulerFoam/phaseModel/Make/options @@ -3,4 +3,5 @@ EXE_INC = \ -I$(LIB_SRC)/transportModels/incompressible/lnInclude LIB_LIBS = \ + -lfiniteVolume \ -lincompressibleTransportModels diff --git a/applications/solvers/solidMechanics/deprecatedSolvers/materialModels/Make/options b/applications/solvers/solidMechanics/deprecatedSolvers/materialModels/Make/options index fa15f1245..71b787396 100644 --- a/applications/solvers/solidMechanics/deprecatedSolvers/materialModels/Make/options +++ b/applications/solvers/solidMechanics/deprecatedSolvers/materialModels/Make/options @@ -1,5 +1,5 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude -EXE_LIBS = \ +LIB_LIBS = \ -lfiniteVolume diff --git a/applications/solvers/surfaceTracking/freeSurface/Make/options b/applications/solvers/surfaceTracking/freeSurface/Make/options index 574ef6cc7..54fa5dd4b 100644 --- a/applications/solvers/surfaceTracking/freeSurface/Make/options +++ b/applications/solvers/surfaceTracking/freeSurface/Make/options @@ -7,7 +7,7 @@ EXE_INC = \ -I$(LIB_SRC)/tetFiniteElement/lnInclude \ -I$(LIB_SRC)/dynamicMesh/meshMotion/tetMotionSolver/lnInclude -EXE_LIBS = \ +LIB_LIBS = \ -lfiniteArea \ -lfiniteVolume \ -lmeshTools \ diff --git a/applications/utilities/thermophysical/chemkinToFoam/Make/options b/applications/utilities/thermophysical/chemkinToFoam/Make/options index 7fe5ba407..52a0cb8ee 100644 --- a/applications/utilities/thermophysical/chemkinToFoam/Make/options +++ b/applications/utilities/thermophysical/chemkinToFoam/Make/options @@ -1,6 +1,13 @@ +ifneq ($(FLEX_DIR), "") +EXE_INC = \ + -I$(FLEX_DIR)/include \ + -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude +else EXE_INC = \ -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \ -I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude +endif EXE_LIBS = \ -lreactionThermophysicalModels \ diff --git a/etc/bashrc b/etc/bashrc index bd08ad0a8..47f3e9c10 100755 --- a/etc/bashrc +++ b/etc/bashrc @@ -56,6 +56,12 @@ foamInstall=$HOME/$WM_PROJECT # END OF (NORMAL) USER EDITABLE PART ################################################################################ +# Set $USER if it has not been set (eg. on Windows/MSYS systems) +if [ -z $USER ] +then + export USER=`whoami` +fi + # note the location for later use (eg, in job scripts) : ${FOAM_INST_DIR:=$foamInstall}; export FOAM_INST_DIR @@ -192,6 +198,15 @@ export FOAM_SIGFPE= export WM_ARCH=`uname -s` case $WM_ARCH in +MINGW32_NT-6.1) + WM_ARCH=MINGW32_NT-6.1 + export WM_ARCH_BASE=mingw + export WM_COMPILER_LIB_ARCH=64 + export WM_CFLAGS='-m64 -fPIC' + export WM_CXXFLAGS='-m64 -fPIC' + export WM_LDFLAGS='-m64' + ;; + Linux) WM_ARCH=linux diff --git a/etc/bashrc.mingw b/etc/bashrc.mingw new file mode 100644 index 000000000..4ba174686 --- /dev/null +++ b/etc/bashrc.mingw @@ -0,0 +1,127 @@ +#!/bin/sh +#----------------------------------*-sh-*-------------------------------------- +# ========= | +# \\ / F ield | foam-extend: Open Source CFD +# \\ / O peration | Version: 3.2 +# \\ / A nd | Web: http://www.foam-extend.org +# \\/ M anipulation | For copyright notice see file Copyright +#------------------------------------------------------------------------------ +# License +# This file is part of foam-extend. +# +# foam-extend 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. +# +# foam-extend 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 foam-extend. If not, see . +# +# Script +# etc/bashrc.mingw +# +# Description +# Startup file for FOAM for use with MSYS shell for MinGW-based builds on Windows. +# Calls the main etc/bashrc script. +# Sourced from ~/.profile or ~/.bashrc +# +# Author: +# Cesare Guardino, Alstom Power Ltd., (2015) +# +#------------------------------------------------------------------------------ + +# {{{ DEFINE USER EDITABLE FUNCTIONS +set_system_paths() { + echo "Setting installations directories of required tools ..." + export CMAKE_HOME=/c/Programs/cmake-3.2.3-win32-x86 + #export GIT_HOME=/c/Programs/Git + #export JAVA_HOME="/c/Program Files/Java/jre1.8.0_45" + export MINGW_HOME=/c/Programs/x86_64-4.8.2-release-win32-seh-rt_v3-rev3/mingw64 + export MPI_ROOTDIR=/c/Programs/OpenMPI_v1.6.1-x64 + export PERL_HOME=/c/Programs/strawberry-perl-5.20.2.1-64bit/perl + #export PEXPORTS_HOME=/c/Programs/pexports-0.46-mingw32 + #export PYTHON_HOME=/c/Programs/Python27 + #export SUBVERSION_HOME=/c/Programs/svn-win32-1.8.13 + export WGET_HOME=/c/Programs/wget-1.11.4-1 + export ZIP_HOME="/c/Program Files/7-Zip" +} + +add_to_path() { + echo "Adding required tools to PATH ..." + export PATH=$ZIP_HOME:$PATH + export PATH=$WGET_HOME/bin:$PATH + #export PATH=$JAVA_HOME/bin:$PATH + #export PATH=$PYTHON_HOME:$PATH + #export PATH=$SUBVERSION_HOME/bin:$PATH + #export PATH=$GIT_HOME/cmd:$PATH + export PATH=$PERL_HOME/bin:$PATH + export PATH=$CMAKE_HOME/bin:$PATH + export PATH=$MPI_ROOTDIR/bin:$PATH + #export PATH=$PEXPORTS_HOME/bin:$PATH + export PATH=$MINGW_HOME/bin:$PATH +} +# }}} + +# {{{ DEFINE PROCESS FUNCTIONS +setup_foam_env() { + : ${WM_OSTYPE:=POSIX}; export WM_OSTYPE + export export FLEX_DIR=$(echo $WD\.. | sed 's/\\/\//g' | sed 's/\(.*\):/\/\1/') + FOAM_ETC_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + export FOAM_INST_DIR=$(readlink -f $FOAM_ETC_DIR/../..) + . $FOAM_ETC_DIR/bashrc + . $FOAM_ETC_DIR/prefs.sh.mingw +} + +set_OMPI_env() { + echo "Setting OpenMPI environment settings ..." + export OMPI_MPICC=gcc.exe + export OMPI_MPIXX=g++.exe + export OMPI_CXXFLAGS==-I$MPI_ROOTDIR/include + export OMPI_CFLAGS=-I$MPI_ROOTDIR/include + export OMPI_CXXFLAGS=-I$MPI_ROOTDIR/include + export OMPI_LDFLAGS=-L$MPI_ROOTDIR/lib + export OMPI_LIBS=$OMPI_LDFLAGS +} + +check_versions() { + echo "Checking versions of installed system tools (based on PATH) ..." + echo "7-Zip: " `which 7z` [`(7z --help 2>&1) 2> /dev/null | head -2`] + echo "CMake: " `which cmake` [`(cmake --version 2>&1) 2> /dev/null | head -1`] + echo "G++: " `which g++` [`(g++ --version 2>&1) 2> /dev/null | head -1`] + echo "GCC: " `which gcc` [`(gcc --version 2>&1) 2> /dev/null | head -1`] + echo "Git: " `which git` [`(git --version 2>&1) 2> /dev/null | head -1`] + echo "Java: " `which java` [`(java -version 2>&1) 2> /dev/null | head -1`] + echo "Make: " `which make` [`(make --version 2>&1) 2> /dev/null | head -1`] + echo "MinGW-w64: " $MINGW_HOME + echo "OpenMPI: " `which mpirun` [`(mpirun --version 2>&1) 2> /dev/null | head -1`] + echo "PEexports: " `which pexports` [`(pexports -v 2>&1) 2> /dev/null | head -1`] + echo "Perl: " `which perl` [`(perl -v 2>&1) 2> /dev/null | head -2`] + echo "Python: " `which python` [`(python --version 2>&1) 2> /dev/null | head -1`] + echo "Subversion: " `which svn` [`(svn --version 2>&1) 2> /dev/null | head -1`] + echo "Wget: " `which wget` [`(wget --version 2>&1) 2> /dev/null | head -3`] +} + +finish() { + echo + echo "==========================================================================================" + echo "FOAM_INST_DIR=$FOAM_INST_DIR" + echo "ENVIRONMENT SETUP COMPLETE." + echo "==========================================================================================" + echo +} +# }}} + +# {{{ MAIN EXECUTION +set_system_paths +setup_foam_env +add_to_path +set_OMPI_env +check_versions +finish +# }}} + diff --git a/etc/prefs.sh.mingw b/etc/prefs.sh.mingw new file mode 100644 index 000000000..6a4f9cc7e --- /dev/null +++ b/etc/prefs.sh.mingw @@ -0,0 +1,242 @@ +#----------------------------------*-sh-*-------------------------------------- +# ========= | +# \\ / F ield | foam-extend: Open Source CFD +# \\ / O peration | Version: 3.2 +# \\ / A nd | Web: http://www.foam-extend.org +# \\/ M anipulation | For copyright notice see file Copyright +#------------------------------------------------------------------------------ +# License +# This file is part of foam-extend. +# +# foam-extend 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. +# +# foam-extend 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 foam-extend. If not, see . +# +# File +# etc/prefs.sh +# +# Description +# Preset variables for the FOAM configuration - POSIX shell syntax. +# +# The prefs.sh file will be sourced by the FOAM etc/bashrc when it is +# found +# +#------------------------------------------------------------------------------ + +export FOAM_VERBOSE=1 + +# Specify system compiler +# ~~~~~~~~~~~~~~~~~~~~~~~ +#compilerInstall=System +#compilerInstall=FOAM + +# Specify system openmpi +# ~~~~~~~~~~~~~~~~~~~~~~ +# +# Normally, you don't need to set more than these 3 env. variables +# The other openmpi related variables will be initialized using +# the command mpicc --showme: +# +#export WM_MPLIB=SYSTEMOPENMPI +export OPENMPI_DIR=$MPI_ROOTDIR +export OPENMPI_BIN_DIR=$OPENMPI_DIR/bin +# +#export OPENMPI_LIB_DIR="`$OPENMPI_BIN_DIR/mpicc --showme:libdirs`" +#export OPENMPI_INCLUDE_DIR="`$OPENMPI_BIN_DIR/mpicc --showme:incdirs`" +#export OPENMPI_COMPILE_FLAGS="`$OPENMPI_BIN_DIR/mpicc --showme:compile`" +#export OPENMPI_LINK_FLAGS="`$OPENMPI_BIN_DIR/mpicc --showme:link`" + +# Specify system installed ThirdParty packages/libraries +# NB: The packages installed under $WM_THIRD_PARTY_DIR +# will always override these values. +# So build your ThirdParty directory accordingly. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# System installed CUDA +#export CUDA_SYSTEM=1 +#export CUDA_DIR=path_to_system_installed_cuda +#export CUDA_BIN_DIR=$CUDA_DIR/bin +#export CUDA_LIB_DIR=$CUDA_DIR/lib +#export CUDA_INCLUDE_DIR=$CUDA_DIR/include +#export CUDA_ARCH=sm_20 + +# System installed Mesquite +#export MESQUITE_SYSTEM=1 +export MESQUITE_DIR=$WM_THIRD_PARTY_DIR/packages/mesquite-2.1.2 +export MESQUITE_BIN_DIR=$MESQUITE_DIR/bin +export MESQUITE_LIB_DIR=$MESQUITE_DIR/lib +export MESQUITE_INCLUDE_DIR=$MESQUITE_DIR/include + +# System installed Metis +#export METIS_SYSTEM=1 +export METIS_DIR=$WM_THIRD_PARTY_DIR/packages/metis-5.1.0 +export METIS_BIN_DIR=$METIS_DIR/bin +export METIS_LIB_DIR=$METIS_DIR/lib +export METIS_INCLUDE_DIR=$METIS_DIR/include + +# System installed ParMetis +#export PARMETIS_SYSTEM=1 +export PARMETIS_DIR=$WM_THIRD_PARTY_DIR/packages/parmetis-4.0.3 +export PARMETIS_BIN_DIR=$PARMETIS_DIR/bin +export PARMETIS_LIB_DIR=$PARMETIS_DIR/lib +export PARMETIS_INCLUDE_DIR=$PARMETIS_DIR/include + +# System installed ParMGridgen +#export PARMGRIDGEN_SYSTEM=1 +export PARMGRIDGEN_DIR=$WM_THIRD_PARTY_DIR/packages/ParMGridGen-1.0 +export PARMGRIDGEN_BIN_DIR=$PARMGRIDGEN_DIR/bin +export PARMGRIDGEN_LIB_DIR=$PARMGRIDGEN_DIR/lib +export PARMGRIDGEN_INCLUDE_DIR=$PARMGRIDGEN_DIR/include + +# System installed Libccmio +#export LIBCCMIO_SYSTEM=1 +#export LIBCCMIO_DIR=path_to_system_installed_libccmio +#export LIBCCMIO_BIN_DIR=$LIBCCMIO_DIR/bin +#export LIBCCMIO_LIB_DIR=$LIBCCMIO_DIR/lib +#export LIBCCMIO_INCLUDE_DIR=$LIBCCMIO_DIR/include + +# System installed Scotch +#export SCOTCH_SYSTEM=1 +export SCOTCH_DIR=$WM_THIRD_PARTY_DIR/packages/scotch_6.0.0 +export SCOTCH_BIN_DIR=$SCOTCH_DIR/bin +export SCOTCH_LIB_DIR=$SCOTCH_DIR/lib +export SCOTCH_INCLUDE_DIR=$SCOTCH_DIR/include + +# System installed CMake +#export CMAKE_SYSTEM=1 +#export CMAKE_DIR=path_to_system_installed_cmake +#export CMAKE_BIN_DIR=$CMAKE_DIR/bin + +# System installed Python +#export PYTHON_SYSTEM=1 +#export PYTHON_DIR=path_to_system_installed_python +#export PYTHON_BIN_DIR=$PYTHON_DIR/bin + +# System installed PyFoam +#export PYFOAM_SYSTEM=1 +#export PYFOAM_DIR=path_to_system_installed_python +#export PYFOAM_BIN_DIR=$PYFOAM_DIR/bin + +# System installed hwloc +#export HWLOC_SYSTEM=1 +#export HWLOC_DIR=path_to_system_installed_hwloc +#export HWLOC_BIN_DIR=$HWLOC_DIR/bin + +# System installed Qt +# This is the only package we assume is system installed by default. +# So we don't use a variable called QT_SYSTEM, but instead a variable +# called QT_THIRD_PARTY in order to override to the ThirdParty QT +# package. +# +# If you choose to use the system installed version of QT, keep +# the variable QT_THIRD_PARTY commented, and uncomment the initialization +# of the variable QT_DIR and QT_BIN_DIR. Make sure both variables are +# properly initialized. +# +# If you choose instead to use the ThirdParty version of QT, only uncomment +# the variable QT_THIRD_PARTY and set it to 1. Keep the initialization +# of the variables QT_DIR nd QT_BIN_DIR commented. The QT ThirdParty scripts +# will take care of setting the variables QT_DIR and QT_BIN_DIR to the +# proper values. +# +#export QT_THIRD_PARTY=1 +#export QT_DIR=path_to_system_installed_qt +#export QT_BIN_DIR=$QT_DIR/bin + +# System installed ParaView +#export PARAVIEW_SYSTEM=1 +#export PARAVIEW_DIR=path_to_system_installed_paraview +#export PARAVIEW_BIN_DIR=$PARAVIEW_DIR/bin + +# System installed bison +#export BISON_SYSTEM=1 + +# System installed flex +#export FLEX_SYSTEM=1 + +# System installed m4 +#export M4_SYSTEM=1 + +# Specify ParaView version +# ~~~~~~~~~~~~~~~~~~~~~~~~ +#export ParaView_VERSION=git # eg, cvs/git version +#export ParaView_MAJOR=3.7 + + +# System identifier for the FOAM CDash test harness on foam-extend +# +# By default, your system FQN/hostname will be used as the system identifier +# when publishing your test harness results on the FOAM CDash server +# on foam-extend. +# You can override your identifier using this environment variable +#export CDASH_SUBMIT_LOCAL_HOST_ID=choose_your_CDash_system_identifer + +# Mac OS X MacPorts root directory. +# The default value is '/opt/local/etc/macports'. +# In order to disable the usage of MacPorts on Mac OSX, simply initialize this +# variable to a non-existing directory, or to a dummy value. +#export MACOSX_MACPORTS_ROOT="_not_using_" + +# ThirdParty packages: build control variables +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# By enabling any of these variables, you will active the compilation and +# installation of the corresponding ThirdParty package +# +# For AllMake.stage1 +#export WM_THIRD_PARTY_USE_GCC_492=1 +#export WM_THIRD_PARTY_USE_GCC_484=1 +#export WM_THIRD_PARTY_USE_GCC_463=1 +#export WM_THIRD_PARTY_USE_GCC_451=1 +#export WM_THIRD_PARTY_USE_GCC_445=1 +#export WM_THIRD_PARTY_USE_PYTHON_27=1 +#export WM_THIRD_PARTY_USE_M4_1416=1 +#export WM_THIRD_PARTY_USE_BISON_27=1 +#export WM_THIRD_PARTY_USE_FLEX_2535=1 +#export WM_THIRD_PARTY_USE_CMAKE_322=1 + +# +# For AllMake.stage2 +#export WM_THIRD_PARTY_USE_OPENMPI_184=1 +#export WM_THIRD_PARTY_USE_OPENMPI_184_ConfigureAdditionalArgs='--enable-mpi-cxx --with-openib=/usr --with-openib-libdir=/usr/lib64' +#export WM_THIRD_PARTY_USE_OPENMPI_165=1 +#export WM_THIRD_PARTY_USE_OPENMPI_165_ConfigureAdditionalArgs='--enable-mpi-cxx --with-openib=/usr --with-openib-libdir=/usr/lib64' +#export WM_THIRD_PARTY_USE_OPENMPI_15=1 +#export WM_THIRD_PARTY_USE_OPENMPI_143=1 +#export WM_THIRD_PARTY_USE_OPENMPI_141=1 + +# +# For AllMake.stage3 +#export WM_THIRD_PARTY_USE_METIS_510=1 +#export WM_THIRD_PARTY_USE_PARMGRIDGEN_10=1 +#export WM_THIRD_PARTY_USE_LIBCCMIO_261=1 +#export WM_THIRD_PARTY_USE_MESQUITE_212=1 +#export WM_THIRD_PARTY_USE_SCOTCH_604=1 +##export WM_THIRD_PARTY_USE_SCOTCH_600=1 +#export WM_THIRD_PARTY_USE_PARMETIS_403=1 +##export WM_THIRD_PARTY_USE_ZOLTAN_36=1 +#export WM_THIRD_PARTY_USE_PYFOAM_064=1 +#export WM_THIRD_PARTY_USE_HWLOC_1101=1 +#export WM_THIRD_PARTY_USE_HWLOC_172=1 + +# +# For AllMake.stage4 +#export WM_THIRD_PARTY_USE_QT_486=1 +#export WM_THIRD_PARTY_USE_PARAVIEW_431=1 +#export WM_THIRD_PARTY_USE_PARAVIEW_410=1 + + +# Add in preset user preferences: will override site preferences +#if [ -e $WM_PROJECT_USER_DIR/etc/prefs.sh ] +#then +# _foamSource $WM_PROJECT_USER_DIR/etc/prefs.sh +#fi +# ----------------------------------------------------------------- end-of-file diff --git a/etc/settings.sh b/etc/settings.sh index ea573e647..b7c0e53e6 100644 --- a/etc/settings.sh +++ b/etc/settings.sh @@ -250,6 +250,12 @@ OPENMPI) _foamSource $WM_THIRD_PARTY_DIR/packages/$mpi_version/platforms/$WM_OPTIONS/etc/$mpi_version.sh fi + # On windows set mpi_version explicitly + if [ "$WM_ARCH_BASE" == "mingw" ] + then + mpi_version=openmpi-1.6.1 + fi + export FOAM_MPI_LIBBIN=$FOAM_LIBBIN/$mpi_version unset mpi_version ;; @@ -498,6 +504,13 @@ esac _foamAddLib $FOAM_MPI_LIBBIN +# Add DLLs on PATH for Windows (cannot use LD_LIBRARY_PATH) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if [ "$WM_ARCH_BASE" == "mingw" ] +then + _foamAddPath $FOAM_LIBBIN $FOAM_LIBBIN/$mpi_version +fi + # Set the minimum MPI buffer size (used by all platforms except SGI MPI) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ minBufferSize=20000000 diff --git a/src/OSspecific/MSWindows/MSwindows.C b/src/OSspecific/MSWindows/MSwindows.C new file mode 100644 index 000000000..7d827ebaf --- /dev/null +++ b/src/OSspecific/MSWindows/MSwindows.C @@ -0,0 +1,1418 @@ +/*---------------------------------------------------------------------------*\ + Copyright : (C) 2011 Symscape + Website : www.symscape.com +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Description + MS Windows specific functions + +\*---------------------------------------------------------------------------*/ + +#include "OSspecific.H" +#include "MSwindows.H" +#include "foamVersion.H" +#include "fileName.H" +#include "fileStat.H" + +#include +#include +#include +#include + +// Windows system header files +#include // _close +#include +#include + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(Foam::MSwindows, 0); + +namespace Foam +{ + +// Don't abort under windows, causes abort dialog to +// popup. Instead just exit with exitCode. +static +void sigAbortHandler(int exitCode) +{ + ::exit(exitCode); +} + + +static +bool installAbortHandler() +{ + // If it didn't succeed there's not much we can do, + // so don't check result. + ::signal(SIGABRT, &sigAbortHandler); + return true; +} + + +static bool const abortHandlerInstalled = installAbortHandler(); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +//- Get last windows api error from GetLastError +std::string MSwindows::getLastError() +{ + // Based on an example at: + // http://msdn2.microsoft.com/en-us/library/ms680582(VS.85).aspx + + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + lpDisplayBuf = LocalAlloc(LMEM_ZEROINIT, + (lstrlen(static_cast(lpMsgBuf))+40)*sizeof(TCHAR)); + sprintf(static_cast(lpDisplayBuf), + "Error %d: %s", int(dw), static_cast(lpMsgBuf)); + + const std::string errorMessage = static_cast(lpDisplayBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); + + return errorMessage; +} + + +//-Declared here to avoid polluting MSwindows.H with windows.h +namespace MSwindows +{ + //- Get windows user name + std::string getUserName(); + + //- Remove quotes, if any, from std::string + void removeQuotes(std::string & arg); + + //- Convert windows directory slash (back-slash) to unix (forward-slash). + //- Windows is fine with unix like directory slashes. + //- Foam's file io (see src/OpenFOAM/db/IOstreams/Sstreams/OSwrite.C) + //- uses back-slash as escape character and continuation, + //- so not an option to have windows file paths with back-slashes + void toUnixSlash(string & arg); + + //- Auto create and then delete array when this goes out of scope + template + class AutoArray + { + T* const array_; + + public: + AutoArray(const unsigned long arrayLength); + ~AutoArray(); + + //- Access array + T* get(); + }; // class AutoArray + + + //- Directory contents iterator + class DirectoryIterator + { + WIN32_FIND_DATA findData_; + HANDLE findHandle_; + fileName nextName_; + bool hasMore_; + + public: + DirectoryIterator(const fileName & directory); + ~DirectoryIterator(); + + //- Initialization succeeded + bool isValid() const; + + //- Has more? + bool hasNext() const; + + //- Next item + const fileName & next(); + }; // class DirectoryIterator +} // namespace MSwindows + + +inline +void MSwindows::removeQuotes(std::string & arg) +{ + std::size_t pos; + + while (std::string::npos != (pos = arg.find('"'))) + { + arg.erase(pos, 1); + } +} + + +inline +void MSwindows::toUnixSlash(string & arg) +{ + arg.replaceAll("\\", "/"); + + const std::string UNC("//"); + + // Preserve UNC i.e., \\machine-name\... + if (0 == arg.find(UNC)) + { + arg.replace(UNC, "\\\\"); + } +} + + +std::string MSwindows::getUserName() +{ + const DWORD bufferSize = 256; + TCHAR buffer[bufferSize]; + DWORD actualBufferSize = bufferSize; + std::string nameAsString; + + bool success = ::GetUserName(buffer, &actualBufferSize); + + if (success) + { + nameAsString = buffer; + } + else + { + if (ERROR_INSUFFICIENT_BUFFER == ::GetLastError() && + 32768 > actualBufferSize) + { + AutoArray actualBuffer(actualBufferSize); + ::GetUserName(actualBuffer.get(), &actualBufferSize); + nameAsString = actualBuffer.get(); + } + } + + return nameAsString; +} + + +template +inline +MSwindows::AutoArray::AutoArray(const unsigned long arrayLength) + : array_(new T[arrayLength]) +{} + + +template +inline +MSwindows::AutoArray::~AutoArray() +{ + delete [] array_; +} + + +template +inline +T* MSwindows::AutoArray::get() +{ + return array_; +} + + +inline +bool MSwindows::DirectoryIterator::isValid() const +{ + const bool valid = (INVALID_HANDLE_VALUE != findHandle_); + return valid; +} + + +MSwindows::DirectoryIterator::DirectoryIterator(const fileName & directory) +{ + const fileName directoryContents = directory/"*"; + findHandle_ = ::FindFirstFile(directoryContents.c_str(), &findData_); + hasMore_ = isValid(); +} + + +MSwindows::DirectoryIterator::~DirectoryIterator() +{ + if (isValid()) + { + ::FindClose(findHandle_); + } +} + + +inline +bool MSwindows::DirectoryIterator::hasNext() const +{ + assert(isValid()); + + return hasMore_; +} + + +inline +const fileName & MSwindows::DirectoryIterator::next() +{ + assert(hasNext()); + + nextName_ = findData_.cFileName; + hasMore_ = ::FindNextFile(findHandle_, &findData_); + + return nextName_; +} + + +//PID_T pid() +int pid() +{ + const DWORD processId = ::GetCurrentProcessId(); + return processId; +} + + +//PID_T ppid() +pid_t ppid() +{ + // No equivalent under windows. + + if (MSwindows::debug) + { + Info<< "ppid not supported under MSwindows" << endl; + } + + return 0; +} + + +//PID_T pgid() +pid_t pgid() +{ + // No equivalent under windows. + + if (MSwindows::debug) + { + Info<< "pgid not supported under MSwindows" << endl; + } + + return 0; +} + +std::string toUnixPath(const std::string & path) +{ + string unixPath(path); + MSwindows::toUnixSlash(unixPath); + MSwindows::removeQuotes(unixPath); + + return unixPath; +} + + +bool env(const word& envName) +{ + const DWORD actualBufferSize = + ::GetEnvironmentVariable(envName.c_str(), NULL, 0); + + const bool envExists = (0 < actualBufferSize); + return envExists; +} + + +string getEnv(const word& envName) +{ + std::string envAsString; + + const DWORD actualBufferSize = + ::GetEnvironmentVariable(envName.c_str(), NULL, 0); + + if (0 < actualBufferSize) + { + MSwindows::AutoArray actualBuffer(actualBufferSize); + ::GetEnvironmentVariable(envName.c_str(), + actualBuffer.get(), + actualBufferSize); + envAsString = actualBuffer.get(); + toUnixPath(envAsString); + } + + return envAsString; +} + + +bool setEnv +( + const word& envName, + const string& value, + const bool overwrite +) +{ + const bool success = + ::SetEnvironmentVariable(envName.c_str(), value.c_str()); + return success; +} + + +word hostName() +{ + const bool full = true; + const DWORD bufferSize = MAX_COMPUTERNAME_LENGTH + 1; + TCHAR buffer[bufferSize]; + DWORD actualBufferSize = bufferSize; + + const bool success = + ::GetComputerName(buffer, &actualBufferSize); + const string computerName = success ? buffer : string::null; + return computerName; +} + + +string domainName() +{ + // Could use ::gethostname and ::gethostbyname like POSIX.C, but would + // then need to link against ws_32. Prefer to minimize dependencies. + + return string::null; +} + + +word userName() +{ + std::string name = getEnv("USERNAME"); + + if (name.empty()) + { + name = MSwindows::getUserName(); + } + + return name; +} + + +bool isAdministrator() +{ + // Not supported but assume worst case for Foam::dynamicCode::checkSecurity + return true; +} + + +fileName home() +{ + std::string homeDir = getEnv("HOME"); + + if (homeDir.empty()) + { + homeDir = getEnv("USERPROFILE"); + } + + return homeDir; +} + + +fileName home(const word& userName) +{ + return home(); +} + + +fileName cwd() +{ + string currentDirectory; + + const DWORD actualBufferSize = + ::GetCurrentDirectory(0, NULL); + + if (0 < actualBufferSize) + { + MSwindows::AutoArray actualBuffer(actualBufferSize); + ::GetCurrentDirectory(actualBufferSize, + actualBuffer.get()); + currentDirectory = actualBuffer.get(); + MSwindows::toUnixSlash(currentDirectory); + } + else + { + FatalErrorIn("cwd()") + << "Couldn't get the current working directory" + << exit(FatalError); + } + + return currentDirectory; +} + + +bool chDir(const fileName& dir) +{ + const bool success = ::SetCurrentDirectory(dir.c_str()); + return success; +} + + +fileNameList findEtcFiles +( + const fileName& name, + bool mandatory, + bool findFirst +) +{ + fileNameList results; +/* + // Search for user files in + // * ~/.OpenFOAM/VERSION + // * ~/.OpenFOAM + // + fileName searchDir = home()/".OpenFOAM"; + if (isDir(searchDir)) + { + fileName fullName = searchDir/FOAMversion/name; + if (isFile(fullName)) + { + results.append(fullName); + if (findFirst) + { + return results; + } + } + + fullName = searchDir/name; + if (isFile(fullName)) + { + results.append(fullName); + if (findFirst) + { + return results; + } + } + } + + // Search for group (site) files in + // * $WM_PROJECT_SITE/VERSION + // * $WM_PROJECT_SITE + // + searchDir = getEnv("WM_PROJECT_SITE"); + if (searchDir.size()) + { + if (isDir(searchDir)) + { + fileName fullName = searchDir/FOAMversion/name; + if (isFile(fullName)) + { + results.append(fullName); + if (findFirst) + { + return results; + } + } + + fullName = searchDir/name; + if (isFile(fullName)) + { + results.append(fullName); + if (findFirst) + { + return results; + } + } + } + } + else + { + // OR search for group (site) files in + // * $WM_PROJECT_INST_DIR/site/VERSION + // * $WM_PROJECT_INST_DIR/site + // + searchDir = getEnv("WM_PROJECT_INST_DIR"); + if (isDir(searchDir)) + { + fileName fullName = searchDir/"site"/FOAMversion/name; + if (isFile(fullName)) + { + results.append(fullName); + if (findFirst) + { + return results; + } + } + + fullName = searchDir/"site"/name; + if (isFile(fullName)) + { + results.append(fullName); + if (findFirst) + { + return results; + } + } + } + } + + // Search for other (shipped) files in + // * $WM_PROJECT_DIR/etc + // + searchDir = getEnv("WM_PROJECT_DIR"); + if (isDir(searchDir)) + { + fileName fullName = searchDir/"etc"/name; + if (isFile(fullName)) + { + results.append(fullName); + if (findFirst) + { + return results; + } + } + } + + // Not found + if (results.empty()) + { + // Abort if the file is mandatory, otherwise return null + if (mandatory) + { + std::cerr + << "--> FOAM FATAL ERROR in Foam::findEtcFiles() :" + " could not find mandatory file\n '" + << name.c_str() << "'\n\n" << std::endl; + ::exit(1); + } + } +*/ + // Return list of matching paths or empty list if none found + return results; +} + + +fileName findEtcFile(const fileName& name, bool mandatory) +{ + // Search most likely location first + // Search installation files: + // ~~~~~~~~~~~~~~~~~~~~~~~~~~ + fileName searchDir = getEnv("WM_PROJECT_DIR"); + if (isDir(searchDir)) + { + // Check for shipped OpenFOAM file in $WM_PROJECT_DIR/etc + fileName fullName = searchDir/"etc"/name; + if (isFile(fullName)) + { + return fullName; + } + } + + // Search user files: + // ~~~~~~~~~~~~~~~~~~ + searchDir = home()/".OpenFOAM"; + if (isDir(searchDir)) + { + // Check for user file in ~/.OpenFOAM/VERSION + fileName fullName = searchDir/FOAMversion/name; + if (isFile(fullName)) + { + return fullName; + } + + // Check for version-independent user file in ~/.OpenFOAM + fullName = searchDir/name; + if (isFile(fullName)) + { + return fullName; + } + } + + + // Search site files: + // ~~~~~~~~~~~~~~~~~~ + searchDir = getEnv("WM_PROJECT_INST_DIR"); + if (isDir(searchDir)) + { + // Check for site file in $WM_PROJECT_INST_DIR/site/VERSION + fileName fullName = searchDir/"site"/FOAMversion/name; + if (isFile(fullName)) + { + return fullName; + } + + // Check for version-independent site file in $WM_PROJECT_INST_DIR/site + fullName = searchDir/"site"/name; + if (isFile(fullName)) + { + return fullName; + } + } + + // Not found + // abort if the file is mandatory, otherwise return null + if (mandatory) + { + cerr<< "--> FOAM FATAL ERROR in Foam::findEtcFile() :" + " could not find mandatory file\n '" + << name.c_str() << "'\n\n" << std::endl; + ::exit(1); + } + + // Return null-constructed fileName rather than fileName::null + // to avoid cyclic dependencies in the construction of globals + return fileName(); +} + + +bool mkDir(const fileName& pathName, const mode_t mode) +{ + if (pathName.empty()) + { + return false; + } + + + bool success = ::CreateDirectory(pathName.c_str(), NULL); + + if (success) + { + chMod(pathName, mode); + } + else + { + const DWORD error = ::GetLastError(); + + switch (error) + { + case ERROR_ALREADY_EXISTS: + { + success = true; + break; + } + case ERROR_PATH_NOT_FOUND: + { + // Part of the path does not exist so try to create it + const fileName& parentName = pathName.path(); + + if (parentName.size() && mkDir(parentName, mode)) + { + success = mkDir(pathName, mode); + } + + break; + } + } + + if (!success) + { + FatalErrorIn("mkDir(const fileName&, mode_t)") + << "Couldn't create directory: " << pathName + << " " << MSwindows::getLastError() + << exit(FatalError); + } + } + + return success; +} + + +// Set the file mode +bool chMod(const fileName& name, const mode_t m) +{ + const int success = _chmod(name.c_str(), m); + return success; +} + + +// Return the file mode +mode_t mode(const fileName& name) +{ + fileStat fileStatus(name); + + const mode_t m = fileStatus.isValid() ? + fileStatus.status().st_mode : 0; + return m; +} + + +// Return the file type: FILE or DIRECTORY +fileName::Type type(const fileName& name) +{ + fileName::Type fileType = fileName::UNDEFINED; + const DWORD attrs = ::GetFileAttributes(name.c_str()); + + if (attrs != INVALID_FILE_ATTRIBUTES) + { + fileType = (attrs & FILE_ATTRIBUTE_DIRECTORY) ? + fileName::DIRECTORY : + fileName::FILE; + } + + return fileType; +} + + +static +bool +isGzFile(const fileName& name) +{ + std::string gzName(name); + gzName += ".gz"; + const DWORD attrs = ::GetFileAttributes(gzName.c_str()); + const bool success = (attrs != INVALID_FILE_ATTRIBUTES); + + return success; +} + + +// Does the name exist in the filing system? +bool exists(const fileName& name, const bool checkGzip) +{ + const DWORD attrs = ::GetFileAttributes(name.c_str()); + const bool success = (attrs != INVALID_FILE_ATTRIBUTES) || + (checkGzip && isGzFile(name)); + + return success; +} + + +// Does the directory exist +bool isDir(const fileName& name) +{ + const DWORD attrs = ::GetFileAttributes(name.c_str()); + bool success = (attrs != INVALID_FILE_ATTRIBUTES) && + (attrs & FILE_ATTRIBUTE_DIRECTORY); + + return success; +} + + +// Does the file exist +bool isFile(const fileName& name, const bool checkGzip) +{ + const DWORD attrs = ::GetFileAttributes(name.c_str()); + const bool success = ((attrs != INVALID_FILE_ATTRIBUTES) && + !(attrs & FILE_ATTRIBUTE_DIRECTORY)) || + (checkGzip && isGzFile(name)); + + return success; +} + + +// Return size of file +off_t fileSize(const fileName& name) +{ + fileStat fileStatus(name); + + const off_t fileSize = fileStatus.isValid() ? + fileStatus.status().st_size : -1; + return fileSize; +} + + +// Return time of last file modification +time_t lastModified(const fileName& name) +{ + fileStat fileStatus(name); + + const time_t modifiedTime = fileStatus.isValid() ? + fileStatus.status().st_mtime : 0; + return modifiedTime; +} + + +// Read a directory and return the entries as a string list +fileNameList readDir +( + const fileName& directory, + const fileName::Type type, + const bool filtergz +) +{ + // Initial filename list size + // also used as increment if initial size found to be insufficient + const int maxNnames = 100; + + if (MSwindows::debug) + { + Info<< "readDir(const fileName&, const fileType, const bool filtergz)" + << " : reading directory " << directory << endl; + } + + // Setup empty string list MAXTVALUES long + fileNameList dirEntries(maxNnames); + + // Temporary variables and counters + label nEntries = 0; + + MSwindows::DirectoryIterator dirIt(directory); + + if (dirIt.isValid()) + { + while (dirIt.hasNext()) + { + const fileName & fName = dirIt.next(); + + // ignore files begining with ., i.e. '.', '..' and '.*' + if (fName.size() > 0 && fName[size_t(0)] != '.') + { + word fileNameExt = fName.ext(); + + if + ( + (type == fileName::DIRECTORY) + || + ( + type == fileName::FILE + && fName[fName.size()-1] != '~' + && fileNameExt != "bak" + && fileNameExt != "BAK" + && fileNameExt != "old" + && fileNameExt != "save" + ) + ) + { + if ((directory/fName).type() == type) + { + if (nEntries >= dirEntries.size()) + { + dirEntries.setSize(dirEntries.size() + maxNnames); + } + + if (filtergz && fileNameExt == "gz") + { + dirEntries[nEntries++] = fName.lessExt(); + } + else + { + dirEntries[nEntries++] = fName; + } + } + } + } + } + } + else if (MSwindows::debug) + { + Info<< "readDir(const fileName&, const fileType, " + "const bool filtergz) : cannot open directory " + << directory << endl; + } + + // Reset the length of the entries list + dirEntries.setSize(nEntries); + + return dirEntries; +} + + +// Copy, recursively if necessary, the source top the destination +bool cp(const fileName& src, const fileName& dest) +{ + // Make sure source exists. + if (!exists(src)) + { + return false; + } + + fileName destFile(dest); + + // Check type of source file. + if (src.type() == fileName::FILE) + { + // If dest is a directory, create the destination file name. + if (destFile.type() == fileName::DIRECTORY) + { + destFile = destFile/src.name(); + } + + // Make sure the destination directory exists. + if (!isDir(destFile.path()) && !mkDir(destFile.path())) + { + return false; + } + + // Open and check streams. + // Use binary mode in case we read binary. + // Causes windows reading to fail if we don't. + std::ifstream srcStream(src.c_str(), + ios_base::in|ios_base::binary); + if (!srcStream) + { + return false; + } + + // Use binary mode in case we write binary. + // Causes windows reading to fail if we don't. + std::ofstream destStream(destFile.c_str(), + ios_base::out|ios_base::binary); + if (!destStream) + { + return false; + } + + // Copy character data. + char ch; + while (srcStream.get(ch)) + { + destStream.put(ch); + } + + // Final check. + if (!srcStream.eof() || !destStream) + { + return false; + } + } + else if (src.type() == fileName::DIRECTORY) + { + // If dest is a directory, create the destination file name. + if (destFile.type() == fileName::DIRECTORY) + { + destFile = destFile/src.component(src.components().size() -1); + } + + // Make sure the destination directory extists. + if (!isDir(destFile) && !mkDir(destFile)) + { + return false; + } + + // Copy files + fileNameList contents = readDir(src, fileName::FILE, false); + forAll(contents, i) + { + if (MSwindows::debug) + { + Info<< "Copying : " << src/contents[i] + << " to " << destFile/contents[i] << endl; + } + + // File to file. + cp(src/contents[i], destFile/contents[i]); + } + + // Copy sub directories. + fileNameList subdirs = readDir(src, fileName::DIRECTORY); + forAll(subdirs, i) + { + if (MSwindows::debug) + { + Info<< "Copying : " << src/subdirs[i] + << " to " << destFile << endl; + } + + // Dir to Dir. + cp(src/subdirs[i], destFile); + } + } + + return true; +} + + +// Create a softlink. destFile should not exist. Returns true if successful. +bool ln(const fileName& src, const fileName& dest) +{ + // Seems that prior to Vista softlinking was poorly supported. + // Vista does a better job, but requires adminstrator privileges. + // Skip for now. + + if (MSwindows::debug) + { + Info<< "MSwindows does not support ln - softlinking" << endl; + } + + return false; +} + + +// Rename srcFile destFile +bool mv(const fileName& srcFile, const fileName& destFile) +{ + if (MSwindows::debug) + { + Info<< "Move : " << srcFile << " to " << destFile << endl; + } + + const fileName destName = + ((destFile.type() == fileName::DIRECTORY) + && (srcFile.type() != fileName::DIRECTORY)) ? + destFile/srcFile.name() : + destFile; + + const bool success = + (0 == std::rename(srcFile.c_str(), destName.c_str())); + + return success; +} + + +//- Rename to a corresponding backup file +// If the backup file already exists, attempt with "01" .. "99" index +bool mvBak(const fileName& src, const std::string& ext) +{ + if (MSwindows::debug) + { + Info<< "mvBak : " << src << " to extension " << ext << endl; + } + + if (exists(src, false)) + { + const int maxIndex = 99; + char index[3]; + + for (int n = 0; n <= maxIndex; n++) + { + fileName dstName(src + "." + ext); + if (n) + { + sprintf(index, "%02d", n); + dstName += index; + } + + // avoid overwriting existing files, except for the last + // possible index where we have no choice + if (!exists(dstName, false) || n == maxIndex) + { + return (0 == std::rename(src.c_str(), dstName.c_str())); + } + + } + } + + // fall-through: nothing to do + return false; +} + + +// Remove a file returning true if successful otherwise false +bool rm(const fileName& file) +{ + if (MSwindows::debug) + { + Info<< "Removing : " << file << endl; + } + + bool success = (0 == std::remove(file.c_str())); + + // If deleting plain file name failed try with .gz + if (!success) + { + const std::string fileGz = file + ".gz"; + success = (0 == std::remove(fileGz.c_str())); + } + + return success; +} + + +// Remove a dirctory and it's contents +bool rmDir(const fileName& directory) +{ + if (MSwindows::debug) + { + Info<< "rmdir(const fileName&) : " + << "removing directory " << directory << endl; + } + + bool success = true; + + // Need to destroy DirectorIterator prior to + // removing directory otherwise fails on Windows XP + { + MSwindows::DirectoryIterator dirIt(directory); + + while (success && dirIt.hasNext()) + { + const fileName & fName = dirIt.next(); + + if (fName != "." && fName != "..") + { + fileName path = directory/fName; + + if (path.type() == fileName::DIRECTORY) + { + success = rmDir(path); + + if (!success) + { + WarningIn("rmdir(const fileName&)") + << "failed to remove directory " << fName + << " while removing directory " << directory + << endl; + } + } + else + { + success = rm(path); + + if (!success) + { + WarningIn("rmdir(const fileName&)") + << "failed to remove file " << fName + << " while removing directory " << directory + << endl; + } + } + } + } + } + + if (success) + { + success = ::RemoveDirectory(directory.c_str()); + + if (!success) + { + WarningIn("rmdir(const fileName&)") + << "failed to remove directory " << directory << endl; + } + } + + return success; +} + + +//- Sleep for the specified number of seconds +unsigned int sleep(const unsigned int s) +{ + const DWORD milliseconds = s * 1000; + + ::Sleep(milliseconds); + + return 0; +} + + +void fdClose(const int fd) +{ + const int result = ::_close(fd); + + if (0 != result) + { + FatalErrorIn + ( + "Foam::fdClose(const int fd)" + ) << "close error on " << fd << endl + << abort(FatalError); + } +} + + +//- Check if machine is up by pinging given port +bool ping +( + const word& destName, + const label destPort, + const label timeOut +) +{ + // Appears that socket calls require adminstrator privileges. + // Skip for now. + + if (MSwindows::debug) + { + Info<< "MSwindows does not support ping" << endl; + } + + return false; +} + + +//- Check if machine is up by ping port 22 = ssh and 222 = rsh +bool ping(const word& hostname, const label timeOut) +{ + return ping(hostname, 222, timeOut) || ping(hostname, 22, timeOut); +} + + +int system(const string& command) +{ + return std::system(command.c_str()); +} + + +// Explicitly track loaded libraries, rather than use +// EnumerateLoadedModules64 and have to link against +// Dbghelp.dll +// Details at http://msdn.microsoft.com/en-us/library/ms679316(v=vs.85).aspx +typedef std::map OfLoadedLibs; + +static +OfLoadedLibs & +getLoadedLibs() +{ + static OfLoadedLibs loadedLibs; + return loadedLibs; +} + + +//- Open shared library +void* dlOpen(const fileName& libName, const bool check) +{ + if (MSwindows::debug) + { + Info<< "dlOpen(const fileName&)" + << " : LoadLibrary of " << libName << endl; + } + + const char* dllExt = ".dll"; + + // Assume libName is of the form, lib.so + string winLibName(libName); + winLibName.replace(".so", dllExt); + void* handle = ::LoadLibrary(winLibName.c_str()); + + if (NULL == handle) + { + // Assumes libName = name + winLibName = "lib"; + winLibName += libName; + winLibName += dllExt; + + handle = ::LoadLibrary(winLibName.c_str()); + } + + if (NULL != handle) + { + getLoadedLibs()[handle] = libName; + } + else if (check) + { + WarningIn("dlOpen(const fileName&, const bool)") + << "dlopen error : " << MSwindows::getLastError() + << endl; + } + + if (MSwindows::debug) + { + Info<< "dlOpen(const fileName&)" + << " : LoadLibrary of " << libName + << " handle " << handle << endl; + } + + return handle; +} + + +//- Close shared library +bool dlClose(void* const handle) +{ + if (MSwindows::debug) + { + Info<< "dlClose(void*)" + << " : FreeLibrary of handle " << handle << endl; + } + + const bool success = + ::FreeLibrary(static_cast(handle)); + + if (success) + { + getLoadedLibs().erase(handle); + } + + return success; +} + + +void* dlSym(void* handle, const std::string& symbol) +{ + if (MSwindows::debug) + { + Info<< "dlSym(void*, const std::string&)" + << " : GetProcAddress of " << symbol << endl; + } + // get address of symbol + void* fun = (void*) ::GetProcAddress(static_cast(handle), symbol.c_str()); + + if (NULL == fun) + { + WarningIn("dlSym(void*, const std::string&)") + << "Cannot lookup symbol " << symbol << " : " << MSwindows::getLastError() + << endl; + } + + return fun; +} + + +bool dlSymFound(void* handle, const std::string& symbol) +{ + if (handle && !symbol.empty()) + { + if (MSwindows::debug) + { + Info<< "dlSymFound(void*, const std::string&)" + << " : GetProcAddress of " << symbol << endl; + } + + // get address of symbol + void* fun = (void*) ::GetProcAddress(static_cast(handle), symbol.c_str()); + + return (NULL != fun); + } + else + { + return false; + } +} + + +fileNameList dlLoaded() +{ + fileNameList libs; + int counter(0); + OfLoadedLibs & loadedLibs = getLoadedLibs(); + + for + ( + OfLoadedLibs::const_iterator it = loadedLibs.begin(); + it != loadedLibs.end(); + ++it + ) + { + libs.newElmt(counter++) = it->second; + } + + if (MSwindows::debug) + { + Info<< "dlLoaded()" + << " : determined loaded libraries :" << libs.size() << endl; + } + return libs; +} + + +void osRandomSeed(const label seed) +{ + std::srand(seed); +} + + +label osRandomInteger() +{ + return std::rand(); +} + + +scalar osRandomDouble() +{ + return scalar(std::rand())/RAND_MAX; +} + +} // namespace Foam +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/MSwindows.H b/src/OSspecific/MSWindows/MSwindows.H new file mode 100644 index 000000000..3c761a837 --- /dev/null +++ b/src/OSspecific/MSWindows/MSwindows.H @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------------*\ + Copyright : (C) 2011 Symscape + Website : www.symscape.com +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM 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. + + OpenFOAM 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 OpenFOAM. If not, see . + +Class + MSwindows + +Description + +SourceFiles + MSwindows.C + +\*---------------------------------------------------------------------------*/ + +#ifndef MSwindows_H +#define MSwindows_H + +#include + +#include "className.H" + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace MSwindows +{ + //- Declare name of the class and it's debug switch + NamespaceName("MSwindows"); + + //- Get last windows api error from GetLastError + std::string getLastError(); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/Make/files b/src/OSspecific/MSWindows/Make/files new file mode 100644 index 000000000..2cdd725c5 --- /dev/null +++ b/src/OSspecific/MSWindows/Make/files @@ -0,0 +1,14 @@ +signals/sigFpe.C +signals/sigSegv.C +signals/sigInt.C +signals/sigQuit.C +regExp.C +timer.C +fileStat.C +MSwindows.C +cpuTime/cpuTime.C +clockTime/clockTime.C +multiThreader/multiThreader.C +printStack.C + +LIB = $(FOAM_LIBBIN)/libOSspecific diff --git a/src/OSspecific/MSWindows/Make/options b/src/OSspecific/MSWindows/Make/options new file mode 100644 index 000000000..e69de29bb diff --git a/src/OSspecific/MSWindows/clockTime/clockTime.C b/src/OSspecific/MSWindows/clockTime/clockTime.C new file mode 100644 index 000000000..d76bb57e9 --- /dev/null +++ b/src/OSspecific/MSWindows/clockTime/clockTime.C @@ -0,0 +1,87 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "clockTime.H" +#include "scalar.H" +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * Static Members * * * * * * * * * * * * * * // + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void clockTime::getTime(struct timeval& t) +{ + gettimeofday(&t, NULL); +} + + +double clockTime::timeDifference +( + const struct timeval& start, + const struct timeval& end +) +{ + return end.tv_sec - start.tv_sec + 1E-6*(end.tv_usec - start.tv_usec); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +clockTime::clockTime() +{ + getTime(startTime_); + lastTime_ = startTime_; + newTime_ = startTime_; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +double clockTime::elapsedTime() const +{ + getTime(newTime_); + return timeDifference(startTime_, newTime_); +} + + +double clockTime::timeIncrement() const +{ + lastTime_ = newTime_; + getTime(newTime_); + return timeDifference(lastTime_, newTime_); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/clockTime/clockTime.H b/src/OSspecific/MSWindows/clockTime/clockTime.H new file mode 100644 index 000000000..4f10a6b30 --- /dev/null +++ b/src/OSspecific/MSWindows/clockTime/clockTime.H @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Class + Foam::clockTime + +Description + Starts timing (using rtc) and returns elapsed time from start. + Better resolution (2uSec instead of ~20mSec) than cpuTime. + +SourceFiles + clockTime.C + +\*---------------------------------------------------------------------------*/ + +#ifndef clockTime_H +#define clockTime_H + +#include +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class clockTime Declaration +\*---------------------------------------------------------------------------*/ + +class clockTime +{ + // Private data + + struct timeval startTime_; + mutable struct timeval lastTime_; + mutable struct timeval newTime_; + + static void getTime(struct timeval& t); + + static double timeDifference + ( + const struct timeval& start, + const struct timeval& end + ); + + +public: + + // Constructors + + //- Construct from components + clockTime(); + + + // Member Functions + + // Access + + //- Returns CPU time from start of run + double elapsedTime() const; + + //- Returns CPU time from last call of clockTimeIncrement() + double timeIncrement() const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/cpuTime/cpuTime.C b/src/OSspecific/MSWindows/cpuTime/cpuTime.C new file mode 100644 index 000000000..e494da66d --- /dev/null +++ b/src/OSspecific/MSWindows/cpuTime/cpuTime.C @@ -0,0 +1,86 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Description + Starts timing CPU usage and return elapsed time from start. + +\*---------------------------------------------------------------------------*/ + +#include "cpuTime.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void cpuTime::getTime(std::clock_t& t) +{ + t = std::clock(); +} + + +double cpuTime::timeDifference +( + const std::clock_t& start, + const std::clock_t& end +) +{ + const double difference = std::difftime(end, start) / CLOCKS_PER_SEC; + return difference; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +cpuTime::cpuTime() +{ + getTime(startTime_); + lastTime_ = startTime_; + newTime_ = startTime_; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +double cpuTime::elapsedCpuTime() const +{ + getTime(newTime_); + return timeDifference(startTime_, newTime_); +} + + +double cpuTime::cpuTimeIncrement() const +{ + lastTime_ = newTime_; + getTime(newTime_); + return timeDifference(lastTime_, newTime_); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/cpuTime/cpuTime.H b/src/OSspecific/MSWindows/cpuTime/cpuTime.H new file mode 100644 index 000000000..4c91dd972 --- /dev/null +++ b/src/OSspecific/MSWindows/cpuTime/cpuTime.H @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Class + Foam::cpuTime + +Description + Starts timing CPU usage and return elapsed time from start. + +SeeAlso + clockTime + +SourceFiles + cpuTime.C + +\*---------------------------------------------------------------------------*/ + +#ifndef cpuTime_H +#define cpuTime_H + +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class cpuTime Declaration +\*---------------------------------------------------------------------------*/ + +class cpuTime +{ + // Private data + + std::clock_t startTime_; + mutable std::clock_t lastTime_; + mutable std::clock_t newTime_; + + static void getTime(std::clock_t& t); + + static double timeDifference + ( + const std::clock_t& start, + const std::clock_t& end + ); + + +public: + + // Constructors + + //- Construct from components + cpuTime(); + + + // Member Functions + + // Access + + //- Returns CPU time from start of run + double elapsedCpuTime() const; + + //- Returns CPU time from last call of cpuTimeIncrement() + double cpuTimeIncrement() const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/deelx.h b/src/OSspecific/MSWindows/deelx.h new file mode 100644 index 000000000..c3748da21 --- /dev/null +++ b/src/OSspecific/MSWindows/deelx.h @@ -0,0 +1,4342 @@ +// deelx.h +// +// DEELX Regular Expression Engine (v1.2) +// +// Copyright 2006 (c) RegExLab.com +// All Rights Reserved. +// +// http://www.regexlab.com/deelx/ +// +// Author: Ê·ÊÙΰ (sswater shi) +// sswater@gmail.com +// +// $Revision: 1.1.2.39 $ +// + +#ifndef __DEELX_REGEXP__H__ +#define __DEELX_REGEXP__H__ + +#include +#include +#include +#include +#include + +// +// Data Reference +// +template class CBufferRefT +{ +public: + CBufferRefT(const ELT * pcsz, int length); + CBufferRefT(const ELT * pcsz); + +public: + int nCompare (const ELT * pcsz) const; + int nCompareNoCase(const ELT * pcsz) const; + int Compare (const ELT * pcsz) const; + int CompareNoCase(const ELT * pcsz) const; + int Compare (const CBufferRefT &) const; + int CompareNoCase(const CBufferRefT &) const; + + ELT At (int nIndex, ELT def = 0) const; + ELT operator [] (int nIndex) const; + + const ELT * GetBuffer() const; + int GetSize() const; + +public: + virtual ~CBufferRefT(); + +// Content +protected: + const ELT * m_pRef; + int m_nSize; +}; + +// +// Implemenation +// +template CBufferRefT :: CBufferRefT(const ELT * pcsz, int length) +{ + m_pRef = pcsz; + m_nSize = length; +} + +template CBufferRefT :: CBufferRefT(const ELT * pcsz) +{ + m_pRef = pcsz; + m_nSize = 0; + + if(pcsz != 0) while(m_pRef[m_nSize] != 0) m_nSize ++; +} + +template int CBufferRefT :: nCompare(const ELT * pcsz) const +{ + for(int i=0; i int CBufferRefT :: nCompareNoCase(const ELT * pcsz) const +{ + for(int i=0; i inline int CBufferRefT :: Compare(const ELT * pcsz) const +{ + return nCompare(pcsz) ? 1 : (int)pcsz[m_nSize]; +} + +template inline int CBufferRefT :: CompareNoCase(const ELT * pcsz) const +{ + return nCompareNoCase(pcsz) ? 1 : (int)pcsz[m_nSize]; +} + +template inline int CBufferRefT :: Compare(const CBufferRefT & cref) const +{ + return m_nSize == cref.m_nSize ? nCompare(cref.GetBuffer()) : 1; +} + +template inline int CBufferRefT :: CompareNoCase(const CBufferRefT & cref) const +{ + return m_nSize == cref.m_nSize ? nCompareNoCase(cref.GetBuffer()) : 1; +} + +template inline ELT CBufferRefT :: At(int nIndex, ELT def) const +{ + return nIndex >= m_nSize ? def : m_pRef[nIndex]; +} + +template inline ELT CBufferRefT :: operator [] (int nIndex) const +{ + return nIndex >= m_nSize ? 0 : m_pRef[nIndex]; +} + +template const ELT * CBufferRefT :: GetBuffer() const +{ + static const ELT _def[] = {0}; return m_pRef ? m_pRef : _def; +} + +template inline int CBufferRefT :: GetSize() const +{ + return m_nSize; +} + +template CBufferRefT :: ~CBufferRefT() +{ +} + +// +// Data Buffer +// +template class CBufferT : public CBufferRefT +{ +public: + CBufferT(const ELT * pcsz, int length); + CBufferT(const ELT * pcsz); + CBufferT(); + +public: + ELT & operator [] (int nIndex); + const ELT & operator [] (int nIndex) const; + void Append(const ELT * pcsz, int length, int eol = 0); + void Append(ELT el, int eol = 0); + +public: + void Push(ELT el); + int Pop (ELT & el); + int Peek(ELT & el) const; + +public: + const ELT * GetBuffer() const; + ELT * GetBuffer(); + ELT * Detach(); + void Release(); + void Prepare(int index, int fill = 0); + void Restore(int size); + +public: + virtual ~CBufferT(); + +// Content +protected: + ELT * m_pBuffer; + int m_nMaxLength; +}; + +// +// Implemenation +// +template CBufferT :: CBufferT(const ELT * pcsz, int length) : CBufferRefT (0, length) +{ + m_nMaxLength = CBufferRefT :: m_nSize + 1; + + CBufferRefT :: m_pRef = m_pBuffer = (ELT *) malloc(sizeof(ELT) * m_nMaxLength); + memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT :: m_nSize); + m_pBuffer[CBufferRefT :: m_nSize] = 0; +} + +template CBufferT :: CBufferT(const ELT * pcsz) : CBufferRefT (pcsz) +{ + m_nMaxLength = CBufferRefT :: m_nSize + 1; + + CBufferRefT :: m_pRef = m_pBuffer = (ELT *) malloc(sizeof(ELT) * m_nMaxLength); + memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT :: m_nSize); + m_pBuffer[CBufferRefT :: m_nSize] = 0; +} + +template CBufferT :: CBufferT() : CBufferRefT (0, 0) +{ + m_nMaxLength = 0; + m_pBuffer = 0; +} + +template inline ELT & CBufferT :: operator [] (int nIndex) +{ + return m_pBuffer[nIndex]; +} + +template inline const ELT & CBufferT :: operator [] (int nIndex) const +{ + return m_pBuffer[nIndex]; +} + +template void CBufferT :: Append(const ELT * pcsz, int length, int eol) +{ + int nNewLength = m_nMaxLength; + + // Check length + if(nNewLength < 8) + nNewLength = 8; + + if(CBufferRefT :: m_nSize + length + eol > nNewLength) + nNewLength *= 2; + + if(CBufferRefT :: m_nSize + length + eol > nNewLength) + { + nNewLength = CBufferRefT :: m_nSize + length + eol + 11; + nNewLength -= nNewLength % 8; + } + + // Realloc + if(nNewLength > m_nMaxLength) + { + CBufferRefT :: m_pRef = m_pBuffer = (ELT *) realloc(m_pBuffer, sizeof(ELT) * nNewLength); + m_nMaxLength = nNewLength; + } + + // Append + memcpy(m_pBuffer + CBufferRefT :: m_nSize, pcsz, sizeof(ELT) * length); + CBufferRefT :: m_nSize += length; + + if(eol > 0) m_pBuffer[CBufferRefT :: m_nSize] = 0; +} + +template inline void CBufferT :: Append(ELT el, int eol) +{ + Append(&el, 1, eol); +} + +template void CBufferT :: Push(ELT el) +{ + // Realloc + if(CBufferRefT :: m_nSize >= m_nMaxLength) + { + int nNewLength = m_nMaxLength * 2; + if( nNewLength < 8 ) nNewLength = 8; + + CBufferRefT :: m_pRef = m_pBuffer = (ELT *) realloc(m_pBuffer, sizeof(ELT) * nNewLength); + m_nMaxLength = nNewLength; + } + + // Append + m_pBuffer[CBufferRefT :: m_nSize++] = el; +} + +template inline int CBufferT :: Pop(ELT & el) +{ + if(CBufferRefT :: m_nSize > 0) + { + el = m_pBuffer[--CBufferRefT :: m_nSize]; + return 1; + } + else + { + return 0; + } +} + +template inline int CBufferT :: Peek(ELT & el) const +{ + if(CBufferRefT :: m_nSize > 0) + { + el = m_pBuffer[CBufferRefT :: m_nSize - 1]; + return 1; + } + else + { + return 0; + } +} + +template const ELT * CBufferT :: GetBuffer() const +{ + static const ELT _def[] = {0}; return m_pBuffer ? m_pBuffer : _def; +} + +template ELT * CBufferT :: GetBuffer() +{ + static const ELT _def[] = {0}; return m_pBuffer ? m_pBuffer : (ELT *)_def; +} + +template ELT * CBufferT :: Detach() +{ + ELT * pBuffer = m_pBuffer; + + CBufferRefT :: m_pRef = m_pBuffer = 0; + CBufferRefT :: m_nSize = m_nMaxLength = 0; + + return pBuffer; +} + +template void CBufferT :: Release() +{ + ELT * pBuffer = Detach(); + + if(pBuffer != 0) free(pBuffer); +} + +template void CBufferT :: Prepare(int index, int fill) +{ + int nNewSize = index + 1; + + // Realloc + if(nNewSize > m_nMaxLength) + { + int nNewLength = m_nMaxLength; + + if( nNewLength < 8 ) + nNewLength = 8; + + if( nNewSize > nNewLength ) + nNewLength *= 2; + + if( nNewSize > nNewLength ) + { + nNewLength = nNewSize + 11; + nNewLength -= nNewLength % 8; + } + + CBufferRefT :: m_pRef = m_pBuffer = (ELT *) realloc(m_pBuffer, sizeof(ELT) * nNewLength); + m_nMaxLength = nNewLength; + } + + // size + if( CBufferRefT :: m_nSize < nNewSize ) + { + memset(m_pBuffer + CBufferRefT :: m_nSize, fill, sizeof(ELT) * (nNewSize - CBufferRefT :: m_nSize)); + CBufferRefT :: m_nSize = nNewSize; + } +} + +template inline void CBufferT :: Restore(int size) +{ + CBufferRefT :: m_nSize = size; +} + +template CBufferT :: ~CBufferT() +{ + if(m_pBuffer != 0) free(m_pBuffer); +} + +// +// Context +// +class CContext +{ +public: + CBufferT m_stack; + CBufferT m_capturestack, m_captureindex; + +public: + int m_nCurrentPos; + int m_nBeginPos; + int m_nLastBeginPos; + int m_nParenZindex; + + void * m_pMatchString; + int m_pMatchStringLength; +}; + +// +// Interface +// +class ElxInterface +{ +public: + virtual int Match (CContext * pContext) const = 0; + virtual int MatchNext(CContext * pContext) const = 0; + +public: + virtual ~ElxInterface() {}; +}; + +// +// Alternative +// +template class CAlternativeElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CAlternativeElxT(); + +public: + CBufferT m_elxlist; +}; + +typedef CAlternativeElxT <0> CAlternativeElx; + +// +// Assert +// +template class CAssertElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CAssertElxT(ElxInterface * pelx, int byes = 1); + +public: + ElxInterface * m_pelx; + int m_byes; +}; + +typedef CAssertElxT <0> CAssertElx; + +// +// Back reference elx +// +template class CBackrefElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CBackrefElxT(int nnumber, int brightleft, int bignorecase); + +public: + int m_nnumber; + int m_brightleft; + int m_bignorecase; + + CBufferT m_szNamed; +}; + +// +// Implementation +// +template CBackrefElxT :: CBackrefElxT(int nnumber, int brightleft, int bignorecase) +{ + m_nnumber = nnumber; + m_brightleft = brightleft; + m_bignorecase = bignorecase; +} + +template int CBackrefElxT :: Match(CContext * pContext) const +{ + // check number, for named + if( m_nnumber < 0 || m_nnumber >= pContext->m_captureindex.GetSize() ) return 0; + + int index = pContext->m_captureindex[m_nnumber]; + if( index < 0 ) return 0; + + // check enclosed + int pos1 = pContext->m_capturestack[index + 1]; + int pos2 = pContext->m_capturestack[index + 2]; + + if( pos2 < 0 ) pos2 = pContext->m_nCurrentPos; + + // info + int lpos = pos1 < pos2 ? pos1 : pos2; + int rpos = pos1 < pos2 ? pos2 : pos1; + int slen = rpos - lpos; + + const CHART * pcsz = (const CHART *)pContext->m_pMatchString; + int npos = pContext->m_nCurrentPos; + int tlen = pContext->m_pMatchStringLength; + + // compare + int bsucc; + CBufferRefT refstr(pcsz + lpos, slen); + + if( m_brightleft ) + { + if(npos < slen) + return 0; + + if(m_bignorecase) + bsucc = ! refstr.nCompareNoCase(pcsz + (npos - slen)); + else + bsucc = ! refstr.nCompare (pcsz + (npos - slen)); + + if( bsucc ) + { + pContext->m_stack.Push(npos); + pContext->m_nCurrentPos -= slen; + } + } + else + { + if(npos + slen > tlen) + return 0; + + if(m_bignorecase) + bsucc = ! refstr.nCompareNoCase(pcsz + npos); + else + bsucc = ! refstr.nCompare (pcsz + npos); + + if( bsucc ) + { + pContext->m_stack.Push(npos); + pContext->m_nCurrentPos += slen; + } + } + + return bsucc; +} + +template int CBackrefElxT :: MatchNext(CContext * pContext) const +{ + int npos = 0; + + pContext->m_stack.Pop(npos); + pContext->m_nCurrentPos = npos; + + return 0; +} + +// RCHART +#ifndef RCHART + #define RCHART(ch) ((CHART)ch) +#endif + +// BOUNDARY_TYPE +enum BOUNDARY_TYPE +{ + BOUNDARY_FILE_BEGIN, // begin of whole text + BOUNDARY_FILE_END , // end of whole text + BOUNDARY_FILE_END_N, // end of whole text, or before newline at the end + BOUNDARY_LINE_BEGIN, // begin of line + BOUNDARY_LINE_END , // end of line + BOUNDARY_WORD_BEGIN, // begin of word + BOUNDARY_WORD_END , // end of word + BOUNDARY_WORD_EDGE , +}; + +// +// Boundary Elx +// +template class CBoundaryElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CBoundaryElxT(int ntype, int byes = 1); + +protected: + static int IsWordChar(CHART ch); + +public: + int m_ntype; + int m_byes; +}; + +// +// Implementation +// +template CBoundaryElxT :: CBoundaryElxT(int ntype, int byes) +{ + m_ntype = ntype; + m_byes = byes; +} + +template int CBoundaryElxT :: Match(CContext * pContext) const +{ + const CHART * pcsz = (const CHART *)pContext->m_pMatchString; + int npos = pContext->m_nCurrentPos; + int tlen = pContext->m_pMatchStringLength; + + CHART chL = npos > 0 ? pcsz[npos - 1] : 0; + CHART chR = npos < tlen ? pcsz[npos ] : 0; + + int bsucc = 0; + + switch(m_ntype) + { + case BOUNDARY_FILE_BEGIN: + bsucc = (npos <= 0); + break; + + case BOUNDARY_FILE_END: + bsucc = (npos >= tlen); + break; + + case BOUNDARY_FILE_END_N: + bsucc = (npos >= tlen) || (pcsz[tlen-1] == RCHART('\n') && (npos == tlen-1 || (pcsz[tlen-2] == RCHART('\r') && npos == tlen-2))); + break; + + case BOUNDARY_LINE_BEGIN: + bsucc = (npos <= 0 ) || (chL == RCHART('\n')) || ((chL == RCHART('\r')) && (chR != RCHART('\n'))); + break; + + case BOUNDARY_LINE_END: + bsucc = (npos >= tlen) || (chR == RCHART('\r')) || ((chR == RCHART('\n')) && (chL != RCHART('\r'))); + break; + + case BOUNDARY_WORD_BEGIN: + bsucc = ! IsWordChar(chL) && IsWordChar(chR); + break; + + case BOUNDARY_WORD_END: + bsucc = IsWordChar(chL) && ! IsWordChar(chR); + break; + + case BOUNDARY_WORD_EDGE: + bsucc = IsWordChar(chL) ? ! IsWordChar(chR) : IsWordChar(chR); + break; + } + + return m_byes ? bsucc : ! bsucc; +} + +template int CBoundaryElxT :: MatchNext(CContext *) const +{ + return 0; +} + +template inline int CBoundaryElxT :: IsWordChar(CHART ch) +{ + return (ch >= RCHART('A') && ch <= RCHART('Z')) || (ch >= RCHART('a') && ch <= RCHART('z')) || (ch >= RCHART('0') && ch <= RCHART('9')) || (ch == RCHART('_')); +} + +// +// Bracket +// +template class CBracketElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CBracketElxT(int nnumber, int bright); + int CheckCaptureIndex(int & index, CContext * pContext) const; + +public: + int m_nnumber; + int m_bright; + + CBufferT m_szNamed; +}; + +template CBracketElxT :: CBracketElxT(int nnumber, int bright) +{ + m_nnumber = nnumber; + m_bright = bright; +} + +template inline int CBracketElxT :: CheckCaptureIndex(int & index, CContext * pContext) const +{ + if( index >= pContext->m_capturestack.GetSize() ) + index = pContext->m_capturestack.GetSize() - 4; + + while(index >= 0) + { + if(pContext->m_capturestack[index] == m_nnumber) + { + return 1; + } + + index -= 4; + } + + + return 0; +} + +// +// capturestack[index+0] => Group number +// capturestack[index+1] => Capture start pos +// capturestack[index+2] => Capture end pos +// capturestack[index+3] => Capture enclose z-index, zindex<0 means inner group with same name +// +template int CBracketElxT :: Match(CContext * pContext) const +{ + // check, for named + if(m_nnumber < 0) return 0; + + if( ! m_bright ) + { + pContext->m_captureindex.Prepare(m_nnumber, -1); + int index = pContext->m_captureindex[m_nnumber]; + + // check + if(CheckCaptureIndex(index, pContext) && pContext->m_capturestack[index+2] < 0) + { + pContext->m_capturestack[index+3] --; + return 1; + } + + // save + pContext->m_captureindex[m_nnumber] = pContext->m_capturestack.GetSize(); + + pContext->m_capturestack.Push(m_nnumber); + pContext->m_capturestack.Push(pContext->m_nCurrentPos); + pContext->m_capturestack.Push(-1); + pContext->m_capturestack.Push( 0); // z-index + } + else + { + // check + int index = pContext->m_captureindex[m_nnumber]; + + if(CheckCaptureIndex(index, pContext)) + { + if(pContext->m_capturestack[index + 3] < 0) // check inner group with same name + { + pContext->m_capturestack[index + 3] ++; + return 1; + } + + // save + pContext->m_capturestack[index + 2] = pContext->m_nCurrentPos; + pContext->m_capturestack[index + 3] = pContext->m_nParenZindex ++; + } + } + + return 1; +} + +template int CBracketElxT :: MatchNext(CContext * pContext) const +{ + int index = pContext->m_captureindex[m_nnumber]; + if( ! CheckCaptureIndex(index, pContext) ) + { + return 0; + } + + if( ! m_bright ) + { + if(pContext->m_capturestack[index + 3] < 0) + { + pContext->m_capturestack[index + 3] ++; + return 0; + } + + pContext->m_capturestack.Restore(pContext->m_capturestack.GetSize() - 4); + + // to find + CheckCaptureIndex(index, pContext); + + // new index + pContext->m_captureindex[m_nnumber] = index; + } + else + { + if( pContext->m_capturestack[index + 2] >= 0 ) + { + pContext->m_capturestack[index + 2] = -1; + pContext->m_capturestack[index + 3] = 0; + } + else + { + pContext->m_capturestack[index + 3] --; + } + } + + return 0; +} + +// +// Deletage +// +template class CDelegateElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CDelegateElxT(int ndata = 0); + +public: + ElxInterface * m_pelx; + int m_ndata; // +0 : recursive to + // -3 : named recursive + + CBufferT m_szNamed; +}; + +template CDelegateElxT :: CDelegateElxT(int ndata) +{ + m_pelx = 0; + m_ndata = ndata; +} + +template int CDelegateElxT :: Match(CContext * pContext) const +{ + if(m_pelx != 0) + return m_pelx->Match(pContext); + else + return 1; +} + +template int CDelegateElxT :: MatchNext(CContext * pContext) const +{ + if(m_pelx != 0) + return m_pelx->MatchNext(pContext); + else + return 0; +} + +// +// Empty +// +template class CEmptyElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CEmptyElxT(); +}; + +typedef CEmptyElxT <0> CEmptyElx; + +// +// Global +// +template class CGlobalElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CGlobalElxT(); +}; + +typedef CGlobalElxT <0> CGlobalElx; + +// +// Repeat +// +template class CRepeatElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CRepeatElxT(ElxInterface * pelx, int ntimes); + +protected: + int MatchFixed (CContext * pContext) const; + int MatchNextFixed(CContext * pContext) const; + +public: + ElxInterface * m_pelx; + int m_nfixed; +}; + +typedef CRepeatElxT <0> CRepeatElx; + +// +// Greedy +// +template class CGreedyElxT : public CRepeatElxT +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CGreedyElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX); + +protected: + int MatchVart (CContext * pContext) const; + int MatchNextVart(CContext * pContext) const; + +public: + int m_nvart; +}; + +typedef CGreedyElxT <0> CGreedyElx; + +// +// Independent +// +template class CIndependentElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CIndependentElxT(ElxInterface * pelx); + +public: + ElxInterface * m_pelx; +}; + +typedef CIndependentElxT <0> CIndependentElx; + +// +// List +// +template class CListElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CListElxT(int brightleft); + +public: + CBufferT m_elxlist; + int m_brightleft; +}; + +typedef CListElxT <0> CListElx; + +// +// Posix Elx +// +template class CPosixElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CPosixElxT(const char * posix, int brightleft); + +protected: + static int m_isblank(int c); + +public: + int (*m_posixfun)(int); + int m_brightleft; + int m_byes; +}; + +// +// Implementation +// +template CPosixElxT :: CPosixElxT(const char * posix, int brightleft) +{ + m_brightleft = brightleft; + + if(posix[1] == '^') + { + m_byes = 0; + posix += 2; + } + else + { + m_byes = 1; + posix += 1; + } + + if (!strncmp(posix, "alnum:", 6)) m_posixfun = ::isalnum ; + else if(!strncmp(posix, "alpha:", 6)) m_posixfun = ::isalpha ; + else if(!strncmp(posix, "ascii:", 6)) m_posixfun = ::isascii ; + else if(!strncmp(posix, "cntrl:", 6)) m_posixfun = ::iscntrl ; + else if(!strncmp(posix, "digit:", 6)) m_posixfun = ::isdigit ; + else if(!strncmp(posix, "graph:", 6)) m_posixfun = ::isgraph ; + else if(!strncmp(posix, "lower:", 6)) m_posixfun = ::islower ; + else if(!strncmp(posix, "print:", 6)) m_posixfun = ::isprint ; + else if(!strncmp(posix, "punct:", 6)) m_posixfun = ::ispunct ; + else if(!strncmp(posix, "space:", 6)) m_posixfun = ::isspace ; + else if(!strncmp(posix, "upper:", 6)) m_posixfun = ::isupper ; + else if(!strncmp(posix, "xdigit:",7)) m_posixfun = ::isxdigit; + else if(!strncmp(posix, "blank:", 6)) m_posixfun = m_isblank ; + else m_posixfun = 0 ; +} + +template int CPosixElxT :: m_isblank(int c) +{ + return c == 0x20 || c == '\t'; +} + +template int CPosixElxT :: Match(CContext * pContext) const +{ + if(m_posixfun == 0) return 0; + + int tlen = pContext->m_pMatchStringLength; + int npos = pContext->m_nCurrentPos; + + // check + int at = m_brightleft ? npos - 1 : npos; + if( at < 0 || at >= tlen ) + return 0; + + CHART ch = ((const CHART *)pContext->m_pMatchString)[at]; + + int bsucc = (*m_posixfun)(ch); + + if( ! m_byes ) + bsucc = ! bsucc; + + if( bsucc ) + pContext->m_nCurrentPos += m_brightleft ? -1 : 1; + + return bsucc; +} + +template int CPosixElxT :: MatchNext(CContext * pContext) const +{ + pContext->m_nCurrentPos -= m_brightleft ? -1 : 1; + return 0; +} + +// +// Possessive +// +template class CPossessiveElxT : public CGreedyElxT +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CPossessiveElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX); +}; + +typedef CPossessiveElxT <0> CPossessiveElx; + +// +// Range Elx +// +template class CRangeElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CRangeElxT(int brightleft, int byes); + +public: + int IsContainChar(CHART ch) const; + +public: + CBufferT m_ranges; + CBufferT m_chars; + CBufferT m_embeds; + +public: + int m_brightleft; + int m_byes; +}; + +// +// Implementation +// +template CRangeElxT :: CRangeElxT(int brightleft, int byes) +{ + m_brightleft = brightleft; + m_byes = byes; +} + +template int CRangeElxT :: Match(CContext * pContext) const +{ + int tlen = pContext->m_pMatchStringLength; + int npos = pContext->m_nCurrentPos; + + // check + int at = m_brightleft ? npos - 1 : npos; + if( at < 0 || at >= tlen ) + return 0; + + CHART ch = ((const CHART *)pContext->m_pMatchString)[at]; + int bsucc = 0, i; + + // compare + for(i=0; !bsucc && iMatch(pContext)) + { + pContext->m_nCurrentPos = npos; + bsucc = 1; + } + } + + if( ! m_byes ) + bsucc = ! bsucc; + + if( bsucc ) + pContext->m_nCurrentPos += m_brightleft ? -1 : 1; + + return bsucc; +} + +template int CRangeElxT :: IsContainChar(CHART ch) const +{ + int bsucc = 0, i; + + // compare + for(i=0; !bsucc && i int CRangeElxT :: MatchNext(CContext * pContext) const +{ + pContext->m_nCurrentPos -= m_brightleft ? -1 : 1; + return 0; +} + +// +// Reluctant +// +template class CReluctantElxT : public CRepeatElxT +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CReluctantElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX); + +protected: + int MatchVart (CContext * pContext) const; + int MatchNextVart(CContext * pContext) const; + +public: + int m_nvart; +}; + +typedef CReluctantElxT <0> CReluctantElx; + +// +// String Elx +// +template class CStringElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CStringElxT(const CHART * fixed, int nlength, int brightleft, int bignorecase); + +public: + CBufferT m_szPattern; + int m_brightleft; + int m_bignorecase; +}; + +// +// Implementation +// +template CStringElxT :: CStringElxT(const CHART * fixed, int nlength, int brightleft, int bignorecase) : m_szPattern(fixed, nlength) +{ + m_brightleft = brightleft; + m_bignorecase = bignorecase; +} + +template int CStringElxT :: Match(CContext * pContext) const +{ + const CHART * pcsz = (const CHART *)pContext->m_pMatchString; + int npos = pContext->m_nCurrentPos; + int tlen = pContext->m_pMatchStringLength; + int slen = m_szPattern.GetSize(); + + int bsucc; + + if(m_brightleft) + { + if(npos < slen) + return 0; + + if(m_bignorecase) + bsucc = ! m_szPattern.nCompareNoCase(pcsz + (npos - slen)); + else + bsucc = ! m_szPattern.nCompare (pcsz + (npos - slen)); + + if( bsucc ) + pContext->m_nCurrentPos -= slen; + } + else + { + if(npos + slen > tlen) + return 0; + + if(m_bignorecase) + bsucc = ! m_szPattern.nCompareNoCase(pcsz + npos); + else + bsucc = ! m_szPattern.nCompare (pcsz + npos); + + if( bsucc ) + pContext->m_nCurrentPos += slen; + } + + return bsucc; +} + +template int CStringElxT :: MatchNext(CContext * pContext) const +{ + int slen = m_szPattern.GetSize(); + + if(m_brightleft) + pContext->m_nCurrentPos += slen; + else + pContext->m_nCurrentPos -= slen; + + return 0; +} + +// +// CConditionElx +// +template class CConditionElxT : public ElxInterface +{ +public: + int Match (CContext * pContext) const; + int MatchNext(CContext * pContext) const; + +public: + CConditionElxT(); + +public: + // backref condition + int m_nnumber; + CBufferT m_szNamed; + + // elx condition + ElxInterface * m_pelxask; + + // selection + ElxInterface * m_pelxyes, * m_pelxno; +}; + +template CConditionElxT :: CConditionElxT() +{ + m_nnumber = -1; +} + +template int CConditionElxT :: Match(CContext * pContext) const +{ + // status + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + + // condition result + int condition_yes = 0; + + // backref type + if( m_nnumber >= 0 ) + { + do + { + if(m_nnumber >= pContext->m_captureindex.GetSize()) break; + + int index = pContext->m_captureindex[m_nnumber]; + if( index < 0) break; + + // else valid + condition_yes = 1; + } + while(0); + } + else + { + if( m_pelxask == 0 ) + condition_yes = 1; + else + condition_yes = m_pelxask->Match(pContext); + + pContext->m_stack.Restore(nsize); + pContext->m_nCurrentPos = nbegin; + } + + // elx result + int bsucc; + if( condition_yes ) + bsucc = m_pelxyes == 0 ? 1 : m_pelxyes->Match(pContext); + else + bsucc = m_pelxno == 0 ? 1 : m_pelxno ->Match(pContext); + + if( bsucc ) + { + pContext->m_stack.Push(ncsize); + pContext->m_stack.Push(condition_yes); + } + else + { + pContext->m_capturestack.Restore(ncsize); + } + + return bsucc; +} + +template int CConditionElxT :: MatchNext(CContext * pContext) const +{ + // pop + int ncsize = 0, condition_yes = 0; + + pContext->m_stack.Pop(condition_yes); + pContext->m_stack.Pop(ncsize); + + // elx result + int bsucc; + if( condition_yes ) + bsucc = m_pelxyes == 0 ? 0 : m_pelxyes->MatchNext(pContext); + else + bsucc = m_pelxno == 0 ? 0 : m_pelxno ->MatchNext(pContext); + + if( bsucc ) + { + pContext->m_stack.Push(ncsize); + pContext->m_stack.Push(condition_yes); + } + else + { + pContext->m_capturestack.Restore(ncsize); + } + + return bsucc; +} + +// +// MatchResult +// +template class MatchResultT +{ +public: + int IsMatched() const; + +public: + int GetStart() const; + int GetEnd () const; + +public: + int MaxGroupNumber() const; + int GetGroupStart(int nGroupNumber) const; + int GetGroupEnd (int nGroupNumber) const; + +public: + MatchResultT(CContext * pContext = 0, int nMaxNumber = -1); + MatchResultT & operator = (const MatchResultT &); + inline operator int() const { return IsMatched(); } + +public: + CBufferT m_result; +}; + +typedef MatchResultT <0> MatchResult; + +// Stocked Elx IDs +enum STOCKELX_ID_DEFINES +{ + STOCKELX_EMPTY = 0, + + /////////////////////// + + STOCKELX_DOT_ALL, + STOCKELX_DOT_NOT_ALL, + + STOCKELX_WORD, + STOCKELX_WORD_NOT, + + STOCKELX_SPACE, + STOCKELX_SPACE_NOT, + + STOCKELX_DIGITAL, + STOCKELX_DIGITAL_NOT, + + ////////////////////// + + STOCKELX_DOT_ALL_RIGHTLEFT, + STOCKELX_DOT_NOT_ALL_RIGHTLEFT, + + STOCKELX_WORD_RIGHTLEFT, + STOCKELX_WORD_RIGHTLEFT_NOT, + + STOCKELX_SPACE_RIGHTLEFT, + STOCKELX_SPACE_RIGHTLEFT_NOT, + + STOCKELX_DIGITAL_RIGHTLEFT, + STOCKELX_DIGITAL_RIGHTLEFT_NOT, + + ///////////////////// + + STOCKELX_COUNT +}; + +// REGEX_FLAGS +#ifndef _REGEX_FLAGS_DEFINED + enum REGEX_FLAGS + { + NO_FLAG = 0, + SINGLELINE = 0x01, + MULTILINE = 0x02, + GLOBAL = 0x04, + IGNORECASE = 0x08, + RIGHTTOLEFT = 0x10, + EXTENDED = 0x20, + }; + #define _REGEX_FLAGS_DEFINED +#endif + +// +// Builder T +// +template class CBuilderT +{ +public: + typedef CDelegateElxT CDelegateElx; + typedef CBracketElxT CBracketElx; + typedef CBackrefElxT CBackrefElx; + typedef CConditionElxT CConditionElx; + +// Methods +public: + ElxInterface * Build(const CBufferRefT & pattern, int flags); + int GetNamedNumber(const CBufferRefT & named) const; + void Clear(); + +public: + CBuilderT(); + ~CBuilderT(); + +// Public Attributes +public: + ElxInterface * m_pTopElx; + int m_nFlags; + int m_nMaxNumber; + int m_nNextNamed; + int m_nGroupCount; + + CBufferT m_objlist; + CBufferT m_grouplist; + CBufferT m_recursivelist; + CBufferT m_namedlist; + CBufferT m_namedbackreflist; + CBufferT m_namedconditionlist; + +// CHART_INFO +protected: + struct CHART_INFO + { + public: + CHART ch; + int type; + int pos; + int len; + + public: + CHART_INFO(CHART c, int t, int p = 0, int l = 0) { ch = c; type = t; pos = p; len = l; } + inline int operator == (const CHART_INFO & ci) { return ch == ci.ch && type == ci.type; } + inline int operator != (const CHART_INFO & ci) { return ! operator == (ci); } + }; + +protected: + static unsigned int Hex2Int(const CHART * pcsz, int length, int & used); + static int ReadDec(char * & str, unsigned int & dec); + void MoveNext(); + int GetNext2(); + + ElxInterface * BuildAlternative(int vaflags); + ElxInterface * BuildList (int & flags); + ElxInterface * BuildRepeat (int & flags); + ElxInterface * BuildSimple (int & flags); + ElxInterface * BuildCharset (int & flags); + ElxInterface * BuildRecursive (int & flags); + ElxInterface * BuildBoundary (int & flags); + ElxInterface * BuildBackref (int & flags); + + ElxInterface * GetStockElx (int nStockId); + ElxInterface * Keep(ElxInterface * pElx); + +// Private Attributes +protected: + CBufferRefT m_pattern; + CHART_INFO prev, curr, next, nex2; + int m_nNextPos; + int m_nCharsetDepth; + int m_bQuoted; + int (*m_quote_fun)(int); + + ElxInterface * m_pStockElxs[STOCKELX_COUNT]; +}; + +// +// Implementation +// +template CBuilderT :: CBuilderT() : m_pattern(0, 0), prev(0, 0), curr(0, 0), next(0, 0), nex2(0, 0) +{ + Clear(); +} + +template CBuilderT :: ~CBuilderT() +{ + Clear(); +} + +template int CBuilderT :: GetNamedNumber(const CBufferRefT & named) const +{ + for(int i=0; im_elxlist[0])->m_szNamed.CompareNoCase(named) ) + return ((CBracketElx *)m_namedlist[i]->m_elxlist[0])->m_nnumber; + } + + return -3; +} + +template ElxInterface * CBuilderT :: Build(const CBufferRefT & pattern, int flags) +{ + // init + m_pattern = pattern; + m_nNextPos = 0; + m_nCharsetDepth = 0; + m_nMaxNumber = 0; + m_nNextNamed = 0; + m_nFlags = flags; + m_bQuoted = 0; + m_quote_fun = 0; + + m_grouplist .Restore(0); + m_recursivelist .Restore(0); + m_namedlist .Restore(0); + m_namedbackreflist .Restore(0); + m_namedconditionlist.Restore(0); + + int i; + for(i=0; i<3; i++) MoveNext(); + + // build + m_pTopElx = BuildAlternative(flags); + + // group 0 + m_grouplist.Prepare(0); + m_grouplist[0] = m_pTopElx; + + // append named to unnamed + m_nGroupCount = m_grouplist.GetSize(); + + m_grouplist.Prepare(m_nMaxNumber + m_namedlist.GetSize()); + + for(i=0; im_elxlist[0]; + CBracketElx * pright = (CBracketElx *)m_namedlist[i]->m_elxlist[2]; + + // append + m_grouplist[m_nGroupCount ++] = m_namedlist[i]; + + if( pleft->m_nnumber > 0 ) + continue; + + // same name + int find_same_name = GetNamedNumber(pleft->m_szNamed); + if( find_same_name >= 0 ) + { + pleft ->m_nnumber = find_same_name; + pright->m_nnumber = find_same_name; + } + else + { + m_nMaxNumber ++; + + pleft ->m_nnumber = m_nMaxNumber; + pright->m_nnumber = m_nMaxNumber; + } + } + + for(i=1; im_elxlist[0]; + + if( pleft->m_nnumber > m_nMaxNumber ) + m_nMaxNumber = pleft->m_nnumber; + } + + // connect recursive + for(i=0; im_ndata == -3 ) + m_recursivelist[i]->m_ndata = GetNamedNumber(m_recursivelist[i]->m_szNamed); + + if( m_recursivelist[i]->m_ndata >= 0 && m_recursivelist[i]->m_ndata <= m_nMaxNumber ) + { + if( m_recursivelist[i]->m_ndata == 0 ) + m_recursivelist[i]->m_pelx = m_pTopElx; + else for(int j=1; jm_ndata == ((CBracketElx *)((CListElx*)m_grouplist[j])->m_elxlist[0])->m_nnumber) + { + m_recursivelist[i]->m_pelx = m_grouplist[j]; + break; + } + } + } + } + + // named backref + for(i=0; im_nnumber = GetNamedNumber(m_namedbackreflist[i]->m_szNamed); + } + + // named condition + for(i=0; im_szNamed); + if( nn >= 0 ) + { + m_namedconditionlist[i]->m_nnumber = nn; + m_namedconditionlist[i]->m_pelxask = 0; + } + } + + return m_pTopElx; +} + +template void CBuilderT :: Clear() +{ + for(int i=0; i unsigned int CBuilderT :: Hex2Int(const CHART * pcsz, int length, int & used) +{ + unsigned int result = 0; + int & i = used; + + for(i=0; i= RCHART('0') && pcsz[i] <= RCHART('9')) + result = (result << 4) + (pcsz[i] - RCHART('0')); + else if(pcsz[i] >= RCHART('A') && pcsz[i] <= RCHART('F')) + result = (result << 4) + (0x0A + (pcsz[i] - RCHART('A'))); + else if(pcsz[i] >= RCHART('a') && pcsz[i] <= RCHART('f')) + result = (result << 4) + (0x0A + (pcsz[i] - RCHART('a'))); + else + break; + } + + return result; +} + +template inline ElxInterface * CBuilderT :: Keep(ElxInterface * pelx) +{ + m_objlist.Push(pelx); + return pelx; +} + +template void CBuilderT :: MoveNext() +{ + // forwards + prev = curr; + curr = next; + next = nex2; + + // get nex2 + while( ! GetNext2() ) {}; +} + +template int CBuilderT :: GetNext2() +{ + // check length + if(m_nNextPos >= m_pattern.GetSize()) + { + nex2 = CHART_INFO(0, 1, m_nNextPos, 0); + return 1; + } + + int delta = 1; + CHART ch = m_pattern[m_nNextPos]; + + // if quoted + if(m_bQuoted) + { + if(ch == RCHART('\\')) + { + if(m_pattern[m_nNextPos + 1] == RCHART('E')) + { + m_quote_fun = 0; + m_bQuoted = 0; + m_nNextPos += 2; + return 0; + } + } + + if(m_quote_fun != 0) + nex2 = CHART_INFO((CHART)(*m_quote_fun)((int)ch), 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + + m_nNextPos += delta; + + return 1; + } + + // common + switch(ch) + { + case RCHART('\\'): + { + CHART ch1 = m_pattern[m_nNextPos+1]; + + // backref + if(ch1 >= RCHART('0') && ch1 <= RCHART('9')) + { + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + break; + } + + // escape + delta = 2; + + switch(ch1) + { + case RCHART('A'): + case RCHART('Z'): + case RCHART('z'): + case RCHART('w'): + case RCHART('W'): + case RCHART('s'): + case RCHART('S'): + case RCHART('B'): + case RCHART('d'): + case RCHART('D'): + case RCHART('k'): + case RCHART('g'): + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + + case RCHART('b'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO('\b', 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + + /* + case RCHART('<'): + case RCHART('>'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + */ + + case RCHART('x'): + if(m_pattern[m_nNextPos+2] != '{') + { + int red = 0; + unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 2, 2, red); + + delta += red; + + if(red > 0) + nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + + break; + } + + case RCHART('u'): + if(m_pattern[m_nNextPos+2] != '{') + { + int red = 0; + unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 2, 4, red); + + delta += red; + + if(red > 0) + nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + } + else + { + int red = 0; + unsigned int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 3, sizeof(int) * 2, red); + + delta += red; + + while(m_nNextPos + delta < m_pattern.GetSize() && m_pattern.At(m_nNextPos + delta) != RCHART('}')) + delta ++; + + delta ++; // skip '}' + + nex2 = CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta); + } + break; + + case RCHART('a'): nex2 = CHART_INFO(RCHART('\a'), 0, m_nNextPos, delta); break; + case RCHART('f'): nex2 = CHART_INFO(RCHART('\f'), 0, m_nNextPos, delta); break; + case RCHART('n'): nex2 = CHART_INFO(RCHART('\n'), 0, m_nNextPos, delta); break; + case RCHART('r'): nex2 = CHART_INFO(RCHART('\r'), 0, m_nNextPos, delta); break; + case RCHART('t'): nex2 = CHART_INFO(RCHART('\t'), 0, m_nNextPos, delta); break; + case RCHART('v'): nex2 = CHART_INFO(RCHART('\v'), 0, m_nNextPos, delta); break; + case RCHART('e'): nex2 = CHART_INFO(RCHART( 27 ), 0, m_nNextPos, delta); break; + + case RCHART('G'): // skip '\G' + if(m_nCharsetDepth > 0) + { + m_nNextPos += 2; + return 0; + } + else + { + nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); + break; + } + + case RCHART('L'): + if( ! m_quote_fun ) m_quote_fun = ::tolower; + + case RCHART('U'): + if( ! m_quote_fun ) m_quote_fun = ::toupper; + + case RCHART('Q'): + { + m_bQuoted = 1; + m_nNextPos += 2; + return 0; + } + + case RCHART('E'): + { + m_quote_fun = 0; + m_bQuoted = 0; + m_nNextPos += 2; + return 0; + } + + case 0: + if(m_nNextPos+1 >= m_pattern.GetSize()) + { + delta = 1; + nex2 = CHART_INFO(ch , 0, m_nNextPos, delta); + } + else + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); // common '\0' char + break; + + default: + nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); + break; + } + } + break; + + case RCHART('*'): + case RCHART('+'): + case RCHART('?'): + case RCHART('.'): + case RCHART('{'): + case RCHART('}'): + case RCHART(')'): + case RCHART('|'): + case RCHART('$'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + break; + + case RCHART('-'): + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + + case RCHART('('): + { + CHART ch1 = m_pattern[m_nNextPos+1]; + CHART ch2 = m_pattern[m_nNextPos+2]; + + // skip remark + if(ch1 == RCHART('?') && ch2 == RCHART('#')) + { + m_nNextPos += 2; + while(m_nNextPos < m_pattern.GetSize()) + { + if(m_pattern[m_nNextPos] == RCHART(')')) + break; + + m_nNextPos ++; + } + + if(m_pattern[m_nNextPos] == RCHART(')')) + { + m_nNextPos ++; + + // get next nex2 + return 0; + } + } + else + { + if(m_nCharsetDepth > 0) + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + } + } + break; + + case RCHART('#'): + if(m_nFlags & EXTENDED) + { + // skip remark + m_nNextPos ++; + + while(m_nNextPos < m_pattern.GetSize()) + { + if(m_pattern[m_nNextPos] == RCHART('\n') || m_pattern[m_nNextPos] == RCHART('\r')) + break; + + m_nNextPos ++; + } + + // get next nex2 + return 0; + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART(' '): + case RCHART('\f'): + case RCHART('\n'): + case RCHART('\r'): + case RCHART('\t'): + case RCHART('\v'): + if(m_nFlags & EXTENDED) + { + m_nNextPos ++; + + // get next nex2 + return 0; + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART('['): + if( m_nCharsetDepth == 0 || m_pattern.At(m_nNextPos + 1, 0) == RCHART(':') ) + { + m_nCharsetDepth ++; + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART(']'): + if(m_nCharsetDepth > 0) + { + m_nCharsetDepth --; + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + } + else + { + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + } + break; + + case RCHART(':'): + if(next == CHART_INFO(RCHART('['), 1)) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + + case RCHART('^'): + if(m_nCharsetDepth == 0 || next == CHART_INFO(RCHART('['), 1) || (curr == CHART_INFO(RCHART('['), 1) && next == CHART_INFO(RCHART(':'), 1))) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + + case 0: + if(m_nNextPos >= m_pattern.GetSize()) + nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); // end of string + else + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); // common '\0' char + break; + + default: + nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); + break; + } + + m_nNextPos += delta; + + return 1; +} + +template ElxInterface * CBuilderT :: GetStockElx(int nStockId) +{ + ElxInterface ** pStockElxs = m_pStockElxs; + + // check + if(nStockId < 0 || nStockId >= STOCKELX_COUNT) + return GetStockElx(0); + + // create if no + if(pStockElxs[nStockId] == 0) + { + switch(nStockId) + { + case STOCKELX_EMPTY: + pStockElxs[nStockId] = Keep(new CEmptyElx()); + break; + + case STOCKELX_WORD: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 1)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_WORD_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DOT_ALL: + pStockElxs[nStockId] = Keep(new CRangeElxT (0, 0)); + break; + + case STOCKELX_DOT_NOT_ALL: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 1)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 1)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_WORD_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 1)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_WORD_RIGHTLEFT_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z')); + pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z')); + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + pRange->m_chars .Push(RCHART('_')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DOT_ALL_RIGHTLEFT: + pStockElxs[nStockId] = Keep(new CRangeElxT (1, 0)); + break; + + case STOCKELX_DOT_NOT_ALL_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_chars .Push(RCHART('\n')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 1)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + pRange->m_chars .Push(RCHART('\f')); + pRange->m_chars .Push(RCHART('\v')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_SPACE_RIGHTLEFT_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_chars .Push(RCHART(' ')); + pRange->m_chars .Push(RCHART('\t')); + pRange->m_chars .Push(RCHART('\r')); + pRange->m_chars .Push(RCHART('\n')); + pRange->m_chars .Push(RCHART('\f')); + pRange->m_chars .Push(RCHART('\v')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL_RIGHTLEFT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 1)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + + case STOCKELX_DIGITAL_RIGHTLEFT_NOT: + { + CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); + + pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); + + pStockElxs[nStockId] = pRange; + } + break; + } + } + + // return + return pStockElxs[nStockId]; +} + +template ElxInterface * CBuilderT :: BuildAlternative(int vaflags) +{ + if(curr == CHART_INFO(0, 1)) + return GetStockElx(STOCKELX_EMPTY); + + // flag instance + int flags = vaflags; + + // first part + ElxInterface * pAlternativeOne = BuildList(flags); + + // check alternative + if(curr == CHART_INFO(RCHART('|'), 1)) + { + CAlternativeElx * pAlternative = (CAlternativeElx *)Keep(new CAlternativeElx()); + pAlternative->m_elxlist.Push(pAlternativeOne); + + // loop + while(curr == CHART_INFO(RCHART('|'), 1)) + { + // skip '|' itself + MoveNext(); + + pAlternativeOne = BuildList(flags); + pAlternative->m_elxlist.Push(pAlternativeOne); + } + + return pAlternative; + } + + return pAlternativeOne; +} + +template ElxInterface * CBuilderT :: BuildList(int & flags) +{ + if(curr == CHART_INFO(0, 1) || curr == CHART_INFO(RCHART('|'), 1) || curr == CHART_INFO(RCHART(')'), 1)) + return GetStockElx(STOCKELX_EMPTY); + + // first + ElxInterface * pListOne = BuildRepeat(flags); + + if(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1)) + { + CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT)); + pList->m_elxlist.Push(pListOne); + + while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1)) + { + pListOne = BuildRepeat(flags); + + // add + pList->m_elxlist.Push(pListOne); + } + + return pList; + } + + return pListOne; +} + +template ElxInterface * CBuilderT :: BuildRepeat(int & flags) +{ + // simple + ElxInterface * pSimple = BuildSimple(flags); + + if(curr.type == 0) return pSimple; + + // is quantifier or not + int bIsQuantifier = 1; + + // quantifier range + unsigned int nMin = 0, nMax = 0; + + switch(curr.ch) + { + case RCHART('{'): + { + CBufferT re; + + // skip '{' + MoveNext(); + + // copy + while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('}'), 1)) + { + re.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + + // skip '}' + MoveNext(); + + // read + int red; + char * str = re.GetBuffer(); + + if( ! ReadDec(str, nMin) ) + red = 0; + else if( *str != ',' ) + red = 1; + else + { + str ++; + + if( ! ReadDec(str, nMax) ) + red = 2; + else + red = 3; + } + + // check + if(red <= 1 ) nMax = nMin; + if(red == 2 ) nMax = INT_MAX; + if(nMax < nMin) nMax = nMin; + } + break; + + case RCHART('?'): + nMin = 0; + nMax = 1; + + // skip '?' + MoveNext(); + break; + + case RCHART('*'): + nMin = 0; + nMax = INT_MAX; + + // skip '*' + MoveNext(); + break; + + case RCHART('+'): + nMin = 1; + nMax = INT_MAX; + + // skip '+' + MoveNext(); + break; + + default: + bIsQuantifier = 0; + break; + } + + // do quantify + if(bIsQuantifier) + { + // 0 times + if(nMax == 0) + return GetStockElx(STOCKELX_EMPTY); + + // fixed times + if(nMin == nMax) + { + if(curr == CHART_INFO(RCHART('?'), 1) || curr == CHART_INFO(RCHART('+'), 1)) + MoveNext(); + + return Keep(new CRepeatElx(pSimple, nMin)); + } + + // range times + if(curr == CHART_INFO(RCHART('?'), 1)) + { + MoveNext(); + return Keep(new CReluctantElx(pSimple, nMin, nMax)); + } + else if(curr == CHART_INFO(RCHART('+'), 1)) + { + MoveNext(); + return Keep(new CPossessiveElx(pSimple, nMin, nMax)); + } + else + { + return Keep(new CGreedyElx(pSimple, nMin, nMax)); + } + } + + return pSimple; +} + +template ElxInterface * CBuilderT :: BuildSimple(int & flags) +{ + CBufferT fixed; + + while(curr != CHART_INFO(0, 1)) + { + if(curr.type == 0) + { + if(next == CHART_INFO(RCHART('{'), 1) || next == CHART_INFO(RCHART('?'), 1) || next == CHART_INFO(RCHART('*'), 1) || next == CHART_INFO(RCHART('+'), 1)) + { + if(fixed.GetSize() == 0) + { + fixed.Append(curr.ch, 1); + MoveNext(); + } + + break; + } + else + { + fixed.Append(curr.ch, 1); + MoveNext(); + } + } + else if(curr.type == 1) + { + CHART vch = curr.ch; + + // end of simple + if(vch == RCHART(')') || vch == RCHART('|')) + break; + + // has fixed already + if(fixed.GetSize() > 0) + break; + + // left parentheses + if(vch == RCHART('(')) + { + return BuildRecursive(flags); + } + + // char set + if( vch == RCHART('[') || vch == RCHART('.') || vch == RCHART('w') || vch == RCHART('W') || + vch == RCHART('s') || vch == RCHART('S') || vch == RCHART('d') || vch == RCHART('D') + ) + { + return BuildCharset(flags); + } + + // boundary + if( vch == RCHART('^') || vch == RCHART('$') || vch == RCHART('A') || vch == RCHART('Z') || vch == RCHART('z') || + vch == RCHART('b') || vch == RCHART('B') || vch == RCHART('G') // vch == RCHART('<') || vch == RCHART('>') + ) + { + return BuildBoundary(flags); + } + + // backref + if(vch == RCHART('\\') || vch == RCHART('k') || vch == RCHART('g')) + { + return BuildBackref(flags); + } + + // treat vchar as char + fixed.Append(curr.ch, 1); + MoveNext(); + } + } + + if(fixed.GetSize() > 0) + return Keep(new CStringElxT (fixed.GetBuffer(), fixed.GetSize(), flags & RIGHTTOLEFT, flags & IGNORECASE)); + else + return GetStockElx(STOCKELX_EMPTY); +} + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +template ElxInterface * CBuilderT :: BuildCharset(int & flags) +{ + // char + CHART ch = curr.ch; + + // skip + MoveNext(); + + switch(ch) + { + case RCHART('.'): + return GetStockElx( + flags & RIGHTTOLEFT ? + ((flags & SINGLELINE) ? STOCKELX_DOT_ALL_RIGHTLEFT : STOCKELX_DOT_NOT_ALL_RIGHTLEFT) : + ((flags & SINGLELINE) ? STOCKELX_DOT_ALL : STOCKELX_DOT_NOT_ALL) + ); + + case RCHART('w'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT : STOCKELX_WORD); + + case RCHART('W'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT_NOT : STOCKELX_WORD_NOT); + + case RCHART('s'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT : STOCKELX_SPACE); + + case RCHART('S'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT_NOT : STOCKELX_SPACE_NOT); + + case RCHART('d'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT : STOCKELX_DIGITAL); + + case RCHART('D'): + return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT_NOT : STOCKELX_DIGITAL_NOT); + + case RCHART('['): + { + CRangeElxT * pRange; + + // create + if(curr == CHART_INFO(RCHART(':'), 1)) + { + CBufferT posix; + + do { + posix.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + while(curr.ch != RCHART(0) && curr != CHART_INFO(RCHART(']'), 1)); + + MoveNext(); // skip ']' + + // posix + return Keep(new CPosixElxT (posix.GetBuffer(), flags & RIGHTTOLEFT)); + } + else if(curr == CHART_INFO(RCHART('^'), 1)) + { + MoveNext(); // skip '^' + pRange = (CRangeElxT *)Keep(new CRangeElxT (flags & RIGHTTOLEFT, 0)); + } + else + { + pRange = (CRangeElxT *)Keep(new CRangeElxT (flags & RIGHTTOLEFT, 1)); + } + + // parse + while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART(']'), 1)) + { + ch = curr.ch; + + if(curr.type == 1 && ( + ch == RCHART('.') || ch == RCHART('w') || ch == RCHART('W') || ch == RCHART('s') || ch == RCHART('S') || ch == RCHART('d') || ch == RCHART('D') || + (ch == RCHART('[') && next == CHART_INFO(RCHART(':'), 1)) + )) + { + pRange->m_embeds.Push(BuildCharset(flags)); + } + else if(next == CHART_INFO(RCHART('-'), 1) && nex2.type == 0) + { + pRange->m_ranges.Push(ch); pRange->m_ranges.Push(nex2.ch); + + // next + MoveNext(); + MoveNext(); + MoveNext(); + } + else + { + pRange->m_chars.Push(ch); + + // next + MoveNext(); + } + } + + // skip ']' + MoveNext(); + + if( flags & IGNORECASE ) + { + CBufferT & ranges = pRange->m_ranges; + int i, oldcount = ranges.GetSize() / 2; + + for(i=0; i= RCHART('A') ) + { + newmin = tolower( max(RCHART('A'), ranges[i*2 ]) ); + newmax = tolower( min(RCHART('Z'), ranges[i*2+1]) ); + + if( newmin < ranges[i*2] || newmax > ranges[i*2+1] ) + { + ranges.Push(newmin); + ranges.Push(newmax); + } + } + + if( ranges[i*2] <= RCHART('z') && ranges[i*2+1] >= RCHART('a') ) + { + newmin = toupper( max(RCHART('a'), ranges[i*2 ]) ); + newmax = toupper( min(RCHART('z'), ranges[i*2+1]) ); + + if( newmin < ranges[i*2] || newmax > ranges[i*2+1] ) + { + ranges.Push(newmin); + ranges.Push(newmax); + } + } + } + + CBufferT & chars = pRange->m_chars; + oldcount = chars.GetSize(); + for(i=0; iIsContainChar(tolower(chars[i])) ) + chars.Push(tolower(chars[i])); + + if( islower(chars[i]) && ! pRange->IsContainChar(toupper(chars[i])) ) + chars.Push(toupper(chars[i])); + } + } + + return pRange; + } + } + + return GetStockElx(STOCKELX_EMPTY); +} + +template ElxInterface * CBuilderT :: BuildRecursive(int & flags) +{ + // skip '(' + MoveNext(); + + if(curr == CHART_INFO(RCHART('?'), 1)) + { + ElxInterface * pElx = 0; + + // skip '?' + MoveNext(); + + int bNegative = 0; + CHART named_end = RCHART('>'); + + switch(curr.ch) + { + case RCHART('!'): + bNegative = 1; + + case RCHART('='): + { + MoveNext(); // skip '!' or '=' + pElx = Keep(new CAssertElx(BuildAlternative(flags & ~RIGHTTOLEFT), !bNegative)); + } + break; + + case RCHART('<'): + switch(next.ch) + { + case RCHART('!'): + bNegative = 1; + + case RCHART('='): + MoveNext(); // skip '<' + MoveNext(); // skip '!' or '=' + { + pElx = Keep(new CAssertElx(BuildAlternative(flags | RIGHTTOLEFT), !bNegative)); + } + break; + + default: // named group + break; + } + // break if assertion // else named + if(pElx != 0) break; + + case RCHART('P'): + if(curr.ch == RCHART('P')) MoveNext(); // skip 'P' + + case RCHART('\''): + if (curr.ch == RCHART('<' )) named_end = RCHART('>' ); + else if(curr.ch == RCHART('\'')) named_end = RCHART('\''); + MoveNext(); // skip '<' or '\'' + { + // named number + int nThisBackref = m_nNextNamed ++; + + CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT)); + CBracketElx * pleft = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 1 : 0)); + CBracketElx * pright = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 0 : 1)); + + // save name + CBufferT & name = pleft->m_szNamed; + CBufferT num; + + while(curr.ch != RCHART(0) && curr.ch != named_end) + { + name.Append(curr.ch, 1); + num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + MoveNext(); // skip '>' or '\'' + + // check + unsigned int number; + char * str = num.GetBuffer(); + + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pleft ->m_nnumber = number; + pright->m_nnumber = number; + + name.Release(); + } + + // left, center, right + pList->m_elxlist.Push(pleft); + pList->m_elxlist.Push(BuildAlternative(flags)); + pList->m_elxlist.Push(pright); + + // for recursive + m_namedlist.Prepare(nThisBackref); + m_namedlist[nThisBackref] = pList; + + pElx = pList; + } + break; + + case RCHART('>'): + { + MoveNext(); // skip '>' + pElx = Keep(new CIndependentElx(BuildAlternative(flags))); + } + break; + + case RCHART('R'): + MoveNext(); // skip 'R' + while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space + + if(curr.ch == RCHART('<') || curr.ch == RCHART('\'')) + { + named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\''); + CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(-3)); + + MoveNext(); // skip '<' or '\\' + + // save name + CBufferT & name = pDelegate->m_szNamed; + CBufferT num; + + while(curr.ch != RCHART(0) && curr.ch != named_end) + { + name.Append(curr.ch, 1); + num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + MoveNext(); // skip '>' or '\'' + + // check + unsigned int number; + char * str = num.GetBuffer(); + + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pDelegate->m_ndata = number; + name.Release(); + } + + m_recursivelist.Push(pDelegate); + pElx = pDelegate; + } + else + { + CBufferT rto; + while(curr.ch != RCHART(0) && curr.ch != RCHART(')')) + { + rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + + unsigned int rtono = 0; + char * str = rto.GetBuffer(); + ReadDec(str, rtono); + + CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono)); + + m_recursivelist.Push(pDelegate); + pElx = pDelegate; + } + break; + + case RCHART('('): + { + CConditionElx * pConditionElx = (CConditionElx *)Keep(new CConditionElx()); + + // condition + ElxInterface * & pCondition = pConditionElx->m_pelxask; + + if(next == CHART_INFO(RCHART('?'), 1)) + { + pCondition = BuildRecursive(flags); + } + else // named, assert or number + { + MoveNext(); // skip '(' + int pos0 = curr.pos; + + // save elx condition + pCondition = Keep(new CAssertElx(BuildAlternative(flags), 1)); + + // save name + pConditionElx->m_szNamed.Append(m_pattern.GetBuffer() + pos0, curr.pos - pos0, 1); + + // save number + CBufferT numstr; + while(pos0 < curr.pos) + { + CHART ch = m_pattern[pos0]; + numstr.Append(((ch & (CHART)0xff) == ch) ? (char)ch : 0, 1); + pos0 ++; + } + + unsigned int number; + char * str = numstr.GetBuffer(); + + // valid group number + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pConditionElx->m_nnumber = number; + pCondition = 0; + } + else // maybe elx, maybe named + { + pConditionElx->m_nnumber = -1; + m_namedconditionlist.Push(pConditionElx); + } + + MoveNext(); // skip ')' + } + + // alternative + { + int newflags = flags; + + pConditionElx->m_pelxyes = BuildList(newflags); + } + + if(curr.ch == RCHART('|')) + { + MoveNext(); // skip '|' + + pConditionElx->m_pelxno = BuildAlternative(flags); + } + else + { + pConditionElx->m_pelxno = 0; + } + + pElx = pConditionElx; + } + break; + + default: + while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space + + if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9')) // recursive (?1) => (?R1) + { + CBufferT rto; + while(curr.ch != RCHART(0) && curr.ch != RCHART(')')) + { + rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + + unsigned int rtono = 0; + char * str = rto.GetBuffer(); + ReadDec(str, rtono); + + CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono)); + + m_recursivelist.Push(pDelegate); + pElx = pDelegate; + } + else + { + // flag + int newflags = flags; + while(curr != CHART_INFO(0, 1) && curr.ch != RCHART(':') && curr.ch != RCHART(')') && curr != CHART_INFO(RCHART('('), 1)) + { + int tochange = 0; + + switch(curr.ch) + { + case RCHART('i'): + case RCHART('I'): + tochange = IGNORECASE; + break; + + case RCHART('s'): + case RCHART('S'): + tochange = SINGLELINE; + break; + + case RCHART('m'): + case RCHART('M'): + tochange = MULTILINE; + break; + + case RCHART('g'): + case RCHART('G'): + tochange = GLOBAL; + break; + + case RCHART('-'): + bNegative = 1; + break; + } + + if(bNegative) + newflags &= ~tochange; + else + newflags |= tochange; + + // move to next char + MoveNext(); + } + + if(curr.ch == RCHART(':') || curr == CHART_INFO(RCHART('('), 1)) + { + // skip ':' + if(curr.ch == RCHART(':')) MoveNext(); + + pElx = BuildAlternative(newflags); + } + else + { + // change parent flags + flags = newflags; + + pElx = GetStockElx(STOCKELX_EMPTY); + } + } + break; + } + + MoveNext(); // skip ')' + + return pElx; + } + else + { + // group and number + CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT)); + int nThisBackref = ++ m_nMaxNumber; + + // left, center, right + pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 1 : 0))); + pList->m_elxlist.Push(BuildAlternative(flags)); + pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 0 : 1))); + + // for recursive + m_grouplist.Prepare(nThisBackref); + m_grouplist[nThisBackref] = pList; + + // right + MoveNext(); // skip ')' + + return pList; + } +} + +template ElxInterface * CBuilderT :: BuildBoundary(int & flags) +{ + // char + CHART ch = curr.ch; + + // skip + MoveNext(); + + switch(ch) + { + case RCHART('^'): + return Keep(new CBoundaryElxT ((flags & MULTILINE) ? BOUNDARY_LINE_BEGIN : BOUNDARY_FILE_BEGIN)); + + case RCHART('$'): + return Keep(new CBoundaryElxT ((flags & MULTILINE) ? BOUNDARY_LINE_END : BOUNDARY_FILE_END)); + + case RCHART('b'): + return Keep(new CBoundaryElxT (BOUNDARY_WORD_EDGE)); + + case RCHART('B'): + return Keep(new CBoundaryElxT (BOUNDARY_WORD_EDGE, 0)); + + case RCHART('A'): + return Keep(new CBoundaryElxT (BOUNDARY_FILE_BEGIN)); + + case RCHART('Z'): + return Keep(new CBoundaryElxT (BOUNDARY_FILE_END_N)); + + case RCHART('z'): + return Keep(new CBoundaryElxT (BOUNDARY_FILE_END)); + + case RCHART('G'): + if(flags & GLOBAL) + return Keep(new CGlobalElx()); + else + return GetStockElx(STOCKELX_EMPTY); + + default: + return GetStockElx(STOCKELX_EMPTY); + } +} + +template ElxInterface * CBuilderT :: BuildBackref(int & flags) +{ + // skip '\\' or '\k' or '\g' + MoveNext(); + + if(curr.ch == RCHART('<') || curr.ch == RCHART('\'')) + { + CHART named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\''); + CBackrefElxT * pbackref = (CBackrefElxT *)Keep(new CBackrefElxT (-1, flags & RIGHTTOLEFT, flags & IGNORECASE)); + + MoveNext(); // skip '<' or '\'' + + // save name + CBufferT & name = pbackref->m_szNamed; + CBufferT num; + + while(curr.ch != RCHART(0) && curr.ch != named_end) + { + name.Append(curr.ch, 1); + num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1); + MoveNext(); + } + MoveNext(); // skip '>' or '\'' + + // check + unsigned int number; + char * str = num.GetBuffer(); + + if( ReadDec(str, number) ? ( *str == '\0') : 0 ) + { + pbackref->m_nnumber = number; + name.Release(); + } + else + { + m_namedbackreflist.Push(pbackref); + } + + return pbackref; + } + else + { + unsigned int nbackref = 0; + + for(int i=0; i<3; i++) + { + if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9')) + nbackref = nbackref * 10 + (curr.ch - RCHART('0')); + else + break; + + MoveNext(); + } + + return Keep(new CBackrefElxT (nbackref, flags & RIGHTTOLEFT, flags & IGNORECASE)); + } +} + +template int CBuilderT :: ReadDec(char * & str, unsigned int & dec) +{ + int s = 0; + while(str[s] != 0 && isspace(str[s])) s++; + + if(str[s] < '0' || str[s] > '9') return 0; + + dec = 0; + unsigned int i; + + for(i = s; i= '0' && str[i] <= '9') + dec = dec * 10 + (str[i] - '0'); + else + break; + } + + while(str[i] != 0 && isspace(str[i])) i++; + str += i; + + return 1; +} + +// +// Regexp +// +template class CRegexpT +{ +public: + CRegexpT(const CHART * pattern = 0, int flags = 0); + CRegexpT(const CHART * pattern, int length, int flags); + void Compile(const CHART * pattern, int flags = 0); + void Compile(const CHART * pattern, int length, int flags); + +public: + MatchResult MatchExact(const CHART * tstring, CContext * pContext = 0) const; + MatchResult MatchExact(const CHART * tstring, int length, CContext * pContext = 0) const; + MatchResult Match(const CHART * tstring, int start = -1, CContext * pContext = 0) const; + MatchResult Match(const CHART * tstring, int length, int start, CContext * pContext = 0) const; + MatchResult Match(CContext * pContext) const; + CContext * PrepareMatch(const CHART * tstring, int start = -1, CContext * pContext = 0) const; + CContext * PrepareMatch(const CHART * tstring, int length, int start, CContext * pContext = 0) const; + CHART * Replace(const CHART * tstring, const CHART * replaceto, int start = -1, int ntimes = -1, MatchResult * result = 0, CContext * pContext = 0) const; + CHART * Replace(const CHART * tstring, int string_length, const CHART * replaceto, int to_length, int & result_length, int start = -1, int ntimes = -1, MatchResult * result = 0, CContext * pContext = 0) const; + int GetNamedGroupNumber(const CHART * group_name) const; + +public: + static void ReleaseString (CHART * tstring ); + static void ReleaseContext(CContext * pContext); + +public: + CBuilderT m_builder; +}; + +// +// Implementation +// +template CRegexpT :: CRegexpT(const CHART * pattern, int flags) +{ + Compile(pattern, CBufferRefT(pattern).GetSize(), flags); +} + +template CRegexpT :: CRegexpT(const CHART * pattern, int length, int flags) +{ + Compile(pattern, length, flags); +} + +template inline void CRegexpT :: Compile(const CHART * pattern, int flags) +{ + Compile(pattern, CBufferRefT(pattern).GetSize(), flags); +} + +template void CRegexpT :: Compile(const CHART * pattern, int length, int flags) +{ + m_builder.Clear(); + if(pattern != 0) m_builder.Build(CBufferRefT(pattern, length), flags); +} + +template inline MatchResult CRegexpT :: MatchExact(const CHART * tstring, CContext * pContext) const +{ + return MatchExact(tstring, CBufferRefT(tstring).GetSize(), pContext); +} + +template MatchResult CRegexpT :: MatchExact(const CHART * tstring, int length, CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + // info + int endpos = 0; + + CContext context; + if(pContext == 0) pContext = &context; + + pContext->m_stack.Restore(0); + pContext->m_capturestack.Restore(0); + pContext->m_captureindex.Restore(0); + + pContext->m_nParenZindex = 0; + pContext->m_nLastBeginPos = -1; + pContext->m_pMatchString = (void*)tstring; + pContext->m_pMatchStringLength = length; + + if(m_builder.m_nFlags & RIGHTTOLEFT) + { + pContext->m_nBeginPos = length; + pContext->m_nCurrentPos = length; + endpos = 0; + } + else + { + pContext->m_nBeginPos = 0; + pContext->m_nCurrentPos = 0; + endpos = length; + } + + pContext->m_captureindex.Prepare(m_builder.m_nMaxNumber, -1); + pContext->m_captureindex[0] = 0; + pContext->m_capturestack.Push(0); + pContext->m_capturestack.Push(pContext->m_nCurrentPos); + pContext->m_capturestack.Push(-1); + pContext->m_capturestack.Push(-1); + + // match + if( ! m_builder.m_pTopElx->Match( pContext ) ) + return 0; + else + { + while( pContext->m_nCurrentPos != endpos ) + { + if( ! m_builder.m_pTopElx->MatchNext( pContext ) ) + return 0; + else + { + if( pContext->m_nLastBeginPos == pContext->m_nBeginPos && pContext->m_nBeginPos == pContext->m_nCurrentPos ) + return 0; + else + pContext->m_nLastBeginPos = pContext->m_nCurrentPos; + } + } + + // end pos + pContext->m_capturestack[2] = pContext->m_nCurrentPos; + + return MatchResult( pContext, m_builder.m_nMaxNumber ); + } +} + +template MatchResult CRegexpT :: Match(const CHART * tstring, int start, CContext * pContext) const +{ + return Match(tstring, CBufferRefT(tstring).GetSize(), start, pContext); +} + +template MatchResult CRegexpT :: Match(const CHART * tstring, int length, int start, CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + CContext context; + if(pContext == 0) pContext = &context; + + pContext->m_nParenZindex = 0; + pContext->m_nLastBeginPos = -1; + pContext->m_pMatchString = (void*)tstring; + pContext->m_pMatchStringLength = length; + + if(start < 0) + { + if(m_builder.m_nFlags & RIGHTTOLEFT) + { + pContext->m_nBeginPos = length; + pContext->m_nCurrentPos = length; + } + else + { + pContext->m_nBeginPos = 0; + pContext->m_nCurrentPos = 0; + } + } + else + { + pContext->m_nBeginPos = start; + pContext->m_nCurrentPos = start; + } + + return Match( pContext ); +} + +template MatchResult CRegexpT :: Match(CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + int endpos, delta; + + if(m_builder.m_nFlags & RIGHTTOLEFT) + { + endpos = -1; + delta = -1; + } + else + { + endpos = pContext->m_pMatchStringLength + 1; + delta = 1; + } + + while(pContext->m_nCurrentPos != endpos) + { + pContext->m_captureindex.Restore(0); + pContext->m_stack .Restore(0); + pContext->m_capturestack.Restore(0); + + pContext->m_captureindex.Prepare(m_builder.m_nMaxNumber, -1); + pContext->m_captureindex[0] = 0; + pContext->m_capturestack.Push(0); + pContext->m_capturestack.Push(pContext->m_nCurrentPos); + pContext->m_capturestack.Push(-1); + pContext->m_capturestack.Push(-1); + + if( m_builder.m_pTopElx->Match( pContext ) ) + { + // zero width + if( pContext->m_nLastBeginPos == pContext->m_nBeginPos && pContext->m_nBeginPos == pContext->m_nCurrentPos ) + { + pContext->m_nCurrentPos += delta; + continue; + } + + // save pos + pContext->m_nLastBeginPos = pContext->m_nBeginPos; + pContext->m_nBeginPos = pContext->m_nCurrentPos; + pContext->m_capturestack[2] = pContext->m_nCurrentPos; + + // return + return MatchResult( pContext, m_builder.m_nMaxNumber ); + } + else + { + pContext->m_nCurrentPos += delta; + } + } + + return 0; +} + +template inline CContext * CRegexpT :: PrepareMatch(const CHART * tstring, int start, CContext * pContext) const +{ + return PrepareMatch(tstring, CBufferRefT(tstring).GetSize(), start, pContext); +} + +template CContext * CRegexpT :: PrepareMatch(const CHART * tstring, int length, int start, CContext * pContext) const +{ + if(m_builder.m_pTopElx == 0) + return 0; + + if(pContext == 0) pContext = new CContext(); + + pContext->m_nParenZindex = 0; + pContext->m_nLastBeginPos = -1; + pContext->m_pMatchString = (void*)tstring; + pContext->m_pMatchStringLength = length; + + if(start < 0) + { + if(m_builder.m_nFlags & RIGHTTOLEFT) + { + pContext->m_nBeginPos = length; + pContext->m_nCurrentPos = length; + } + else + { + pContext->m_nBeginPos = 0; + pContext->m_nCurrentPos = 0; + } + } + else + { + pContext->m_nBeginPos = start; + pContext->m_nCurrentPos = start; + } + + return pContext; +} + +template inline int CRegexpT :: GetNamedGroupNumber(const CHART * group_name) const +{ + return m_builder.GetNamedNumber(group_name); +} + +template CHART * CRegexpT :: Replace(const CHART * tstring, const CHART * replaceto, int start, int ntimes, MatchResult * result, CContext * pContext) const +{ + int result_length = 0; + return Replace(tstring, CBufferRefT(tstring).GetSize(), replaceto, CBufferRefT(replaceto).GetSize(), result_length, start, ntimes, result, pContext); +} + +template CHART * CRegexpT :: Replace(const CHART * tstring, int string_length, const CHART * replaceto, int to_length, int & result_length, int start, int ntimes, MatchResult * remote_result, CContext * oContext) const +{ + if(m_builder.m_pTopElx == 0) return 0; + + // --- compile replace to --- + + CBufferT compiledto; + + static const CHART rtoptn[] = { RCHART('\\'), RCHART('$' ), RCHART('('), RCHART('?'), RCHART(':'), RCHART('[' ), RCHART('$' ), RCHART('&' ), RCHART('`' ), RCHART('\''), RCHART('+'), RCHART('_' ), RCHART('\\'), RCHART('d'), RCHART(']'), RCHART('|'), RCHART('\\'), RCHART('{'), RCHART('.'), RCHART('*'), RCHART('?'), RCHART('\\'), RCHART('}'), RCHART(')' ), RCHART('\0') }; + static CRegexpT rtoreg(rtoptn); + + MatchResult local_result(0), * result = remote_result ? remote_result : & local_result; + + // prepare + CContext * pContext = PrepareMatch(replaceto, to_length, -1, oContext); + int lastIndex = 0, nmatch = 0; + + while( ((*result) = rtoreg.Match(pContext)).IsMatched() ) + { + int delta = result->GetStart() - lastIndex; + if( delta > 0 ) + { + compiledto.Push(lastIndex); + compiledto.Push(delta); + } + + lastIndex = result->GetStart(); + delta = 2; + + switch(replaceto[lastIndex + 1]) + { + case RCHART('$'): + compiledto.Push(lastIndex); + compiledto.Push(1); + break; + + case RCHART('&'): + case RCHART('`'): + case RCHART('\''): + case RCHART('+'): + case RCHART('_'): + compiledto.Push(-1); + compiledto.Push((int)replaceto[lastIndex + 1]); + + case RCHART('{'): + delta = result->GetEnd() - result->GetStart(); + nmatch = m_builder.GetNamedNumber(CBufferRefT (replaceto + (lastIndex + 2), delta - 3)); + + if(nmatch > 0 && nmatch <= m_builder.m_nMaxNumber) + { + compiledto.Push(-2); + compiledto.Push(nmatch); + } + else + { + compiledto.Push(lastIndex); + compiledto.Push(delta); + } + break; + + default: + nmatch = 0; + for(delta=1; delta<=3; delta++) + { + CHART ch = replaceto[lastIndex + delta]; + + if(ch < RCHART('0') || ch > RCHART('9')) + break; + + nmatch = nmatch * 10 + (ch - RCHART('0')); + } + + if(nmatch > m_builder.m_nMaxNumber) + { + while(nmatch > m_builder.m_nMaxNumber) + { + nmatch /= 10; + delta --; + } + + if(nmatch == 0) + { + delta = 1; + } + } + + if(delta == 1) + { + compiledto.Push(lastIndex); + compiledto.Push(1); + } + else + { + compiledto.Push(-2); + compiledto.Push(nmatch); + } + break; + } + + lastIndex += delta; + } + + if(lastIndex < to_length) + { + compiledto.Push(lastIndex); + compiledto.Push(to_length - lastIndex); + } + + int rightleft = m_builder.m_nFlags & RIGHTTOLEFT; + + int tb = rightleft ? compiledto.GetSize() - 2 : 0; + int te = rightleft ? -2 : compiledto.GetSize(); + int ts = rightleft ? -2 : 2; + + // --- compile complete --- + + int beginpos = rightleft ? string_length : 0; + int endpos = rightleft ? 0 : string_length; + + int toIndex0 = 0; + int toIndex1 = 0; + int i, ntime; + + CBufferT buffer; + + // prepare + pContext = PrepareMatch(tstring, string_length, start, pContext); + lastIndex = beginpos; + + // Match + for(ntime = 0; ntimes < 0 || ntime < ntimes; ntime ++) + { + (*result) = Match(pContext); + + if( ! result->IsMatched() ) + break; + + // before + if( rightleft ) + { + int distance = lastIndex - result->GetEnd(); + if( distance ) + { + buffer.Push(tstring + result->GetEnd()); + buffer.Push((const CHART *)distance); + + toIndex1 -= distance; + } + lastIndex = result->GetStart(); + } + else + { + int distance = result->GetStart() - lastIndex; + if( distance ) + { + buffer.Push(tstring + lastIndex); + buffer.Push((const CHART *)distance); + + toIndex1 += distance; + } + lastIndex = result->GetEnd(); + } + + toIndex0 = toIndex1; + + // middle + for(i=tb; i!=te; i+=ts) + { + int off = compiledto[i]; + int len = compiledto[i + 1]; + + const CHART * sub = replaceto + off; + + if( off == -1 ) + { + switch(RCHART(len)) + { + case RCHART('&'): + sub = tstring + result->GetStart(); + len = result->GetEnd() - result->GetStart(); + break; + + case RCHART('`'): + sub = tstring; + len = result->GetStart(); + break; + + case RCHART('\''): + sub = tstring + result->GetEnd(); + len = string_length - result->GetEnd(); + break; + + case RCHART('+'): + for(nmatch = result->MaxGroupNumber(); nmatch >= 0; nmatch --) + { + if(result->GetGroupStart(nmatch) >= 0) break; + } + sub = tstring + result->GetGroupStart(nmatch); + len = result->GetGroupEnd(nmatch) - result->GetGroupStart(nmatch); + break; + + case RCHART('_'): + sub = tstring; + len = string_length; + break; + } + } + else if( off == -2 ) + { + sub = tstring + result->GetGroupStart(len); + len = result->GetGroupEnd(len) - result->GetGroupStart(len); + } + + buffer.Push(sub); + buffer.Push((const CHART *)len); + + toIndex1 += rightleft ? (-len) : len; + } + } + + // after + if(rightleft) + { + if(endpos < lastIndex) + { + buffer.Push(tstring + endpos); + buffer.Push((const CHART *)(lastIndex - endpos)); + } + } + else + { + if(lastIndex < endpos) + { + buffer.Push(tstring + lastIndex); + buffer.Push((const CHART *)(endpos - lastIndex)); + } + } + + if(oContext == 0) ReleaseContext(pContext); + + // join string + result_length = 0; + for(i=0; i result_string; + result_string.Prepare(result_length); + result_string.Restore(0); + + if(rightleft) + { + for(i=buffer.GetSize()-2; i>=0; i-=2) + { + result_string.Append(buffer[i], (int)buffer[i+1]); + } + } + else + { + for(i=0; im_result.Append(result_length, 3); + result->m_result.Append(ntime); + + if(rightleft) + { + result->m_result.Append(result_length - toIndex1); + result->m_result.Append(result_length - toIndex0); + } + else + { + result->m_result.Append(toIndex0); + result->m_result.Append(toIndex1); + } + + return result_string.Detach(); +} + +template inline void CRegexpT :: ReleaseString(CHART * tstring) +{ + if(tstring != 0) free(tstring); +} + +template inline void CRegexpT :: ReleaseContext(CContext * pContext) +{ + if(pContext != 0) delete pContext; +} + +// +// All implementations +// +template CAlternativeElxT :: CAlternativeElxT() +{ +} + +template int CAlternativeElxT :: Match(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 1; + + // try all + for(int n = 0; n < m_elxlist.GetSize(); n++) + { + if(m_elxlist[n]->Match(pContext)) + { + pContext->m_stack.Push(n); + return 1; + } + } + + return 0; +} + +template int CAlternativeElxT :: MatchNext(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 0; + + int n = 0; + + // recall prev + pContext->m_stack.Pop(n); + + // prev + if(m_elxlist[n]->MatchNext(pContext)) + { + pContext->m_stack.Push(n); + return 1; + } + else + { + // try rest + for(n++; n < m_elxlist.GetSize(); n++) + { + if(m_elxlist[n]->Match(pContext)) + { + pContext->m_stack.Push(n); + return 1; + } + } + + return 0; + } +} + +// assertx.cpp: implementation of the CAssertElx class. +// +template CAssertElxT :: CAssertElxT(ElxInterface * pelx, int byes) +{ + m_pelx = pelx; + m_byes = byes; +} + +template int CAssertElxT :: Match(CContext * pContext) const +{ + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + int bsucc; + + // match + if( m_byes ) + bsucc = m_pelx->Match(pContext); + else + bsucc = ! m_pelx->Match(pContext); + + // status + pContext->m_stack.Restore(nsize); + pContext->m_nCurrentPos = nbegin; + + if( bsucc ) + pContext->m_stack.Push(ncsize); + else + pContext->m_capturestack.Restore(ncsize); + + return bsucc; +} + +template int CAssertElxT :: MatchNext(CContext * pContext) const +{ + int ncsize = 0; + + pContext->m_stack.Pop(ncsize); + pContext->m_capturestack.Restore(ncsize); + + return 0; +} + +// emptyelx.cpp: implementation of the CEmptyElx class. +// +template CEmptyElxT :: CEmptyElxT() +{ +} + +template int CEmptyElxT :: Match(CContext *) const +{ + return 1; +} + +template int CEmptyElxT :: MatchNext(CContext *) const +{ + return 0; +} + +// globalx.cpp: implementation of the CGlobalElx class. +// +template CGlobalElxT ::CGlobalElxT() +{ +} + +template int CGlobalElxT :: Match(CContext * pContext) const +{ + return pContext->m_nCurrentPos == pContext->m_nBeginPos; +} + +template int CGlobalElxT :: MatchNext(CContext *) const +{ + return 0; +} + +// greedelx.cpp: implementation of the CGreedyElx class. +// +template CGreedyElxT :: CGreedyElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT (pelx, nmin) +{ + m_nvart = nmax - nmin; +} + +template int CGreedyElxT :: Match(CContext * pContext) const +{ + if( ! CRepeatElxT :: MatchFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CGreedyElxT :: MatchNext(CContext * pContext) const +{ + if( MatchNextVart(pContext) ) + return 1; + + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CGreedyElxT :: MatchVart(CContext * pContext) const +{ + int n = 0; + int nbegin = pContext->m_nCurrentPos; + + while(n < m_nvart && CRepeatElxT :: m_pelx->Match(pContext)) + { + while(pContext->m_nCurrentPos == nbegin) + { + if( ! CRepeatElxT :: m_pelx->MatchNext(pContext) ) break; + } + + if(pContext->m_nCurrentPos == nbegin) break; + + n ++; + nbegin = pContext->m_nCurrentPos; + } + + pContext->m_stack.Push(n); + + return 1; +} + +template int CGreedyElxT :: MatchNextVart(CContext * pContext) const +{ + int n = 0; + pContext->m_stack.Pop(n); + + if(n == 0) return 0; + + if( ! CRepeatElxT :: m_pelx->MatchNext(pContext) ) + { + n --; + } + + pContext->m_stack.Push(n); + + return 1; +} + +// indepelx.cpp: implementation of the CIndependentElx class. +// +template CIndependentElxT :: CIndependentElxT(ElxInterface * pelx) +{ + m_pelx = pelx; +} + +template int CIndependentElxT :: Match(CContext * pContext) const +{ + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + + // match + int bsucc = m_pelx->Match(pContext); + + // status + pContext->m_stack.Restore(nsize); + + if( bsucc ) + { + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(ncsize); + } + + return bsucc; +} + +template int CIndependentElxT :: MatchNext(CContext * pContext) const +{ + int nbegin = 0, ncsize = 0; + + pContext->m_stack.Pop(ncsize); + pContext->m_stack.Pop(nbegin); + + pContext->m_capturestack.Restore(ncsize); + pContext->m_nCurrentPos = nbegin; + + return 0; +} + +// listelx.cpp: implementation of the CListElx class. +// +template CListElxT :: CListElxT(int brightleft) +{ + m_brightleft = brightleft; +} + +template int CListElxT :: Match(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 1; + + // prepare + int bol = m_brightleft ? m_elxlist.GetSize() : -1; + int stp = m_brightleft ? -1 : 1; + int eol = m_brightleft ? -1 : m_elxlist.GetSize(); + + // from first + int n = bol + stp; + + // match all + while(n != eol) + { + if(m_elxlist[n]->Match(pContext)) + { + n += stp; + } + else + { + n -= stp; + + while(n != bol && ! m_elxlist[n]->MatchNext(pContext)) + n -= stp; + + if(n != bol) + n += stp; + else + return 0; + } + } + + return 1; +} + +template int CListElxT :: MatchNext(CContext * pContext) const +{ + if(m_elxlist.GetSize() == 0) + return 0; + + // prepare + int bol = m_brightleft ? m_elxlist.GetSize() : -1; + int stp = m_brightleft ? -1 : 1; + int eol = m_brightleft ? -1 : m_elxlist.GetSize(); + + // from last + int n = eol - stp; + + while(n != bol && ! m_elxlist[n]->MatchNext(pContext)) + n -= stp; + + if(n != bol) + n += stp; + else + return 0; + + // match rest + while(n != eol) + { + if(m_elxlist[n]->Match(pContext)) + { + n += stp; + } + else + { + n -= stp; + + while(n != bol && ! m_elxlist[n]->MatchNext(pContext)) + n -= stp; + + if(n != bol) + n += stp; + else + return 0; + } + } + + return 1; +} + +// mresult.cpp: implementation of the MatchResult class. +// +template MatchResultT :: MatchResultT(CContext * pContext, int nMaxNumber) +{ + if(pContext != 0) + { + m_result.Prepare(nMaxNumber * 2 + 3, -1); + + // matched + m_result[0] = 1; + m_result[1] = nMaxNumber; + + for(int n = 0; n <= nMaxNumber; n++) + { + int index = pContext->m_captureindex[n]; + if( index < 0 ) continue; + + // check enclosed + int pos1 = pContext->m_capturestack[index + 1]; + int pos2 = pContext->m_capturestack[index + 2]; + + // info + m_result[n*2 + 2] = pos1 < pos2 ? pos1 : pos2; + m_result[n*2 + 3] = pos1 < pos2 ? pos2 : pos1; + } + } +} + +template inline int MatchResultT :: IsMatched() const +{ + return m_result.At(0, 0); +} + +template inline int MatchResultT :: MaxGroupNumber() const +{ + return m_result.At(1, 0); +} + +template inline int MatchResultT :: GetStart() const +{ + return m_result.At(2, -1); +} + +template inline int MatchResultT :: GetEnd() const +{ + return m_result.At(3, -1); +} + +template inline int MatchResultT :: GetGroupStart(int nGroupNumber) const +{ + return m_result.At(2 + nGroupNumber * 2, -1); +} + +template inline int MatchResultT :: GetGroupEnd(int nGroupNumber) const +{ + return m_result.At(2 + nGroupNumber * 2 + 1, -1); +} + +template MatchResultT & MatchResultT :: operator = (const MatchResultT & result) +{ + m_result.Restore(0); + if(result.m_result.GetSize() > 0) m_result.Append(result.m_result.GetBuffer(), result.m_result.GetSize()); + + return *this; +} + +// posselx.cpp: implementation of the CPossessiveElx class. +// +template CPossessiveElxT :: CPossessiveElxT(ElxInterface * pelx, int nmin, int nmax) : CGreedyElxT (pelx, nmin, nmax) +{ +} + +template int CPossessiveElxT :: Match(CContext * pContext) const +{ + int nbegin = pContext->m_nCurrentPos; + int nsize = pContext->m_stack.GetSize(); + int ncsize = pContext->m_capturestack.GetSize(); + int bsucc = 1; + + // match + if( ! CRepeatElxT :: MatchFixed(pContext) ) + { + bsucc = 0; + } + else + { + while( ! CGreedyElxT :: MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + { + bsucc = 0; + break; + } + } + } + + // status + pContext->m_stack.Restore(nsize); + + if( bsucc ) + { + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(ncsize); + } + + return bsucc; +} + +template int CPossessiveElxT :: MatchNext(CContext * pContext) const +{ + int nbegin = 0, ncsize = 0; + + pContext->m_stack.Pop(ncsize); + pContext->m_stack.Pop(nbegin); + + pContext->m_capturestack.Restore(ncsize); + pContext->m_nCurrentPos = nbegin; + + return 0; +} + +// reluctx.cpp: implementation of the CReluctantElx class. +// +template CReluctantElxT :: CReluctantElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT (pelx, nmin) +{ + m_nvart = nmax - nmin; +} + +template int CReluctantElxT :: Match(CContext * pContext) const +{ + if( ! CRepeatElxT :: MatchFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CReluctantElxT :: MatchNext(CContext * pContext) const +{ + if( MatchNextVart(pContext) ) + return 1; + + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + + while( ! MatchVart(pContext) ) + { + if( ! CRepeatElxT :: MatchNextFixed(pContext) ) + return 0; + } + + return 1; +} + +template int CReluctantElxT :: MatchVart(CContext * pContext) const +{ + pContext->m_stack.Push(0); + + return 1; +} + +template int CReluctantElxT :: MatchNextVart(CContext * pContext) const +{ + int n = 0, nbegin = pContext->m_nCurrentPos; + + pContext->m_stack.Pop(n); + + if(n < m_nvart && CRepeatElxT :: m_pelx->Match(pContext)) + { + while(pContext->m_nCurrentPos == nbegin) + { + if( ! CRepeatElxT :: m_pelx->MatchNext(pContext) ) break; + } + + if(pContext->m_nCurrentPos != nbegin) + { + n ++; + + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(n); + + return 1; + } + } + + while(n > 0) + { + pContext->m_stack.Pop(nbegin); + + while( CRepeatElxT :: m_pelx->MatchNext(pContext) ) + { + if(pContext->m_nCurrentPos != nbegin) + { + pContext->m_stack.Push(nbegin); + pContext->m_stack.Push(n); + + return 1; + } + } + + n --; + } + + return 0; +} + +// repeatx.cpp: implementation of the CRepeatElx class. +// +template CRepeatElxT :: CRepeatElxT(ElxInterface * pelx, int ntimes) +{ + m_pelx = pelx; + m_nfixed = ntimes; +} + +template int CRepeatElxT :: Match(CContext * pContext) const +{ + return MatchFixed(pContext); +} + +template int CRepeatElxT :: MatchNext(CContext * pContext) const +{ + return MatchNextFixed(pContext); +} + +template int CRepeatElxT :: MatchFixed(CContext * pContext) const +{ + if(m_nfixed == 0) + return 1; + + int n = 0; + + while(n < m_nfixed) + { + if(m_pelx->Match(pContext)) + { + n ++; + } + else + { + n --; + + while(n >= 0 && ! m_pelx->MatchNext(pContext)) + n --; + + if(n >= 0) + n ++; + else + return 0; + } + } + + return 1; +} + +template int CRepeatElxT :: MatchNextFixed(CContext * pContext) const +{ + if(m_nfixed == 0) + return 0; + + // from last + int n = m_nfixed - 1; + + while(n >= 0 && ! m_pelx->MatchNext(pContext)) + n --; + + if(n >= 0) + n ++; + else + return 0; + + // match rest + while(n < m_nfixed) + { + if(m_pelx->Match(pContext)) + { + n ++; + } + else + { + n --; + + while(n >= 0 && ! m_pelx->MatchNext(pContext)) + n --; + + if(n >= 0) + n ++; + else + return 0; + } + } + + return 1; +} + +// Regexp +typedef CRegexpT CRegexpA; +typedef CRegexpT CRegexpW; + +#if defined(_UNICODE) || defined(UNICODE) + typedef CRegexpW CRegexp; +#else + typedef CRegexpA CRegexp; +#endif + +#endif//__DEELX_REGEXP__H__ diff --git a/src/OSspecific/MSWindows/fileStat.C b/src/OSspecific/MSWindows/fileStat.C new file mode 100644 index 000000000..23c7a346c --- /dev/null +++ b/src/OSspecific/MSWindows/fileStat.C @@ -0,0 +1,202 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "fileStat.H" +#include "IOstreams.H" +#include "timer.H" + +#include + + + +#undef major +#undef minor +#undef makedev + +# define major(dev) ((int)(((dev) >> 8) & 0xff)) +# define minor(dev) ((int)((dev) & 0xff)) +# define makedev(major, minor) ((((unsigned int) (major)) << 8) \ + | ((unsigned int) (minor))) + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct null +fileStat::fileStat() +: + isValid_(false) +{} + + +// Construct from components +fileStat::fileStat(const fileName& fName, const unsigned int maxTime) +{ + // Work on volatile + volatile bool locIsValid = false; + + timer myTimer(maxTime); + + if (!timedOut(myTimer)) + { + if (::stat(fName.c_str(), &status_) != 0) + { + locIsValid = false; + } + else + { + locIsValid = true; + } + } + + // Copy into (non-volatile, possible register based) member var + isValid_ = locIsValid; +} + + +// Construct from Istream. +fileStat::fileStat(Istream& is) +{ + is >> *this; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +// compare two fileStates for same device +bool fileStat::sameDevice(const fileStat& stat2) const +{ + return + isValid_ + && ( + major(status_.st_dev) == major(stat2.status().st_dev) + && minor(status_.st_dev) == minor(stat2.status().st_dev) + ); +} + +// compare two fileStates for same Inode +bool fileStat::sameINode(const fileStat& stat2) const +{ + return isValid_ && (status_.st_ino == stat2.status().st_ino); +} + +// compare state against inode +bool fileStat::sameINode(const label iNode) const +{ + return isValid_ && (status_.st_ino == ino_t(iNode)); +} + + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +// Input in list syntax +Istream& operator>>(Istream& is, fileStat& fStat) +{ + // Read beginning of machine info list + is.readBegin("fileStat"); + + label + devMaj, devMin, + ino, mode, uid, gid, + rdevMaj, rdevMin, + size, atime, mtime, ctime; + + is >> fStat.isValid_ + >> devMaj + >> devMin + >> ino + >> mode + >> uid + >> gid + >> rdevMaj + >> rdevMin + >> size + >> atime + >> mtime + >> ctime; + + dev_t st_dev = makedev(devMaj, devMin); + fStat.status_.st_dev = st_dev; + + fStat.status_.st_ino = ino; + fStat.status_.st_mode = mode; + fStat.status_.st_uid = uid; + fStat.status_.st_gid = gid; + + dev_t st_rdev = makedev(rdevMaj, rdevMin); + fStat.status_.st_rdev = st_rdev; + + fStat.status_.st_size = size; + fStat.status_.st_atime = atime; + fStat.status_.st_mtime = mtime; + fStat.status_.st_ctime = ctime; + + // Read end of machine info list + is.readEnd("fileStat"); + + // Check state of Istream + is.check("Istream& operator>>(Istream&, fileStat&)"); + + return is; +} + + +// Output in list syntax +Ostream& operator<<(Ostream& os, const fileStat& fStat) +{ + // Set precision so 32bit unsigned int can be printed + // int oldPrecision = os.precision(); + int oldPrecision = 0; + os.precision(10); + + os << token::BEGIN_LIST << fStat.isValid_ + << token::SPACE << label(major(fStat.status_.st_dev)) + << token::SPACE << label(minor(fStat.status_.st_dev)) + << token::SPACE << label(fStat.status_.st_ino) + << token::SPACE << label(fStat.status_.st_mode) + << token::SPACE << label(fStat.status_.st_uid) + << token::SPACE << label(fStat.status_.st_gid) + << token::SPACE << label(major(fStat.status_.st_rdev)) + << token::SPACE << label(minor(fStat.status_.st_rdev)) + << token::SPACE << label(fStat.status_.st_size) + << token::SPACE << label(fStat.status_.st_atime) + << token::SPACE << label(fStat.status_.st_mtime) + << token::SPACE << label(fStat.status_.st_ctime) + << token::END_LIST; + + os.precision(oldPrecision); + return os; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/fileStat.H b/src/OSspecific/MSWindows/fileStat.H new file mode 100644 index 000000000..18978cb6e --- /dev/null +++ b/src/OSspecific/MSWindows/fileStat.H @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Class + Foam::fileStat + +Description + Wrapper for stat() system call. + +Warning + on Linux (an maybe on others) a stat() of an nfs mounted (remote) + file does never timeout and cannot be interrupted! + So e.g. Foam::ping first and hope nfs is running. + +SourceFiles + fileStat.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fileStat_H +#define fileStat_H + +#include +#include + +#include "label.H" +#include "fileName.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class fileStat Declaration +\*---------------------------------------------------------------------------*/ + +class fileStat +{ + // Private data + + struct stat status_; + + bool isValid_; + + +public: + + // Constructors + + //- Empty constructor + fileStat(); + + //- Construct from components + fileStat(const fileName& fName, const unsigned int maxTime=0); + + //- Construct from Istream + fileStat(Istream&); + + + // Member Functions + + // Access + + //- Raw status + const struct stat& status() const + { + return status_; + } + + //- Did constructor fail + bool isValid() const + { + return isValid_; + } + + + // Check + + //- compare two fileStats for same device + bool sameDevice(const fileStat& stat2) const; + + //- compare two fileStats for same Inode + bool sameINode(const fileStat& stat2) const; + + //- compare state against inode + bool sameINode(const label iNode) const; + + + // IOstream Operators + + friend Istream& operator>>(Istream&, fileStat&); + friend Ostream& operator<<(Ostream&, const fileStat&); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/multiThreader/multiThreader.C b/src/OSspecific/MSWindows/multiThreader/multiThreader.C new file mode 100644 index 000000000..d02ac7a0c --- /dev/null +++ b/src/OSspecific/MSWindows/multiThreader/multiThreader.C @@ -0,0 +1,707 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Class + multiThreader + +Description + Implementation of the multiThreader class + +Author + Sandeep Menon + University of Massachusetts Amherst + +\*----------------------------------------------------------------------------*/ + +#include "multiThreader.H" + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +defineTypeNameAndDebug(IOmultiThreader, 0); + +bool multiThreader::debug = false; +bool Mutex::debug = false; +bool rwMutex::debug = false; + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +multiThreader::multiThreader(int numThreads) +: + maxQueueSize_(10), + poolInfo_(NULL) +{ + if (numThreads > 0) + { + numThreads_ = numThreads; + + if (debug) + { + Info << "Initializing threading environment with " + << numThreads_ << " threads." << endl; + } + } + else + { + // Default number of threads at one (single-threaded) + numThreads_ = 1; + + if (debug) + { + Info << "Defaulting threading environment to one thread." << endl; + } + } + + // Initialize the thread pool + initializeThreadPool(); +} + + +Mutex::Mutex() +{ + // Set attributes based on debug flag + pthread_mutexattr_t attribute; + pthread_mutexattr_init(&attribute); + + if (debug) + { + pthread_mutexattr_settype(&attribute, PTHREAD_MUTEX_ERRORCHECK); + } + else + { + pthread_mutexattr_settype(&attribute, PTHREAD_MUTEX_NORMAL); + } + + if (pthread_mutex_init(&lock_, &attribute)) + { + FatalErrorIn("multiThreader::Mutex::Mutex()") + << "Unable to initialize mutex" + << abort(FatalError); + } + + // Destroy the attribute + pthread_mutexattr_destroy(&attribute); +} + + +rwMutex::rwMutex() +{ + // Set attributes for the mutex + pthread_rwlockattr_t attribute; + pthread_rwlockattr_init(&attribute); + + if (pthread_rwlock_init(&lock_, &attribute)) + { + FatalErrorIn("multiThreader::rwMutex::rwMutex()") + << "Unable to initialize read-write mutex" + << abort(FatalError); + } + + // Destroy the attribute + pthread_rwlockattr_destroy(&attribute); +} + + +Conditional::Conditional() +{ + if (pthread_cond_init(&condition_, NULL)) + { + FatalErrorIn("multiThreader::Conditional::Conditional()") + << "Unable to initialize condition" + << abort(FatalError); + } +} + +// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * // + +multiThreader::~multiThreader() +{ + destroyThreadPool(); +} + + +Mutex::~Mutex() +{ + if (pthread_mutex_destroy(&lock_)) + { + FatalErrorIn("multiThreader::Mutex::~Mutex()") + << "Unable to destroy mutex" + << abort(FatalError); + } +} + + +rwMutex::~rwMutex() +{ + if (pthread_rwlock_destroy(&lock_)) + { + FatalErrorIn("multiThreader::rwMutex::~rwMutex()") + << "Unable to destroy read-write mutex" + << abort(FatalError); + } +} + + +Conditional::~Conditional() +{ + if (pthread_cond_destroy(&condition_)) + { + FatalErrorIn("multiThreader::Conditional::~Conditional()") + << "Unable to destroy condition" + << abort(FatalError); + } +} + + +// * * * * * * * * * * * * * * * Private Functions * * * * * * * * * * * * * // + +void multiThreader::initializeThreadPool() +{ + // Initialize threads only if multi-threaded + if (multiThreaded()) + { + // Allocate the threadPool structure + poolInfo_ = new threadPool; + + // Initialize fields + poolInfo_->threader = this; + poolInfo_->numThreads = numThreads_; + poolInfo_->queueSize = 0; + poolInfo_->threads = new pthread_t[numThreads_]; + poolInfo_->head = NULL; + poolInfo_->tail = NULL; + + // Initialize flags + poolInfo_->queueClosed = false; + poolInfo_->shutDown = false; + + // Initialize thread attributes + pthread_attr_init(&(poolInfo_->attr)); + pthread_attr_setdetachstate + ( + &(poolInfo_->attr), + PTHREAD_CREATE_JOINABLE + ); + + // Create worker threads and have them wait for jobs + for (int tIndex = 0; tIndex < numThreads_; tIndex++) + { + int status = pthread_create + ( + &(poolInfo_->threads[tIndex]), + &(poolInfo_->attr), + reinterpret_cast + ( + poolThread + ), + reinterpret_cast + ( + poolInfo_ + ) + ); + + if (status != 0) + { + FatalErrorIn("multiThreader::initializeThreadPool()") + << "pthread_create could not initialize thread: " + << tIndex + << abort(FatalError); + } + } + } +} + + +threadReturnType multiThreader::poolThread(void *arg) +{ + // Typecast the argument into the required structure + threadPool *poolInfo = reinterpret_cast(arg); + + // Work queue loop + while (true) + { + // Lock the work queue + poolInfo->queueLock.lock(); + + // Wait for work to arrive in the queue + while ((poolInfo->queueSize == 0) && (!poolInfo->shutDown)) + { +# ifdef FULLDEBUG + if (debug) + { + Info << "poolThread::Wait on queueNotEmpty." << endl; + } +# endif + poolInfo->threader->waitForCondition + ( + poolInfo->queueNotEmpty, + poolInfo->queueLock + ); + } + + // Check for shutdown + if (poolInfo->shutDown) + { + poolInfo->queueLock.unlock(); + pthread_exit(NULL); + } + + // Pick an item off the queue, and get to work + workQueueItem *myWorkItem = poolInfo->head; + poolInfo->queueSize--; + if (poolInfo->queueSize == 0) + { + poolInfo->head = poolInfo->tail = NULL; + } + else + { + poolInfo->head = myWorkItem->next; + } + + // Handle a waiting destructor + if (poolInfo->queueSize == 0) + { +# ifdef FULLDEBUG + if (debug) + { + Info << "poolThread::Signaling: Empty queue." << endl; + } +# endif + poolInfo->threader->signal(poolInfo->queueEmpty); + } + + // Unlock the work queue + poolInfo->queueLock.unlock(); + + // Perform the work + myWorkItem->function(myWorkItem->arg); + + // Free up the work item + delete myWorkItem; + } + + return threadReturnValue; +} + + +void multiThreader::addToWorkQueue +( + void (*tFunction)(void*), + void *arg +) const +{ + if (singleThreaded()) + { +# ifdef FULLDEBUG + if (debug) + { + Info << "addToWorkQueue:: Not in multiThreaded mode." << endl; + } +# endif + + return; + } + + // Lock the work queue + poolInfo_->queueLock.lock(); + + // If occupied, wait for the queue to free-up + while + ( + (poolInfo_->queueSize == maxQueueSize_) + && (!(poolInfo_->shutDown || poolInfo_->queueClosed)) + ) + { +# ifdef FULLDEBUG + if (debug) + { + Info << "addToWorkQueue:: Wait on queueNotFull." << endl; + } +# endif + waitForCondition(poolInfo_->queueNotFull, poolInfo_->queueLock); + } + + // Is the pool in the process of being destroyed? + // Unlock the mutex and return to caller. + if (poolInfo_->shutDown || poolInfo_->queueClosed) + { + poolInfo_->queueLock.unlock(); + return; + } + + // Allocate a new work structure + workQueueItem *newWorkItem = new workQueueItem; + newWorkItem->function = tFunction; + newWorkItem->arg = arg; + newWorkItem->next = NULL; + + // Add new work structure to the queue + if (poolInfo_->queueSize == 0) + { + poolInfo_->tail = poolInfo_->head = newWorkItem; + broadCast(poolInfo_->queueNotEmpty); + } + else + { + poolInfo_->tail->next = newWorkItem; + poolInfo_->tail = newWorkItem; + } + + poolInfo_->queueSize++; + + // Unlock the work queue + poolInfo_->queueLock.unlock(); +} + + +void multiThreader::destroyThreadPool() +{ + // Destroy threads only if multi-threaded + if (multiThreaded()) + { + // Lock the work queue + poolInfo_->queueLock.lock(); + + // Is a shutdown already in progress? + if (poolInfo_->queueClosed || poolInfo_->shutDown) + { + // Unlock the mutex and return + poolInfo_->queueLock.unlock(); + return; + } + + poolInfo_->queueClosed = true; + + // Wait for workers to drain the queue + while (poolInfo_->queueSize != 0) + { + waitForCondition(poolInfo_->queueEmpty, poolInfo_->queueLock); + } + + poolInfo_->shutDown = true; + + // Unlock the work queue + poolInfo_->queueLock.unlock(); + + // Wake up workers so that they check the shutdown flag + broadCast(poolInfo_->queueNotEmpty); + broadCast(poolInfo_->queueNotFull); + + // Wait for all workers to exit + for(int i=0; i < numThreads_; i++) + { + if (pthread_join(poolInfo_->threads[i],NULL)) + { + FatalErrorIn("multiThreader::destroyThreadPool()") + << "pthread_join failed." + << abort(FatalError); + } + } + + // Destroy the attribute + pthread_attr_destroy(&(poolInfo_->attr)); + + // Deallocate the work-queue and pool structure + delete [] poolInfo_->threads; + + workQueueItem *currentNode; + while(poolInfo_->head != NULL) + { + currentNode = poolInfo_->head->next; + poolInfo_->head = poolInfo_->head->next; + delete currentNode; + } + + delete poolInfo_; + } +} + + +void multiThreader::waitForCondition +( + Conditional& condition, + Mutex& mutex +) const +{ + if (pthread_cond_wait(condition(),mutex())) + { + FatalErrorIn("multiThreader::waitForCondition()") + << "Conditional wait failed." + << abort(FatalError); + } +} + + +void multiThreader::broadCast(Conditional& condition) const +{ + if (pthread_cond_broadcast(condition())) + { + FatalErrorIn("multiThreader::broadCast()") + << "Unable to broadcast." + << abort(FatalError); + } +} + + +void multiThreader::signal(Conditional& condition) const +{ + if (pthread_cond_signal(condition())) + { + FatalErrorIn("multiThreader::signal()") + << "Unable to signal." + << abort(FatalError); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +//- Return the number of threads +int multiThreader::getNumThreads() const +{ + return numThreads_; +} + + +//- Obtain the thread ID for a given index +pthread_t multiThreader::getID(int index) const +{ + if (multiThreaded()) + { + if (poolInfo_ && index > -1 && index < numThreads_) + { + return poolInfo_->threads[index]; + } + else + { + FatalErrorIn("multiThreader::getID(int index)") + << "Invalid request for ID." + << abort(FatalError); + } + } + + return pthread_self(); +} + + +//- Return true if the number of threads is equal to one. +bool multiThreader::singleThreaded() const +{ + return (numThreads_ == 1); +} + + +//- Return true if the number of threads is more than one. +bool multiThreader::multiThreaded() const +{ + return (numThreads_ > 1); +} + + +//- Return the maxQueueSize +int multiThreader::getMaxQueueSize() const +{ + return maxQueueSize_; +} + + +//- Set the maxQueueSize +void multiThreader::setMaxQueueSize(int size) const +{ + if (size > 0) + { + maxQueueSize_ = size; + } + else + { + FatalErrorIn("multiThreader::setMaxQueueSize(int size)") + << "Improper value for MaxQueueSize." + << abort(FatalError); + } +} + + +void Mutex::lock() const +{ + if (pthread_mutex_lock(&lock_)) + { + FatalErrorIn("multiThreader::Mutex::lock()") + << "Unable to lock mutex." + << abort(FatalError); + } +} + + +bool Mutex::tryLock() const +{ + label retVal; + + if ((retVal = pthread_mutex_trylock(&lock_)) != 0) + { +# ifdef FULLDEBUG + if (debug) + { + if (retVal == EINVAL) + { + FatalErrorIn("multiThreader::Mutex::trylock()") + << "Mutex returned EINVAL." + << abort(FatalError); + } + if (retVal == EFAULT) + { + FatalErrorIn("multiThreader::Mutex::trylock()") + << "Mutex returned EFAULT." + << abort(FatalError); + } + } +# endif + } + + return retVal; +} + + +void Mutex::unlock() const +{ + if (pthread_mutex_unlock(&lock_)) + { + FatalErrorIn("multiThreader::Mutex::unlock()") + << "Unable to unlock the mutex." + << abort(FatalError); + } +} + + +void rwMutex::lock(const lockType lType) const +{ + if (lType == READ_LOCK) + { + if (pthread_rwlock_rdlock(&lock_)) + { + FatalErrorIn("multiThreader::rwMutex::lock()") + << "Unable to read lock the mutex." + << abort(FatalError); + } + } + else + if (lType == WRITE_LOCK) + { + if (pthread_rwlock_wrlock(&lock_)) + { + FatalErrorIn("multiThreader::rwMutex::lock()") + << "Unable to write lock the mutex." + << abort(FatalError); + } + } + else + { + FatalErrorIn("multiThreader::rwMutex::lock()") + << "Undefined mutex type." + << abort(FatalError); + } +} + + +bool rwMutex::tryLock(const lockType lType) const +{ + label retVal = -1; + + if (lType == READ_LOCK) + { + if ((retVal = pthread_rwlock_tryrdlock(&lock_)) != 0) + { + if (retVal == EINVAL) + { + FatalErrorIn("multiThreader::rwMutex::tryLock()") + << "Read mutex returned EINVAL." + << abort(FatalError); + } + + if (retVal == EFAULT) + { + FatalErrorIn("multiThreader::rwMutex::tryLock()") + << "Read mutex returned EFAULT." + << abort(FatalError); + } + } + } + else + if (lType == WRITE_LOCK) + { + if ((retVal = pthread_rwlock_trywrlock(&lock_)) != 0) + { + if (retVal == EINVAL) + { + FatalErrorIn("multiThreader::rwMutex::tryLock()") + << "Write mutex returned EINVAL." + << abort(FatalError); + } + + if (retVal == EFAULT) + { + FatalErrorIn("multiThreader::rwMutex::tryLock()") + << "Write mutex returned EFAULT." + << abort(FatalError); + } + } + } + else + { + FatalErrorIn("multiThreader::rwMutex::tryLock()") + << "Undefined mutex type." + << abort(FatalError); + } + + return retVal; +} + + +void rwMutex::unlock() const +{ + if (pthread_rwlock_unlock(&lock_)) + { + FatalErrorIn("multiThreader::rwMutex::unlock()") + << "Unable to unlock the read-write mutex." + << abort(FatalError); + } +} + + +// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // + +void multiThreader::operator=(const multiThreader& rhs) +{ + // Check for assignment to self + if (this == &rhs) + { + FatalErrorIn("multiThreader::operator=(const multiThreader&)") + << "Attempted assignment to self" + << abort(FatalError); + } +} + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/multiThreader/multiThreader.H b/src/OSspecific/MSWindows/multiThreader/multiThreader.H new file mode 100644 index 000000000..d680e9f79 --- /dev/null +++ b/src/OSspecific/MSWindows/multiThreader/multiThreader.H @@ -0,0 +1,324 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Class + multiThreader + +Description + Class which provides support for generic multi-threaded execution of class + methods using POSIX threads. + + The IOmultiThreader is an inherited class which allows integration with + the object registry, thereby allowing a single multi-threader object to + be accessed by multiple classes in a global sense. + + Thread-pooling is implemented as described in: + "Using POSIX Threads: Programming with Pthreads" + by Brad Nichols, Dick Buttlar, Jackie Farrell + O'Reilly & Associates, Inc. + +Author + Sandeep Menon + University of Massachusetts Amherst + +SourceFiles + multiThreader.C + +\*---------------------------------------------------------------------------*/ + +#ifndef multiThreader_H +#define multiThreader_H + +#include "error.H" +#include "regIOobject.H" + +#include +#include +#include +#include + +extern "C" +{ + typedef void *(*externThreadFunctionType)(void *); +} + +typedef void *(*threadFunctionType)(void *); + +#define threadReturnType void * +#define threadReturnValue NULL + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class Mutex +{ + // Private data + + mutable pthread_mutex_t lock_; + +public: + + // Debug switch + static bool debug; + + // Constructor + Mutex(); + + // Destructor + ~Mutex(); + + // Lock the mutex + void lock() const; + + // Try to acquire the mutex. + // Returns zero if successful + bool tryLock() const; + + // Unlock the mutex + void unlock() const; + + // Operator overload + inline pthread_mutex_t* operator()() + { + return &lock_; + } +}; + +class rwMutex +{ + // Private data + + mutable pthread_rwlock_t lock_; + +public: + + // Enumerants for lock-types + enum lockType + { + READ_LOCK, + WRITE_LOCK + }; + + // Debug switch + static bool debug; + + // Constructor + rwMutex(); + + // Destructor + ~rwMutex(); + + // Lock the mutex + void lock(const lockType lType) const; + + // Try to acquire a lock + bool tryLock(const lockType lType) const; + + // Unlock the mutex + void unlock() const; + + // Operator overload + inline pthread_rwlock_t* operator()() + { + return &lock_; + } +}; + +class Conditional +{ + // Private data + + mutable pthread_cond_t condition_; + +public: + + // Constructor + Conditional(); + + // Destructor + ~Conditional(); + + // Operator overload + inline pthread_cond_t* operator()() + { + return &condition_; + } +}; + +/*---------------------------------------------------------------------------*\ + Class multiThreader Declaration +\*---------------------------------------------------------------------------*/ + +class multiThreader +{ + // Private data + + mutable int numThreads_; + + mutable int maxQueueSize_; + + // Work-queue item: Holds a pointer to the method and its argument + struct workQueueItem + { + void (*function)(void*); + void *arg; + workQueueItem *next; + }; + + // Common structure for all threads in the pool. + mutable struct threadPool + { + multiThreader *threader; + int numThreads; + int queueSize; + pthread_t *threads; + pthread_attr_t attr; + workQueueItem *head, *tail; + + // Flags + bool queueClosed; + bool shutDown; + + // Synchronization + Mutex queueLock; + Conditional queueNotEmpty; + Conditional queueNotFull; + Conditional queueEmpty; + } *poolInfo_; + + // Private Member Functions + + void initializeThreadPool(); + + static threadReturnType poolThread(void *arg); + + void destroyThreadPool(); + + //- Disallow default bitwise copy construct + multiThreader(const multiThreader&); + + //- Disallow default bitwise assignment + void operator=(const multiThreader&); + +public: + + // Debug switch + + static bool debug; + + // Constructor + + //- Construct with specified number of threads + multiThreader(int numThreads); + + + // Destructor + + ~multiThreader(); + + + // Member Functions + + //- Return the number of threads + int getNumThreads() const; + + //- Obtain the thread ID for a given index + pthread_t getID(int index) const; + + //- Return true if the number of threads is equal to one. + bool singleThreaded() const; + + //- Return true if the number of threads is more than one. + bool multiThreaded() const; + + //- Return the maxQueueSize + int getMaxQueueSize() const; + + //- Set the maxQueueSize + void setMaxQueueSize(int size) const; + + //- Add a function to the work queue + void addToWorkQueue(void (*tFunction)(void*), void *arg) const; + + //- Conditional handling + void waitForCondition(Conditional&, Mutex&) const; + void broadCast(Conditional&) const; + void signal(Conditional&) const; +}; + +/*---------------------------------------------------------------------------*\ + Class IOmultiThreader Declaration +\*---------------------------------------------------------------------------*/ + +class IOmultiThreader +: + public regIOobject, + public multiThreader +{ + + // Member functions + + //- Disallow default bitwise copy construct + IOmultiThreader(const IOmultiThreader&); + + //- Disallow default bitwise assignment + void operator=(const IOmultiThreader&); + +public: + + //- Runtime type information + TypeName("multiThreader"); + + + // Constructors + + //- Construct from IOobject and specified number of threads + IOmultiThreader(const IOobject& io, int numThreads) + : + regIOobject(io), + multiThreader(numThreads) + {} + + // Destructor + + virtual ~IOmultiThreader() {} + + // Member functions + + bool writeData(Ostream&) const + { + return true; + } +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSWindows/multiThreader/threadHandler.H b/src/OSspecific/MSWindows/multiThreader/threadHandler.H new file mode 100644 index 000000000..ed39d1f9e --- /dev/null +++ b/src/OSspecific/MSWindows/multiThreader/threadHandler.H @@ -0,0 +1,214 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | foam-extend: Open Source CFD + \\ / O peration | Version: 3.2 + \\ / A nd | Web: http://www.foam-extend.org + \\/ M anipulation | For copyright notice see file Copyright +------------------------------------------------------------------------------- +License + This file is part of foam-extend. + + foam-extend 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. + + foam-extend 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 foam-extend. If not, see . + +Class + threadHandler + +Description + Helper class used to assist in multi-threading and synchronization. + + Use this class to pass information to a threaded static member-function + belonging to the class T. + +Author + Sandeep Menon + University of Massachusetts Amherst + All rights reserved + +SourceFiles + threadHandlerI.H + +\*---------------------------------------------------------------------------*/ + +#ifndef threadHandler_H +#define threadHandler_H + +#include "FixedList.H" +#include "List.H" +#include "multiThreader.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class threadHandler Declaration +\*---------------------------------------------------------------------------*/ + +template +class threadHandler +{ + // Reference to the template class + T& tRef_; + + // Reference to the multiThreader class + const multiThreader& threader_; + + // List of function argument pointers + List argList_; + + // Total number of threads + const label nThreads_; + + // ID generated by the pthreads API + pthread_t pthreadID_; + + // Is this a master/slave thread + mutable bool master_; + + // Synchronization mutexes + mutable Mutex startMutex_; + mutable Mutex stopMutex_; + + // Conditionals for synchronization + mutable Conditional startConditional_; + mutable Conditional stopConditional_; + + // On some implementations, a conditional wait + // might return prematurely due to a spurious + // wake-up signal. Use a predicate to avoid this + // behaviour. + mutable FixedList predicate_; + +public: + + // Enumerants for signalling + enum signalType + { + START, + STOP + }; + + // Constructor + threadHandler + ( + T& tPtr, + const multiThreader& threader + ); + + // Destructor + ~threadHandler(); + + // Return a reference to the template class + inline T& reference(); + + // Set a size for the argument list + inline void setSize(const label size); + + // Set a argument pointer for a particular index + inline void set(const label index, void* argPtr); + + // Return a reference to the multiThreader + inline const multiThreader& threader() const; + + // Return the number of threads + inline label nThreads() const; + + // Designate as master thread + inline void setMaster() const; + + // Designate as slave thread + inline void setSlave() const; + + // Is this a master thread? + inline bool master() const; + + // Is this a slave thread? + inline bool slave() const; + + // Lock this thread + inline void lock(const signalType sType) const; + + // Unlock this thread + inline void unlock(const signalType sType) const; + + // Send signal to a waiting conditional + inline void sendSignal(const signalType sType) const; + + // Wait for signal + inline void waitForSignal(const signalType sType) const; + + // Return state of the predicate variable + inline bool predicate(const signalType sType) const; + + // Set the predicate variable + inline void setPredicate(const signalType sType) const; + + // Unset the predicate variable + inline void unsetPredicate(const signalType sType) const; + + // Set the ID + inline void setID(const pthread_t& pt); + + // Return the ID + inline pthread_t ID() const; + + // Does the calling thread correspond to this handler? + inline bool self() const; + + // Return an argument pointer at a particular index + inline void * operator()(const label index); +}; + + +// Lock all threads provided by sequence +template +void lockThreads +( + const List