示例#1
0
/* emulate fputs for console. */
int vmdcon_fputs(const int lvl, const char *string) 
{
    /* prefix message with info level... or not. */
    switch (lvl) {
      case VMDCON_INFO:
        vmdcon_append(lvl, "Info) ", 6);
        break;

      case VMDCON_WARN:
        vmdcon_append(lvl, "Warning) ", 9);
        break;

      case VMDCON_ERROR:
        vmdcon_append(lvl, "ERROR) ", 7);
        break;

      default:  
        break;
    }

    vmdcon_append(lvl, string, -1);
    vmdcon_purge();

    return 0;    
}
示例#2
0
/* register a tk/tcl widget to be the console window.
 * we get the widget path directly from tcl, 
 * so we have to create a copy (and free it later).
 * we also need a pointer to the tcl interpreter.
 */
int vmdcon_register(const char *w_path, const char *mark, void *interp)
{
    wkf_mutex_lock(&vmdcon_status_lock);
    vmdcon_interp=interp;

    /* unregister current console widget */
    if(w_path == NULL) {
        if (vmdcon_wpath != NULL) {
            free(vmdcon_wpath);
            free(vmdcon_mark);
        }
        vmdcon_wpath=NULL;
        vmdcon_mark=NULL;
        /* we have to indicate that no console is available */
        if (vmdcon_status == VMDCON_WIDGET) vmdcon_status=VMDCON_NONE;
    } else {
        int len;
        
        if (vmdcon_wpath != NULL) {
            free(vmdcon_wpath);
            free(vmdcon_mark);
        }
    
        len=strlen(w_path);
        vmdcon_wpath=(char*)malloc(len+1);
        strcpy(vmdcon_wpath, w_path);
        len=strlen(mark);
        vmdcon_mark=(char*)malloc(len+1);
        strcpy(vmdcon_mark, mark);
    }
    wkf_mutex_unlock(&vmdcon_status_lock);

    /* try to flush pending console log text. */
    return vmdcon_purge();
}
示例#3
0
Inform& sendmsg(Inform& inform) { 
  Inform& rc = inform.send(); 

#if defined(VMDTKCON)
  vmdcon_purge();
#else
  fflush(stdout); // force standard output to be flushed here, otherwise output
                  // from Inform, stdio, Tcl, and Python can be weirdly 
                  // buffered, resulting in jumbled output from batch runs
#endif
  return rc;
}
示例#4
0
/* emulate printf. unfortunately, we cannot rely on 
 * snprintf being available, so we have to write to
 * a very large buffer and then free it. :-( */
int vmdcon_printf(const int lvl, const char *fmt, ...) 
{
    va_list ap;
    char *buf;
    int len;

    /* expand formated output into a single string */
    buf = (char *)malloc(vmdcon_bufsz);
    va_start(ap, fmt);
    len = vsprintf(buf, fmt, ap);

    /* check result. we may get a segfault, but if not
     * let the user know that he/she is in trouble. */
    if (len >= vmdcon_bufsz) {
        fprintf(stderr,"WARNING! buffer overflow in vmdcon_printf. %d vs %d.\n",
                len, vmdcon_bufsz);
        free(buf);
        errno=ERANGE;
        return -1;
    }

    /* prefix message with info level... or not. */
    switch (lvl) {
      case VMDCON_INFO:
        vmdcon_append(lvl, "Info) ", 6);
        break;

      case VMDCON_WARN:
        vmdcon_append(lvl, "Warning) ", 9);
        break;

      case VMDCON_ERROR:
        vmdcon_append(lvl, "ERROR) ", 7);
        break;

      default:  
        break;
    }

    vmdcon_append(lvl, buf, len);
    vmdcon_purge();

    free(buf);
    return 0;    
}
示例#5
0
/* append text from to console log buffer to queue. */
int vmdcon_showlog(void)
{
    struct vmdcon_msg *log, *msg;

    wkf_mutex_lock(&vmdcon_output_lock);
    log=vmdcon_logmsgs;
    do {
        /* append to message queue. */
        msg=(struct vmdcon_msg *)malloc(sizeof(struct vmdcon_msg));
        msg->txt=(char *) malloc(strlen(log->txt)+1);
        msg->lvl=VMDCON_ALWAYS;
        strcpy(msg->txt,log->txt);
        msg->next=NULL;
    
        if (vmdcon_pending == NULL) {
            vmdcon_pending=msg;
            vmdcon_lastmsg=msg;
        } else {
            vmdcon_lastmsg->next=msg;
            vmdcon_lastmsg=msg;
        }
        log=log->next;
    } while (log->next != NULL);

    /* terminate the dmesg output with a newline */
    msg=(struct vmdcon_msg *)malloc(sizeof(struct vmdcon_msg));
    msg->txt=(char *) malloc(strlen("\n")+1);
    msg->lvl=VMDCON_ALWAYS;
    strcpy(msg->txt,"\n");
    msg->next=NULL;
    
    if (vmdcon_pending == NULL) {
        vmdcon_pending=msg;
        vmdcon_lastmsg=msg;
    } else {
        vmdcon_lastmsg->next=msg;
        vmdcon_lastmsg=msg;
    }
    log=log->next;

    wkf_mutex_unlock(&vmdcon_output_lock);
    return vmdcon_purge();
}
示例#6
0
int TclTextInterp::evalString(const char *s) {
#if defined(VMD_NANOHUB)
  if (Tcl_Eval(interp, s) != TCL_OK) {
#else
  if (Tcl_RecordAndEval(interp, s, 0) != TCL_OK) {
#endif
    // Don't print error message if there's nothing to show.
    if (strlen(Tcl_GetStringResult(interp))) 
      msgErr << Tcl_GetStringResult(interp) << sendmsg;
    return FALSE;
  }
  return TRUE;
}

void TclTextInterp::setString(const char *name, const char *val) {
  if (interp)
    Tcl_SetVar(interp, name, val, 
      TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
}

void TclTextInterp::setMap(const char *name, const char *key, 
                           const char *val) { 
  if (interp)
    Tcl_SetVar2(interp, name, key, val, 
      TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
    
}

// There's a fair amount of code duplication between doEvent and evalFile,
// maybe these could be combined somehow, say by having TclTextInterp keep 
// track of its Tcl_Channel objects.
// 
// Side note: Reading line-by-line gives different Tcl semantics than 
// just calling Tcl_EvalFile. Shell commands (e.g., stty) are properly
// parsed when read line-by-line and passed to Tcl_RecordAndEval, but are
// unrecognized when contained in a file read by Tcl_EvalFile.  I would 
// consider this a bug.  

int TclTextInterp::evalFile(const char *fname) {
  Tcl_Channel inchannel = Tcl_OpenFileChannel(interp, fname, "r", 0644);
  Tcl_Channel outchannel = Tcl_GetStdChannel(TCL_STDOUT);
  if (inchannel == NULL) {
    msgErr << "Error opening file " << fname << sendmsg;
    msgErr << Tcl_GetStringResult(interp) << sendmsg;
    return 1;
  }

  Tcl_Obj *cmdPtr = Tcl_NewObj();
  Tcl_IncrRefCount(cmdPtr);
  int length = 0;
  while ((length = Tcl_GetsObj(inchannel, cmdPtr)) >= 0) {
    Tcl_AppendToObj(cmdPtr, "\n", 1);
    char *stringrep = Tcl_GetStringFromObj(cmdPtr, NULL);
    if (!Tcl_CommandComplete(stringrep)) {
      continue;
    }

    // check if "exit" was called
    if (app->exitFlag) break;

#if defined(VMD_NANOHUB)
    Tcl_EvalObjEx(interp, cmdPtr, 0);
#else
    Tcl_RecordAndEvalObj(interp, cmdPtr, 0);
#endif

#if TCL_MINOR_VERSION >= 4
    Tcl_DecrRefCount(cmdPtr);
    cmdPtr = Tcl_NewObj();
    Tcl_IncrRefCount(cmdPtr);
#else
    // XXX this crashes Tcl 8.5.[46] with an internal panic
    Tcl_SetObjLength(cmdPtr, 0);
#endif

    // XXX this makes sure the display is updated 
    // after each line read from the file or pipe
    // So, this is also where we'd optimise reading multiple
    // lines at once
    //
    // In VR modes (CAVE, FreeVR, VR Juggler) the draw method will 
    // not be called from app->display_update(), so multiple lines
    // of input could be combined in one frame, if possible
    app->display_update();

    Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
    char *bytes = Tcl_GetStringFromObj(resultPtr, &length);
#if defined(VMDTKCON)
    if (length > 0) {
      vmdcon_append(VMDCON_ALWAYS, bytes,length);
      vmdcon_append(VMDCON_ALWAYS, "\n", 1);
    }
    vmdcon_purge();
#else
    if (length > 0) {
#if TCL_MINOR_VERSION >= 4
      Tcl_WriteChars(outchannel, bytes, length);
      Tcl_WriteChars(outchannel, "\n", 1);
#else
      Tcl_Write(outchannel, bytes, length);
      Tcl_Write(outchannel, "\n", 1);
#endif
    }
    Tcl_Flush(outchannel);
#endif
  }
  Tcl_Close(interp, inchannel);
  Tcl_DecrRefCount(cmdPtr);
  return 0;
}
示例#7
0
void TclTextInterp::doEvent() {
  if (!done_waiting())
    return;

  // no recursive calls to TclEvalObj; this prevents  
  // display update ui from messing up Tcl. 
  if (callLevel) 
    return;

  Tcl_Channel inChannel = Tcl_GetStdChannel(TCL_STDIN);
  Tcl_Channel outChannel = Tcl_GetStdChannel(TCL_STDOUT);

  if (needPrompt && consoleisatty) {
#if TCL_MINOR_VERSION >= 4
    if (gotPartial) {
      Tcl_WriteChars(outChannel, "? ", -1);
    } else { 
      Tcl_WriteChars(outChannel, VMD_CMD_PROMPT, -1);
    }
#else
    if (gotPartial) {
      Tcl_Write(outChannel, "? ", -1);
    } else { 
      Tcl_Write(outChannel, VMD_CMD_PROMPT, -1);
    }
#endif
#if defined(VMDTKCON)
    vmdcon_purge();
#endif
    Tcl_Flush(outChannel);
    needPrompt = 0;
  }

#if defined(VMD_NANOHUB)  
  return;
#endif

  //
  // MPI builds of VMD cannot try to read any command input from the 
  // console because it creates shutdown problems, at least with MPICH.
  // File-based command input is fine however.
  //
  // For the time being, the Android builds won't attempt to get any
  // console input.  Any input we're going to get is going to come via
  // some means other than stdin, such as a network socket, text box, etc.
  //
  if (ignorestdin)
    return;
 
  if (!vmd_check_stdin())
    return;

  //
  // event loop based on tclMain.c
  //
  // According to the Tcl docs, GetsObj returns -1 on error or EOF.
    
  int length = Tcl_GetsObj(inChannel, commandPtr);
  if (length < 0) {
    if (Tcl_Eof(inChannel)) {
      // exit if we're not a tty, or if eofexit is set
      if ((!consoleisatty) || app->get_eofexit())
        app->VMDexit("", 0, 0);
    } else {
      msgErr << "Error reading Tcl input: " << Tcl_ErrnoMsg(Tcl_GetErrno()) 
             << sendmsg;
    }
    return;
  }
  
  needPrompt = 1;
  // add the newline removed by Tcl_GetsObj
  Tcl_AppendToObj(commandPtr, "\n", 1);

  char *stringrep = Tcl_GetStringFromObj(commandPtr, NULL);
  if (!Tcl_CommandComplete(stringrep)) {
    gotPartial = 1;
    return;
  }
  gotPartial = 0;

  callLevel++;
#if defined(VMD_NANOHUB)
  Tcl_EvalObjEx(interp, commandPtr, 0);
#else
  Tcl_RecordAndEvalObj(interp, commandPtr, 0);
#endif
  callLevel--;

#if TCL_MINOR_VERSION >= 4
  Tcl_DecrRefCount(commandPtr);
  commandPtr = Tcl_NewObj();
  Tcl_IncrRefCount(commandPtr);
#else
  // XXX this crashes Tcl 8.5.[46] with an internal panic
  Tcl_SetObjLength(commandPtr, 0);
#endif
    
  // if ok, send to stdout; if not, send to stderr
  Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
  char *bytes = Tcl_GetStringFromObj(resultPtr, &length);
#if defined(VMDTKCON)
  if (length > 0) {
    vmdcon_append(VMDCON_ALWAYS, bytes,length);
    vmdcon_append(VMDCON_ALWAYS, "\n", 1);
  }
  vmdcon_purge();
#else
  if (length > 0) {
#if TCL_MINOR_VERSION >= 4
    Tcl_WriteChars(outChannel, bytes, length);
    Tcl_WriteChars(outChannel, "\n", 1);
#else
    Tcl_Write(outChannel, bytes, length);
    Tcl_Write(outChannel, "\n", 1);
#endif
  }
  Tcl_Flush(outChannel);
#endif
}
示例#8
0
文件: vmd.C 项目: quolc/VMDLeap
int VMDinitialize(int *argc, char ***argv) {
  int i;

#if defined VMDMPI
  // hack to fix up env vars if necessary
  for (i=0; i<(*argc); i++) {
    if(!strupcmp((*argv)[i], "-vmddir")) {
      if((*argc) > (i + 1)) {
        setenv("VMDDIR", (*argv)[++i], 1);
      } else {
        msgErr << "-vmddir must specify a fully qualified path." << sendmsg;
      }
    }
  }

  vmd_mpi_init(argc, argv);  // initialize MPI, fix up env vars, etc.
#endif

#if defined(_MSC_VER) && !defined(VMDSEPARATESTARTUP)
  win32vmdstart(); // get registry info etc
#endif

#if !defined(VMDNOMACBUNDLE) && defined(__APPLE__)
  macosxvmdstart(*argc, *argv); // get env variables etc
#endif

  // Tell Tcl where the executable is located
  const char *argv0 = vmd_initialize_tcl((*argv)[0]);

#ifdef VMDTCL
  // register signal handler
  tclhandler = Tcl_AsyncCreate(VMDTclAsyncProc, (ClientData)NULL); 
  signal(SIGINT, (sighandler_t) VMDTclSigHandler);  
#endif

  // Let people know who we are.
  VMDtitle();

  // Tell the user what we think about the hardware we're running on.
  // If VMD is compiled for MPI, then we don't print any of the normal
  // standalone startup messages and instead we use the special MPI-specific
  // node scan startup messages only.
#if !defined(VMDMPI)
#if defined(VMDTHREADS) 
  int vmdnumcpus = wkf_thread_numprocessors();
  msgInfo << "Multithreading available, " << vmdnumcpus <<
             ((vmdnumcpus > 1) ? " CPUs" : " CPU") <<  " detected." 
          << sendmsg;
#endif

  long vmdcorefree = vmd_get_avail_physmem_mb();
  if (vmdcorefree >= 0) {
    long vmdcorepcnt = vmd_get_avail_physmem_percent();
    msgInfo << "Free system memory: " << vmdcorefree 
            << "MB (" << vmdcorepcnt << "%)" << sendmsg;
  }
#endif

  // Read environment variables and command line options.
  // Initialize customArgv with just argv0 to avoid problems with
  // Tcl extension.
  customArgv.append((char *)argv0);
  VMDGetOptions(*argc, *argv); 

#if (!defined(__APPLE__) && !defined(_MSC_VER)) && (defined(VMDOPENGL) || defined(VMDFLTK))
  // If we're using X-windows, we autodetect if the DISPLAY environment
  // variable is unset, and automatically switch back to text mode without
  // requiring the user to pass the "-dispdev text" command line parameters
  if ((which_display == DISPLAY_WIN) && (getenv("DISPLAY") == NULL)) {
    which_display = DISPLAY_TEXT;
  }
#endif

#if defined(VMDTKCON)
  vmdcon_init();
  msgInfo << "Using VMD Console redirection interface." << sendmsg;
  // we default to a widget mode console, unless text mode is requested.
  // we don't have an tcl interpreter registered yet, so it is set to NULL.
  // flushing pending messages to the screen, is only in text mode possible.
  if ((which_display == DISPLAY_TEXT) || just_print_help) {
    vmdcon_use_text(NULL);
    vmdcon_purge();
  } else {
    vmdcon_use_widget(NULL);
  }
#endif

#ifdef VMDFLTK
  // Do various special FLTK initialization stuff here
  if ((which_display != DISPLAY_TEXT)) {
    // Cause FLTK to to use 24-bit color for all windows if possible
    // This must be done before any FLTK windows are shown for the first time.
    if (!Fl::visual(FL_DOUBLE | FL_RGB8)) {
      if (!Fl::visual(FL_RGB8)) {
        Fl::visual(FL_RGB); 
      }
    }

    // Disable the use of the arrow keys for navigating buttons and other
    // non-text widgets, we'll try it out and see how it pans out
    Fl::visible_focus(0);

    // Disable Drag 'n Drop since the only text field in VMD is the
    // atomselection input and DND severely gets in the way there.
    Fl::dnd_text_ops(0);
  }
#endif

  // Quit now if the user just wanted a list of command line options.
  if (just_print_help) {
    vmd_sleep(10);  // This is here so that the user can see the message 
                    // before the terminal/shell exits...
    return 0;
  }

  // Set up default allocators; these may be overridden by cave or freevr. 
  vmd_alloc   = malloc;  // system malloc() in the default case
  vmd_dealloc = free;    // system free() in the default case
  vmd_realloc = realloc; // system realloc(), set to NULL when not available 

  // check for a CAVE display
  if (DISPLAY_USES_CAVE(which_display)) {
#ifdef VMDCAVE
    // allocate shared memory pool used to communicate with child renderers
    int megs = 2048;
    if (getenv("VMDCAVEMEM") != NULL) {
      megs = atoi(getenv("VMDCAVEMEM"));
    } 
    msgInfo << "Attempting to get " << megs << 
            "MB of CAVE Shared Memory" << sendmsg;
    grab_CAVE_memory(megs);

    CAVEConfigure(argc, *argv, NULL); // configure cave walls and memory use

    // point VMD shared memory allocators to CAVE routines
    vmd_alloc = malloc_from_CAVE_memory;
    vmd_dealloc = free_to_CAVE_memory;
    vmd_realloc = NULL; // no realloc() functionality is available presently
#else
    msgErr << "Not compiled with the CAVE options set." << sendmsg;
    which_display = DISPLAY_WIN;    
#endif
  }

  // check for a FreeVR display
  if (DISPLAY_USES_FREEVR(which_display)) {
#ifdef VMDFREEVR
    int megs = 2048;
    if (getenv("VMDFREEVRMEM") != NULL) {
      megs = atoi(getenv("VMDFREEVRMEM"));
    } 
    msgInfo << "Attempting to get " << megs << 
            "MB of FreeVR Shared Memory" << sendmsg;
    grab_FreeVR_memory(megs); // have to do this *before* vrConfigure() if
                              // we want more than the default shared mem.
    vrConfigure(NULL, NULL, NULL); // configure FreeVR walls

    // point shared memory allocators to FreeVR routines
    vmd_alloc = malloc_from_FreeVR_memory;
    vmd_dealloc = free_to_FreeVR_memory;
    vmd_realloc = NULL; // no realloc() functionality is available presently
#else
    msgErr << "Not compiled with the FREEVR options set." << sendmsg;
    which_display = DISPLAY_WIN;    
#endif
  }

  // return custom argc/argv
  *argc = customArgv.num();
  for (i=0; i<customArgv.num(); i++) {
    (*argv)[i] = customArgv[i];
  }
  return 1; // successful startup
}