Skip to content
Snippets Groups Projects
Select Git revision
  • 09149e34657f77ca5bd40c292b0e3adc4eeff988
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

Callbacks.cpp

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    • Christophe Geuzaine's avatar
      09149e34
      · 09149e34
      Christophe Geuzaine authored
      This patch fixes an old design flaw in the post-processing module,
      namely that we used a list of Post_View objects instead of a list of
      pointers to Post_View objects in CTX.post.list.
      
      This had many annoying consequences, in particular the fact that we
      needed to be extra careful every time the list was reallocated (as
      pointers to the list elements would become invalid).
      
      I tried very hard to change the code everywhere it should be changed,
      but I might have missed something. Please let me know if you see
      anything suspicious (like a crash when you duplicate/remove/combine/...
      post-processing views).
      09149e34
      History
      Christophe Geuzaine authored
      This patch fixes an old design flaw in the post-processing module,
      namely that we used a list of Post_View objects instead of a list of
      pointers to Post_View objects in CTX.post.list.
      
      This had many annoying consequences, in particular the fact that we
      needed to be extra careful every time the list was reallocated (as
      pointers to the list elements would become invalid).
      
      I tried very hard to change the code everywhere it should be changed,
      but I might have missed something. Please let me know if you see
      anything suspicious (like a crash when you duplicate/remove/combine/...
      post-processing views).
    OS.cpp 12.27 KiB
    // Gmsh - Copyright (C) 1997-2013 C. Geuzaine, J.-F. Remacle
    //
    // See the LICENSE.txt file for license information. Please report all
    // bugs and problems to the public mailing list <gmsh@geuz.org>.
    
    // This file contains a bunch of functions that depend on OS-dependent
    // features and/or system calls
    
    // these are available on all OSes
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <signal.h>
    #include <time.h>
    #include <math.h>
    #include "GmshConfig.h"
    #include "StringUtils.h"
    
    #if !defined(WIN32) || defined(__CYGWIN__)
    #include <unistd.h>
    #include <sys/time.h>
    #include <sys/resource.h>
    #endif
    
    #if defined(WIN32)
    #include <windows.h>
    #include <process.h>
    #include <psapi.h>
    #include <io.h>
    #include <direct.h>
    #include <fcntl.h>
    #include <iostream>
    #include <fstream>
    #endif
    
    #if defined(__APPLE__)
    #define RUSAGE_SELF      0
    #define RUSAGE_CHILDREN -1
    #endif
    
    #include "GmshMessage.h"
    
    #if defined(WIN32) && !defined(__CYGWIN__)
    
    // UTF8 utility routines borrowed from FLTK
    
    static unsigned utf8decode(const char* p, const char* end, int* len)
    {
      static unsigned short cp1252[32] = {
        0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
        0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
        0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
        0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178
      };
      unsigned char c = *(unsigned char*)p;
      if (c < 0x80) {
        if (len) *len = 1;
        return c;
      } else if (c < 0xa0) {
        if (len) *len = 1;
        return cp1252[c-0x80];
      } else if (c < 0xc2) {
        goto FAIL;
      }
      if ( (end && p+1 >= end) || (p[1]&0xc0) != 0x80) goto FAIL;
      if (c < 0xe0) {
        if (len) *len = 2;
        return
          ((p[0] & 0x1f) << 6) +
          ((p[1] & 0x3f));
      } else if (c == 0xe0) {
        if (((unsigned char*)p)[1] < 0xa0) goto FAIL;
        goto UTF8_3;
      } else if (c < 0xf0) {
      UTF8_3:
        if ( (end && p+2 >= end) || (p[2]&0xc0) != 0x80) goto FAIL;
        if (len) *len = 3;
        return
          ((p[0] & 0x0f) << 12) +
          ((p[1] & 0x3f) << 6) +
          ((p[2] & 0x3f));
      } else if (c == 0xf0) {
        if (((unsigned char*)p)[1] < 0x90) goto FAIL;
        goto UTF8_4;
      } else if (c < 0xf4) {
      UTF8_4:
        if ( (end && p+3 >= end) || (p[2]&0xc0) != 0x80 || (p[3]&0xc0) != 0x80) goto FAIL;
        if (len) *len = 4;
        return
          ((p[0] & 0x07) << 18) +
          ((p[1] & 0x3f) << 12) +
          ((p[2] & 0x3f) << 6) +
          ((p[3] & 0x3f));
      } else if (c == 0xf4) {
        if (((unsigned char*)p)[1] > 0x8f) goto FAIL; /* after 0x10ffff */
        goto UTF8_4;
      } else {
      FAIL:
        if (len) *len = 1;
        return c;
      }
    }
    
    static unsigned utf8toUtf16(const char* src, unsigned srclen,
                                unsigned short* dst, unsigned dstlen)
    {
      const char* p = src;
      const char* e = src+srclen;
      unsigned count = 0;
      if (dstlen) for (;;) {
        if (p >= e) {dst[count] = 0; return count;}
        if (!(*p & 0x80)) { /* ascii */
          dst[count] = *p++;
        } else {
          int len; unsigned ucs = utf8decode(p,e,&len);
          p += len;
          if (ucs < 0x10000) {
    	dst[count] = ucs;
          } else {
    	/* make a surrogate pair: */
    	if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
    	dst[count] = (((ucs-0x10000u)>>10)&0x3ff) | 0xd800;
    	dst[++count] = (ucs&0x3ff) | 0xdc00;
          }
        }
        if (++count == dstlen) {dst[count-1] = 0; break;}
      }
      /* we filled dst, measure the rest: */
      while (p < e) {
        if (!(*p & 0x80)) p++;
        else {
          int len; unsigned ucs = utf8decode(p,e,&len);
          p += len;
          if (ucs >= 0x10000) ++count;
        }
        ++count;
      }
      return count;
    }
    
    static wchar_t *wbuf[2] = {NULL, NULL};
    
    static void setwbuf(int i, const char *f)
    {
      if(i != 0 || i != 1) return;
      size_t l = strlen(f);
      unsigned wn = utf8toUtf16(f, (unsigned) l, NULL, 0) + 1;
      wbuf[i] = (wchar_t*)realloc(wbuf[i], sizeof(wchar_t)*wn);
      wn = utf8toUtf16(f, (unsigned) l, (unsigned short *)wbuf[i], wn);
      wbuf[i][wn] = 0;
    }
    
    #endif
    
    FILE *Fopen(const char* f, const char *mode)
    {
    #if defined (WIN32) && !defined(__CYGWIN__)
      setwbuf(0, f);
      setwbuf(1, mode);
      return _wfopen(wbuf[0], wbuf[1]);
    #else
      return fopen(f, mode);
    #endif
    }
    
    const char *GetEnvironmentVar(const char *var)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      const char *tmp = getenv(var);
      // Don't accept top dir or anything partially expanded like
      // c:\Documents and Settings\%USERPROFILE%, etc.
      if(!tmp || !strcmp(tmp, "/") || strstr(tmp, "%") || strstr(tmp, "$"))
        return 0;
      else
        return tmp;
    #else
      return getenv(var);
    #endif
    }
    
    const void SetEnvironmentVar(const char *var, const char *val)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      _putenv((std::string(var) + "=" + std::string(val)).c_str());
    #else
      setenv(var, val, 1);
    #endif
    }
    
    double GetTimeInSeconds()
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      FILETIME ft;
      GetSystemTimeAsFileTime(&ft);
      double t =  1.e-7 * 4294967296. * (double)ft.dwHighDateTime +
                  1.e-7 * (double)ft.dwLowDateTime;
      return t;
    #else
      struct timeval tp;
      gettimeofday(&tp, (struct timezone *)0);
      double t = (double)tp.tv_sec + 1.e-6 * (double)tp.tv_usec;
      return t;
    #endif
    }
    
    void SleepInSeconds(double s)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      Sleep((long)(1.e3 * s));
    #else
      usleep((long)(1.e6 * s));
    #endif
    }
    
    static void GetResources(double *s, long *mem)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      FILETIME creation, exit, kernel, user;
      if(GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user)){
        *s = 1.e-7 * 4294967296. * (double)user.dwHighDateTime +
             1.e-7 * (double)user.dwLowDateTime;
      }
      PROCESS_MEMORY_COUNTERS info;
      GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
      *mem = (long)info.PeakWorkingSetSize;
    #else
      static struct rusage r;
      getrusage(RUSAGE_SELF, &r);
      *s = (double)r.ru_utime.tv_sec + 1.e-6 * (double)r.ru_utime.tv_usec;
    #if defined(__APPLE__)
      *mem = (long)r.ru_maxrss;
    #else
      *mem = (long)(r.ru_maxrss * 1024L);
    #endif
    #endif
    }
    
    void CheckResources()
    {
    #if !defined (WIN32) || defined(__CYGWIN__)
      static struct rlimit r;
    
      getrlimit(RLIMIT_STACK, &r);
    
      // Try to get at least 16 MB of stack. Running with too small a stack
      // can cause crashes in the recursive calls (e.g. for tet
      // classification in 3D Delaunay)
      if(r.rlim_cur < 16 * 1024 * 1024){
        Msg::Info("Increasing process stack size (%d kB < 16 MB)", r.rlim_cur / 1024);
        r.rlim_cur = r.rlim_max;
        setrlimit(RLIMIT_STACK, &r);
      }
    #endif
    }
    
    double Cpu()
    {
      long mem = 0;
      double s = 0.;
      GetResources(&s, &mem);
      return s;
    }
    
    long GetMemoryUsage()
    {
      long mem = 0;
      double s = 0.;
      GetResources(&s, &mem);
      return mem;
    }
    
    int GetProcessId()
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      return _getpid();
    #else
      return getpid();
    #endif
    }
    
    std::string GetHostName()
    {
      char host[256];
      gethostname(host, sizeof(host));
      return std::string(host);
    }
    
    int UnlinkFile(const std::string &fileName)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      setwbuf(0, fileName.c_str());
      return _wunlink(wbuf[0]);
    #else
      return unlink(fileName.c_str());
    #endif
    }
    
    int StatFile(const std::string &fileName)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      struct _stat buf;
      setwbuf(0, fileName.c_str());
      int ret = _wstat(wbuf[0], &buf);
    #else
      struct stat buf;
      int ret = stat(fileName.c_str(), &buf);
    #endif
      return ret;
    }
    
    int CreateDirectory(const std::string &dirName)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      setwbuf(0, dirName.c_str());
      if(_wmkdir(wbuf[0])) return 0;
    #else
      if(mkdir(dirName.c_str(), 0777)) return 0;
    #endif
      return 1;
    }
    
    int KillProcess(int pid)
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
      if(!TerminateProcess(hProc, 0)){
        CloseHandle(hProc);
        return 0;
      }
    #else
      if(kill(pid, 9))
        return 0;
    #endif
      return 1;
    }
    
    int SystemCall(const std::string &command, bool blocking)
    {
      // separate (potential) executable from arguments
      std::string exe, args;
      std::string::size_type pos = command.find_first_of(" ");
      if(pos != std::string::npos){
        exe = command.substr(0, pos);
        args = command.substr(pos, command.size() - pos);
      }
      else
        exe = command;
    
      // get executable extension
      std::vector<std::string> split = SplitFileName(exe);
    
      // do we try to run a .py script or a .exe?
      bool isPython = (split[2] == ".py" || split[2] == ".PY");
      bool isExe = (split[2] == ".exe" || split[2] == ".EXE");
    
      if(isPython || isExe){
        if(StatFile(exe)){
          Msg::Error("Unable to open file '%s'", exe.c_str());
          return 1;
        }
      }
    
    #if defined(WIN32) && !defined(__CYGWIN__)
      if(isPython){
        Msg::Info("Shell opening '%s' with arguments '%s'", exe.c_str(),
                  args.c_str());
        ShellExecute(NULL, (char*)"open", (char*)exe.c_str(),
                     (char*)args.c_str(), NULL, 0);
      }
      else{
        STARTUPINFO suInfo;
        PROCESS_INFORMATION prInfo;
        memset(&suInfo, 0, sizeof(suInfo));
        suInfo.cb = sizeof(suInfo);
        Msg::Info("Calling '%s'", command.c_str());
        if(blocking){
          CreateProcess(NULL, (char*)command.c_str(), NULL, NULL, FALSE,
    		    NORMAL_PRIORITY_CLASS, NULL, NULL,
    		    &suInfo, &prInfo);
          // wait until child process exits.
          WaitForSingleObject(prInfo.hProcess, INFINITE);
          // close process and thread handles.
          CloseHandle(prInfo.hProcess);
          CloseHandle(prInfo.hThread);
        }
        else{
          // DETACHED_PROCESS removes the console (useful if the program to launch
          // is a console-mode exe)
          CreateProcess(NULL, (char*)command.c_str(), NULL, NULL, FALSE,
    		    NORMAL_PRIORITY_CLASS|DETACHED_PROCESS, NULL, NULL,
    		    &suInfo, &prInfo);
        }
      }
    #else
      std::string cmd(command);
      if(isPython || isExe){
        if(access(exe.c_str(), X_OK)){
          if(isPython){
            Msg::Info("Script '%s' is not executable: running with python", exe.c_str());
            cmd = "python " + cmd;
          }
          else
            Msg::Warning("File '%s' is not executable", exe.c_str());
        }
        else if(split[0].empty()){
          // workaround if pwd is not in PATH
          cmd = "./" + cmd;
        }
      }
      if(!system(NULL)) {
        Msg::Error("Could not find /bin/sh: aborting system call");
        return 1;
      }
      if(!blocking) cmd += " &";
      Msg::Info("Calling '%s'", cmd.c_str());
      if(!system(cmd.c_str())) return 1;
    #endif
      return 0;
    }
    
    std::string GetCurrentWorkdir()
    {
      char path[1024];
    
    #if defined(WIN32) && !defined(__CYGWIN__)
      if(!_getcwd(path, sizeof(path))) return "";
    #else
      if(!getcwd(path, sizeof(path))) return "";
    #endif
    
      std::string str(path);
      // match the convention of SplitFileName that delivers directory path
      // ending with a directory separator
    #if defined(WIN32)
      str.append("\\");
    #else
      str.append("/");
    #endif
      return str;
    }
    
    void RedirectIOToConsole()
    {
    #if defined(WIN32) && !defined(__CYGWIN__)
      // Win32 GUI apps do not write to the DOS console; make it work again by
      // attaching to parent console, which allows to use the DOS shell to work with
      // Gmsh on the command line (without this hack, you need to either use a
      // better shell (e.g. bash), or compile a /subsystem:console version
      if(!AttachConsole(ATTACH_PARENT_PROCESS)) return;
      // redirect unbuffered stdout, stdin and stderr to the console
      {
        intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
        if(lStdHandle != (intptr_t)INVALID_HANDLE_VALUE){
          int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
          if(hConHandle >= 0){
            FILE *fp = _fdopen(hConHandle, "w");
            if(fp){
              *stdout = *fp;
              setvbuf(stdout, NULL, _IONBF, 0);
            }
          }
        }
      }
      {
        intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
        if(lStdHandle != (intptr_t)INVALID_HANDLE_VALUE){
          int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
          if(hConHandle >= 0){
            FILE *fp = _fdopen(hConHandle, "r");
            if(fp){
              *stdin = *fp;
              setvbuf(stdin, NULL, _IONBF, 0);
            }
          }
        }
      }
      {
        intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
        if(lStdHandle != (intptr_t)INVALID_HANDLE_VALUE){
          int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
          if(hConHandle >= 0){
            FILE *fp = _fdopen(hConHandle, "w");
            if(fp){
              *stderr = *fp;
              setvbuf(stderr, NULL, _IONBF, 0);
            }
          }
        }
      }
      // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console
      // as well
      std::ios::sync_with_stdio();
    #endif
    }