Logo Search packages:      
Sourcecode: openturns version File versions  Download package

WrapperCommonFunctions.cxx

Go to the documentation of this file.
//                                               -*- C++ -*-
/**
 * @file  WrapperCommonFunctions.cxx
 * @brief This file provides function tools for the wrapper library
 *
 * (C) Copyright 2005-2006 EDF
 *
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 *
 *
 * @author $LastChangedBy: dutka $
 * @date   $LastChangedDate: 2007-02-16 12:11:35 +0100 (Fri, 16 Feb 2007) $
 */

#include "WrapperCommonFunctions.hxx"
#include "OSS.hxx"
#include "Log.hxx"
#include "ResourceMap.hxx"

using OT::Base::Common::ResourceMap;


/* Write a message in the Open TURNS log */
extern void printToLog(const OT::String & msg)
{
  OT::Base::Common::Log::Wrapper( msg );
}


/* Write a user message in the Open TURNS log */
extern void printToLogUser(const OT::String & msg)
{
  OT::Base::Common::Log::User( msg );
}


/* Some functions that help debugging memory allocation */
/* Allocate SIZE bytes of memory.  */
extern __malloc_ptr_t dbg_malloc __MALLOC_P ((int line, size_t __size))
{
  __malloc_ptr_t ptr = malloc(__size);
  if (ptr) memset(ptr, 0, __size);
#ifdef DEBUG
  printToLog( OT::OSS() << "(malloc) line " << line
            << " : ptr=" << ptr
            << " size=" << __size );
#endif
  return ptr;
}

/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
extern __malloc_ptr_t dbg_calloc __MALLOC_P ((int line, size_t __nmemb, size_t __size))
{
  __malloc_ptr_t ptr = calloc(__nmemb, __size);
  if (ptr) memset(ptr, 0, __nmemb*__size);
#ifdef DEBUG
  printToLog( OT::OSS() << "(calloc) line " << line
            << " : ptr=" << ptr
            << " nmemb=" << __nmemb
            << " size=" << __size );
#endif
  return ptr;
}
  
/* Re-allocate the previously allocated block in __ptr, making the new
   block SIZE bytes long.  */
extern __malloc_ptr_t dbg_realloc __MALLOC_P ((int line, __malloc_ptr_t __ptr, size_t __size))
{
  __malloc_ptr_t ptr = realloc(__ptr, __size);
#ifdef DEBUG
  printToLog( OT::OSS() << "(realloc) line " << line
            << " : ptr=" << ptr
            << " __ptr=" << __ptr
            << " size=" << __size );
#endif
  return ptr;
}
  
/* Free a block allocated by `malloc', `realloc' or `calloc'.  */
extern void dbg_free __MALLOC_P ((int line, __malloc_ptr_t __ptr))
{
#ifdef DEBUG
  printToLog( OT::OSS() << "(free) line " << line
            << " : ptr=" << __ptr );
#endif
  free(__ptr);
}



#ifdef DEBUG_MEMORY
#if (OT_DEBUG_LEVEL < 9)
#warning "-DDEBUG_MEMORY is only visible when debug level is 9 or higher"
#endif
#define malloc(sz)      dbg_malloc( __LINE__, (sz) )
#define calloc(nb,sz)   dbg_calloc( __LINE__, (nb), (sz) )
#define realloc(ptr,sz) dbg_realloc( __LINE__, (ptr), (sz) )
#define free(ptr)       dbg_free( __LINE__, (ptr) )
#endif






/* Read file pointed by path and allocate a buffer that contains all its data.
 * Put the stat of file in p_file_stat;
 */
extern char * readFile(const char * path, struct stat * p_file_stat)
{
  char * buf = NULL;
  unsigned long acceptable_errors = MAX_ERRORS;
  long position;
  long fd;
  long rc;
  size_t remaining_bytes;
  struct stat file_stat;
  if (stat(path, &file_stat)) {
    printToLog( OT::OSS() << "file path=" << path << " does NOT exists" );
    return NULL;
  }
  buf = (char *) calloc(file_stat.st_size+1, sizeof(char));
  if (buf == NULL) {
    printToLog( OT::OSS() << "Can NOT allocate enough memory (" << file_stat.st_size << " bytes)" );
    return NULL;
  }
      
  /* We open and read the file into the buffer */
  if ( (fd = open(path, O_RDONLY)) == -1) {
    printToLog( OT::OSS() << "Can NOT open file " << path << " for reading. Reason: " << strerror(errno) );
    return NULL;
  }

  /* We read the file */
#ifdef DEBUG
  printToLog( OT::OSS() << "Reading file " << path << " (size=" << file_stat.st_size << ")" );
#endif
  remaining_bytes = file_stat.st_size;
  position = 0;
  while (remaining_bytes) {
    ssize_t got_bytes = read(fd, buf+position, remaining_bytes);
#ifdef DEBUG
    printToLog( OT::OSS() << "Read " << got_bytes << " bytes - position=" << position << ", remaining_bytes=" << remaining_bytes );
#endif
    if (got_bytes == -1) {
      if (--acceptable_errors && ( (errno == EAGAIN) || (errno == EINTR) || (errno == EIO) ) ) continue;
      else {
      printToLog( OT::OSS() << "Error in reading file " << path << ". Reason: " << strerror(errno) );
      return NULL;
      }
    }
    acceptable_errors = MAX_ERRORS;
    position += got_bytes;
    remaining_bytes -= got_bytes;
  }
  buf[position] = 0;

  /* We close the file */
  while ( (rc = close(fd)) == -1) {
    if ( (errno == EINTR) || (errno == EIO) ) continue;
    else {
      printToLog( OT::OSS() << "Can NOT close file " << path << ". Reason: " << strerror(errno) );
      return NULL;
    }
  }

#ifdef DEBUG
  printToLog( OT::OSS() << "Buffer from file " << path << " (size=" << file_stat.st_size << ")" );
#endif
  *p_file_stat = file_stat;
  return buf;
}



/* Write the content of buf into file pointed by path. Use file_stat to set the mode */
extern long writeFile(const char * path, const char * buf, struct stat file_stat)
{
  unsigned long acceptable_errors = MAX_ERRORS;
  long position;
  long fd;
  long rc;
  ssize_t remaining_bytes;

  if (buf == NULL) {
    printToLog( OT::OSS() << "Can NOT write a null buffer" );
    return 1;
  }
      
  /* We open and read the file into the buffer */
  if ( (fd = creat(path, file_stat.st_mode)) == -1) {
    printToLog( OT::OSS() << "Can NOT open file " << path << " for writing. Reason: " << strerror(errno) );
    return 1;
  }

  /* We write the file */
#ifdef DEBUG
  printToLog( OT::OSS() << "Writing file " << path << " (size=" << strlen(buf) << ")" );
#endif
  remaining_bytes = strlen(buf);
  position = 0;
  while (remaining_bytes) {
    long sent_bytes = write(fd, buf+position, remaining_bytes);
    if (sent_bytes == -1) {
      if (--acceptable_errors && ( (errno == EAGAIN) || (errno == EINTR) || (errno == EIO) ) ) continue;
      else {
      printToLog( OT::OSS() << "Error in writing file " << path << ". Reason: " << strerror(errno) );
      return 1;
      }
    }
    acceptable_errors = MAX_ERRORS;
    position += sent_bytes;
    remaining_bytes -= sent_bytes;
  }

  /* We close the file */
  while ( (rc = close(fd)) == -1) {
    if ( (errno == EINTR) || (errno == EIO) ) continue;
    else {
      printToLog( OT::OSS() << "Can NOT close file " << path << ". Reason: " << strerror(errno) );
      return 1;
    }
  }

  return 0;
}






/* Print a regexp_match array */
extern void printRegexpMatchArray(const struct regexp_match regmatch)
{
  long i;
  for(i = 0; i < regmatch.n; ++i) {
    printToLog( OT::OSS() << ((i == 0) ? "" : "      ") );
    printToLog( OT::OSS() << "regmatch[" << i << "/" << regmatch.n
            << "] = { reg_init_paren_pos = " << regmatch.d[i].reg_init_paren_pos
            << ", repl_init_paren_ref = " << regmatch.d[i].repl_init_paren_ref
            << ", reg_tmp_paren_pos = " << regmatch.d[i].reg_tmp_paren_pos
            << ", repl_tmp_paren_ref = " << regmatch.d[i].repl_tmp_paren_ref
            << ", reg_new_paren_pos = " << regmatch.d[i].reg_new_paren_pos
            << ", repl_new_paren_ref = " << regmatch.d[i].repl_new_paren_ref
            << " }" );
  }
}


/* PARENTHESIS_FOUND is true when ptr points to a '(' character that is not backslashed */
#define PARENTHESIS_FOUND(ptr, string) ( (*(ptr) == '(') && ( ((ptr) == &(string)[0]) || (*((ptr)-1) != '\\') ) )


/* Return the number of parenthesis that corresponds to subexpressions in pattern matching */
extern long getNumberOfParenthesis(const std::string & s)
{
  long number = 0;
  const char * ptr = 0;

  if (s.size() == 0) return 0;

  ptr = s.c_str();
  while (*ptr) {
    if ( PARENTHESIS_FOUND( ptr, s.c_str() ) ) ++number;
    ++ptr;
  }

  return number;
}


/* Allocate and set the regexp_match array with the corresponding reference of sub-expressions */
extern struct regexp_match createRegexpMatchArray(const std::string & myregexp)
{
  long number = 0;
  struct regexp_match regmatch;
  const char * ptr = 0;

  regmatch.n = 0;
  regmatch.d = 0;
  if (myregexp.size() == 0) goto ERR;

  regmatch.n = getNumberOfParenthesis(myregexp);
  if (regmatch.n > 0) {

    regmatch.d = (struct regexp_match_data *) calloc(regmatch.n, sizeof(struct regexp_match_data));

    ptr = &myregexp[0];
    while (*ptr) {
      if ( PARENTHESIS_FOUND( ptr, myregexp.c_str() ) ) {
      regmatch.d[number].reg_init_paren_pos  = ptr - myregexp.c_str();
      regmatch.d[number].reg_new_paren_pos   = regmatch.d[number].reg_init_paren_pos;
      regmatch.d[number].repl_init_paren_ref = number + 1;
      regmatch.d[number].repl_new_paren_ref  = number + 1;
      regmatch.d[number].reg_tmp_paren_pos   = regmatch.d[number].reg_init_paren_pos;
      regmatch.d[number].repl_tmp_paren_ref  = regmatch.d[number].repl_init_paren_ref;
      ++number;
      }
      ++ptr;
    }

  } /* end if (nb_paren > 0) */

#ifdef DEBUG
  printToLog( OT::OSS() << "regexp = '" << myregexp << "'" );
  printRegexpMatchArray( regmatch );
#endif    

 ERR:
  return regmatch;
}

/* Free the storage allocated for a regexp_match structure */
extern void freeRegexpMatchArray(const struct regexp_match regmatch)
{
  free( regmatch.d );
}



extern void printChunk(struct chunk * elt)
{
#ifdef DEBUG
  if (elt)
    printToLog( OT::OSS() << "elt = " << elt
            << "\n      next = " << elt->next
            << "\n      start = " << elt->start
            << " / end = " << elt->end
            << "\n      ref = " << elt->ref
            << "\n      repl = " << elt->repl );
  else printToLog( OT::OSS() << "elt = " << elt );
#endif
}

/* Add an element (chunk) at the end of the linked list */
extern struct chunk * addChunkToList(struct chunk * list, struct chunk * elt)
{
  if (list == 0) return elt;
  struct chunk * current = list;
  while (current->next) current = current->next;
  current->next = elt;
  printChunk(elt);
  return list;
}

/* Print out the list as a string */
extern void printList(struct chunk * list)
{
  if (list == 0) return;
  if (list->repl) printToLog( OT::OSS() << list->repl);
  else for(long i=list->start; i<list->end; ++i) printToLog( OT::OSS() << (list->ref[i] ? list->ref[i] : '*') );
  printList(list->next);
}

/* Copy the content of the list as a string into buf. Buf MUST be allocated to a size that can
 * contains the whole list.
 */
extern void copyList(char * buf, struct chunk * list)
{
  char * ptr;

  if (list == 0) return;
  if (list->repl) {
    strcpy(buf, list->repl);
    ptr = buf + strlen(list->repl);
  } else {
    strncpy(buf, &(list->ref[list->start]), list->end - list->start);
    ptr = buf + list->end - list->start;
  }
  copyList(ptr, list->next);
}


/* Return the length of the string that corresponds to the list content */
extern long lengthList(struct chunk * list)
{
  long len = 0;

  if (list == 0) return 0;
  len = lengthList(list->next);
  if (list->repl) len += strlen(list->repl);
  else len += list->end - list->start;
#ifdef DEBUG
  printToLog( OT::OSS() << "(lengthList) len = " << len );
#endif
  return len;
}

/* Deallocate the elements (chunks) of the list */
extern void freeList(struct chunk * list)
{
  if (list == 0) return;
  freeList(list->next);
  if (list->repl) free(list->repl);
  free(list);
#ifdef DEBUG
  printToLog( "(freeList)" );
#endif
}




/* Substitute the content of mystring according to myregexp with myreplace.
 * Return a new buffer allocated (malloc) with the content of the replaced string.
 */
extern char * substitute(const char * mystring,
                   const std::string & origRegexp,
                   const std::string & origReplace,
                   const std::string & newRegexp,
                   const std::string & newReplace,
                   const struct regexp_match regmatch)
{
  regex_t * compiled;
  long cflags;
  size_t nmatch;
  regmatch_t * pmatch;
  struct chunk * list;
  struct chunk * last_elt;
  long pos;
  int  rc;
  long len;
  long len_mystring;
  size_t i,j;
  char * buf;
  int somematch;

  /* build regular expression */
  compiled = (regex_t *) malloc(sizeof(regex_t));
  cflags = REG_EXTENDED | REG_NEWLINE;
  rc = 0;
  if (( rc=regcomp(compiled, newRegexp.c_str(), cflags) )) {
    char * msg;
    size_t msg_len;

    msg_len = regerror(rc, compiled, 0, 0);
    msg = (char *) calloc(msg_len, sizeof(char));
    regerror(rc, compiled, msg, msg_len);
    printToLog( OT::OSS() << "Error in compiling regular expression '" << newRegexp << "' (from '" << origRegexp << "'). Message is: " << msg );
    free(msg);
    return 0;
  }

  /* scan buffer for matching patterns */
  nmatch = getNumberOfParenthesis(newRegexp) + 1;
  pmatch = (regmatch_t *) calloc(nmatch, sizeof(regmatch_t));
  len_mystring = strlen(mystring);
  pos = 0;
  rc = 0;
  somematch = 0;
  list = 0;
  while ( (pos <= len_mystring) &&
        !(rc = regexec(compiled, mystring+pos, nmatch, pmatch, 0))) {
    somematch = 1;

    if ( (pmatch[0].rm_so != -1) && (pmatch[0].rm_eo != -1) ) {
      struct chunk * elt;
      elt = (struct chunk *) malloc(sizeof(struct chunk));
      elt->next  = 0;
      elt->start = pos;
      elt->end   = pmatch[0].rm_so;
      elt->ref   = mystring;
      elt->repl  = 0;
      list = addChunkToList(list, elt);
#ifdef DEBUG
      printToLog( OT::OSS() << "Matched '" << OT::String( mystring + pmatch[0].rm_so, mystring + pmatch[0].rm_eo ) << "'" );
      printToLog( OT::OSS() << "Replaced by '" << newReplace << "'" );
#endif
    }

    for (i=0; i<newReplace.size(); /**/) {
      j = i;
      while ((newReplace[j] != 0) && (newReplace[j] != '\\')) ++j;
      if (i != j) {
#ifdef DEBUG
      printToLog( OT::OSS() << "Reading chunk from " << i << " to " << j << "  in replace string " << newReplace );
#endif
      struct chunk * elt;
      elt = (struct chunk *) malloc(sizeof(struct chunk));
      elt->next  = 0;
      elt->start = i;
      elt->end   = j;
      elt->ref   = newReplace.c_str();
      elt->repl  = 0;
      list = addChunkToList(list, elt);
      }
      
      if (newReplace[j] == '\\') {
#ifdef DEBUG
      printToLog( OT::OSS() << "Reading \\ in replace string " <<  newReplace );
#endif
      ++j;
      if ( islower(newReplace[j]) ) {
#ifdef DEBUG
        printToLog( OT::OSS() << "Reading lower case character '" << newReplace[j] << "' at place " << j << " in replace string " << newReplace );
#endif
        struct chunk * elt;
        elt = (struct chunk *) malloc(sizeof(struct chunk));
        elt->next  = 0;
        elt->start = 0;
        elt->end   = 1;
        elt->ref   = 0;
        elt->repl  = (char *) calloc(2, sizeof(char));
        elt->repl[0] = newReplace[j] - 'a';
        elt->repl[1] = 0;
        list = addChunkToList(list, elt);
      }
      if ( isdigit(newReplace[j]) ) {
#ifdef DEBUG
        printToLog( OT::OSS() << "Reading digit '" << newReplace[j] << "' at place " << j << " in replace string " << newReplace );
#endif
        char * ptr;
        size_t subexp;
        subexp = (size_t) strtoul(newReplace.c_str() + j, &ptr, 10);
        j = ptr - newReplace.c_str();
        if ((subexp > 0) && (subexp <= nmatch)) {
          struct chunk * elt;
          elt = (struct chunk *) malloc(sizeof(struct chunk));
          elt->next  = 0;
          elt->start = pos+pmatch[subexp].rm_so;
          elt->end   = pos+pmatch[subexp].rm_eo;
          elt->ref   = mystring;
          elt->repl  = 0;
          list = addChunkToList(list, elt);
        }
      }
      }
      i = j;
    } /* end for */

    

    if ( (pmatch[0].rm_so != -1) && (pmatch[0].rm_eo != -1) ) {
      pos += pmatch[0].rm_eo;
    }
  } /* end while */

  if ( (rc != REG_NOMATCH) || !somematch) {
    char * msg;
    size_t msg_len;

    msg_len = regerror(rc, compiled, 0, 0);
    msg = (char *) calloc(msg_len, sizeof(char));
    regerror(rc, compiled, msg, msg_len);
#ifdef DEBUG
    printToLog( OT::OSS() << "Error in matching regular expression '" << newRegexp << "' (from '" << origRegexp << "') in string '" << mystring << "'. Message is: " << msg );
#endif
    free(msg);
    freeList(list);
    regfree(compiled);
    free(pmatch);
    free(compiled);
    return 0;
  }

  last_elt = (struct chunk *) malloc(sizeof(struct chunk));
  last_elt->next  = 0;
  last_elt->start = pos;
  last_elt->end   = strlen(mystring);
  last_elt->ref   = mystring;
  last_elt->repl  = 0;
  list = addChunkToList(list, last_elt);

  len = lengthList(list);
#ifdef DEBUG
  printToLog( OT::OSS() << "length of list = " << len );  
#endif
  buf = (char *) calloc(len+1, sizeof(char));
  memset(buf, 0, len+1);
  copyList(buf, list);

  freeList(list);
  regfree(compiled);
  free(pmatch);
  free(compiled);

  return buf;
}

typedef std::map<std::string, std::string> ShortcutMap;


/* Initialize a map of shortcuts */
extern ShortcutMap getShortcutMap(const struct WrapperExchangedData * p_exchangedData)
{
  ShortcutMap shMap;
  const struct PlatformConfiguration * p_pf = p_exchangedData->platform_;

  shMap[ p_pf->realRegexpShortcut_      ] = ResourceMap::GetInstance().get("real-regexp");
  shMap[ p_pf->integerRegexpShortcut_   ] = ResourceMap::GetInstance().get("integer-regexp");
  shMap[ p_pf->separatorRegexpShortcut_ ] = ResourceMap::GetInstance().get("separator-regexp");

  return shMap;
}


/* Substitute the possibly found shortcuts in the regular expression
 * and set accordingly the regexp_match array to reflect the
 * changes in the regexp.
 */
extern void substituteShortcuts(const ShortcutMap & shMap, 
                        const std::string & origRegexp,
                        const std::string & origReplace,
                        std::string & newRegexp,
                        std::string & newReplace,
                        struct regexp_match regmatch)
{
  // HERE

  newRegexp.erase();
  newReplace.erase();    
    
  std::string regexpBeforeSubstitution  = origRegexp;
  std::string replaceBeforeSubstitution = origReplace;    

#ifdef DEBUG
  printToLog( OT::OSS() << "(substituteShortcuts) working on regexp '" << origRegexp << "' and replace string '" << origReplace );
#endif
    
  /* We try to substitute as many times as there is substitutions to do.
   * This is the case when shortcuts contains shortcuts.
   */
  long pos1 = 0;
  long pos2 = 0;
  long pass = 0;
  while ( 1 ) {

    std::string regexpAtPreviousRound  = regexpBeforeSubstitution;
    std::string replaceAtPreviousRound = replaceBeforeSubstitution;

    pass += 1;
#ifdef DEBUG
    printToLog( OT::OSS() << "(substituteShortcuts) pass #" << pass );  
#endif
    ShortcutMap::const_iterator it;
    for(it = shMap.begin(); it != shMap.end(); ++it) {
      const std::string regexpShortcut  = it->first;
      const std::string shortcutReplace = it->second;

#ifdef DEBUG
      printToLog( OT::OSS() << "(substituteShortcuts) regexpShortcut='" << regexpShortcut << "' => shortcutReplace='" << shortcutReplace );
      printToLog( OT::OSS() << "(substituteShortcuts) regexpBeforeSubstitution ='" << regexpBeforeSubstitution );
      printToLog( OT::OSS() << "(substituteShortcuts) replaceBeforeSubstitution='" << replaceBeforeSubstitution );
      printRegexpMatchArray( regmatch );
#endif  
      newRegexp.erase();
      newReplace.erase();

      /*************************************/
      /* We operate on regular expressions */
      /*************************************/
      pos1 = 0;
      pos2 = 0;
      while ( 1 ) {
      pos2 = regexpBeforeSubstitution.find( regexpShortcut, pos1 );
      if ( (pos2 < 0) || (pos2 > static_cast<long>( regexpBeforeSubstitution.size() )) ) break;

      newRegexp.append( regexpBeforeSubstitution, pos1, pos2-pos1 ); /* We copy the part between two substituted substrings */
      newRegexp.append( shortcutReplace );                           /* We do the substitution */

      /* We translate the values in p_regmatch structure */
      for(long i=0; i<regmatch.n; ++i) {
        if (pos2 < regmatch.d[i].reg_tmp_paren_pos) {
          regmatch.d[i].reg_new_paren_pos  += shortcutReplace.size() - regexpShortcut.size();
          regmatch.d[i].repl_new_paren_ref += getNumberOfParenthesis( shortcutReplace );
        }
      }

      pos1 = pos2 + regexpShortcut.size();

#ifdef DEBUG
      printRegexpMatchArray( regmatch );
#endif  
      } /* end while */
    
      newRegexp.append( regexpBeforeSubstitution, pos1, regexpBeforeSubstitution.size()-pos1 ); /* We copy the tail */


      /*********************************/
      /* We operate on replace strings */
      /*********************************/
      pos1 = 0;
      pos2 = 0;

      /* build regular expression */
      regex_t * compiled = (regex_t *) malloc(sizeof(regex_t));
      long cflags = REG_EXTENDED | REG_NEWLINE;
      int rc = 0;
      char re[] = "\\\\[0-9]+";
      if (( rc=regcomp(compiled, re, cflags) )) { /* We look for the \nnn back references */
      char * msg;
      size_t msg_len;
          
      msg_len = regerror(rc, compiled, 0, 0);
      msg = (char *) calloc(msg_len, sizeof(char));
      regerror(rc, compiled, msg, msg_len);
      printToLog( OT::OSS() << "Error in compiling regular expression '" << re << "'. Message is: " << msg );
      free(msg);
      return;
      }

      /* scan buffer for matching patterns */
      regmatch_t pmatch;
      long len = replaceBeforeSubstitution.size();
      while (pos1 <= len) {
      if (( rc = regexec(compiled, replaceBeforeSubstitution.c_str()+pos1, 1, &pmatch, 0) )) {
#ifdef DEBUG
        //      char * msg;
        //      size_t msg_len;
          
        //      msg_len = regerror(rc, compiled, 0, 0);
        //      msg = (char *) calloc(msg_len, sizeof(char));
        //      regerror(rc, compiled, msg, msg_len);
        //      fprintf(stderr,
        //            "Error in matching regular expression '" <<  << "' in string '" <<  << "'. Message is: ",
        //            re,
        //            replaceBeforeSubstitution.c_str()+pos1,
        //            msg);
        //      free(msg);
#endif
        break;
      }

      if ( (pmatch.rm_so != -1) && (pmatch.rm_eo != -1) ) {
        /* We match \nnn in the replace string */
        /* We read the value matched and look in the regmatch struct for the corresponding value */
        pos2 = pos1 + pmatch.rm_so + 1; /* one is for the slash */
        long nnn = strtoul(replaceBeforeSubstitution.c_str() + pos2, 0, 0);
        long new_nnn = 0;
        for(long i=0; i<regmatch.n; ++i) {
          if (regmatch.d[i].repl_init_paren_ref == nnn) {
            new_nnn = regmatch.d[i].repl_new_paren_ref;
            break;
          }
        } /* end for */

          /* We do the substitutions */
        std::ostringstream oss;
        oss << new_nnn;
        newReplace.append( replaceBeforeSubstitution, pos1, pos2-pos1 ); /* We copy the part between two substituted substrings */
        newReplace.append( oss.str() );

        pos1 = pos1 + pmatch.rm_eo;
      } /* end if */
      } /* end while */

      newReplace.append( replaceBeforeSubstitution, pos1, replaceBeforeSubstitution.size()-pos1 ); /* We copy the tail */

      regfree( compiled );
      free( compiled );

#ifdef DEBUG
      printToLog( OT::OSS() << "(substituteShortcuts) newRegexp                ='" << newRegexp );
      printToLog( OT::OSS() << "(substituteShortcuts) newReplace               ='" << newReplace );
      //printRegexpMatchArray( regmatch );
#endif  

      regexpBeforeSubstitution  = newRegexp;
      //replaceBeforeSubstitution = newReplace;
      /* We translate the values in p_regmatch structure */
      for(long i=0; i<regmatch.n; ++i) {
      regmatch.d[i].reg_tmp_paren_pos  = regmatch.d[i].reg_new_paren_pos;
      regmatch.d[i].repl_tmp_paren_ref = regmatch.d[i].repl_new_paren_ref;
      }
      
    } /* end for */  

    if (regexpAtPreviousRound == newRegexp) break; /* We leave the loop when no more substitutions were done */
    
  } /* end while */

#ifdef DEBUG
  printToLog( OT::OSS() << "(substituteShortcuts) build new regexp '" << newRegexp << "' and replace string '" << newReplace );
#endif
}


/* Substitute all the variables in p_variableList in buf.
 * Buf may be realloc-ated to hold the new string (if bigger).
 */
extern char * substituteVariables(char * buf,
                          const struct WrapperExchangedData * p_exchangedData,
                          const struct point * p_point,
                          long & sizeDiff)
{
  char * new_buf = 0;
  long coord = 0;
  long initialSize = strlen( buf );
  const struct WrapperVariableList * currentVariableElement = p_exchangedData->variableList_;
  while (currentVariableElement) {
    if (currentVariableElement->variable_->type_ == WRAPPER_IN) {

      long len = strlen(currentVariableElement->variable_->format_) * 2;
      char * orig_replace = (char *) calloc(len, sizeof(char));
      long bytes = 0;
      while ( (bytes = snprintf(orig_replace, len, currentVariableElement->variable_->format_, p_point->data_[coord])) >= len) {
#ifdef DEBUG
      printToLog( OT::OSS() << "bytes=" << bytes );
#endif
      len *= 2;
      orig_replace = (char *) realloc(orig_replace, len * sizeof(char));
      }
      orig_replace[bytes] = 0;

#ifdef DEBUG
      printToLog( OT::OSS() << "format_='" << currentVariableElement->variable_->format_ << "' len=" << len );

      printToLog( OT::OSS() << "orig_replace='" << orig_replace << "' bytes=" << bytes );
#endif

      /* TODO : a function that allocates and sets the p_regmatch array */
      std::string origRegexp  = currentVariableElement->variable_->regexp_;
      std::string origReplace = orig_replace;
      std::string newRegexp;
      std::string newReplace;

      free(orig_replace);

      ShortcutMap shMap = getShortcutMap( p_exchangedData );
      struct regexp_match regmatch = createRegexpMatchArray( origRegexp );
      substituteShortcuts( shMap, origRegexp, origReplace, newRegexp, newReplace, regmatch );

      new_buf = substitute(buf, origRegexp, origReplace, newRegexp, newReplace, regmatch );
      freeRegexpMatchArray( regmatch );
      if (new_buf) {
      free(buf);
      buf = new_buf;
      }
      ++coord;
    }
    currentVariableElement = currentVariableElement->next_;
  }
  long finalSize = strlen( buf );
  sizeDiff = finalSize - initialSize;
  return buf;
}


/* Look for origRegexp in mystring and parse it as if it was a double. Returns NaN if not found or failure */
extern double retrieve(const std::string & mystring,
                   const std::string & origRegexp,
                   const std::string & origFormat,
                   const std::string & newRegexp,
                   const std::string & newFormat,
                   const struct regexp_match regmatch)
{
  double value = 9999.1111;
  regex_t * compiled;
  long cflags;
  size_t nmatch;
  regmatch_t * pmatch;
  long rc;
  size_t parenthesis;
  size_t nbParenthesis;

  /* build regular expression */
  compiled = (regex_t *) malloc(sizeof(regex_t));
  cflags = REG_EXTENDED | REG_NEWLINE;
  rc = 0;
  if (( rc=regcomp(compiled, newRegexp.c_str(), cflags) )) {
    char * msg;
    size_t msg_len;

    msg_len = regerror(rc, compiled, 0, 0);
    msg = (char *) calloc(msg_len, sizeof(char));
    regerror(rc, compiled, msg, msg_len);
    printToLog( OT::OSS() << "Error in compiling regular expression '" << newRegexp << "' (from '" << origRegexp << "'). Message is: " << msg );
    free(msg);
    return nan("char-sequence");
  }

  /* read parenthesis to be extracted */
  /* We expect a format like '\nnn' where nnn is the number of the parenthesis we have to extract */
  regex_t * expr = (regex_t *) malloc(sizeof(regex_t));
  char re[] = "^\\\\[0-9]+$";
  regcomp(expr, re, REG_EXTENDED);
  if (( rc = regexec(expr, newFormat.c_str(), 0, 0, 0) )) {
    printToLog( OT::OSS() << "Error in matching format expression '" << newFormat << "' (from '" << origFormat << "'). Should be of the form '\\nnn' where nnn is the number of the parenthesis you want to extract (re = '" << re << "')" );
    regfree(expr);
    free(expr);
    regfree(compiled);
    free(compiled);
    return nan("char-sequence");
  }

  parenthesis = strtoul(newFormat.c_str()+1, 0, 0);
  regfree(expr);
  free(expr);
    

  /* scan buffer for matching patterns */
  nbParenthesis = getNumberOfParenthesis(newRegexp);
  if (parenthesis > nbParenthesis) {
    printToLog( OT::OSS() << "Error between regular expression '" << newRegexp << "' and format '" << newFormat << "' (from '" << origRegexp << "'and '" << origFormat << "'). The number of parenthesis seen in expression does not match the value read in format" );
    regfree(compiled);
    free(compiled);
    return nan("char-sequence");
  }
  nmatch = nbParenthesis + 1;
  pmatch = (regmatch_t *) calloc(nmatch, sizeof(regmatch_t));
  rc = 0;
  if (!(rc = regexec(compiled, mystring.c_str(), nmatch, pmatch, 0))) {
    if ( (pmatch[parenthesis].rm_so != -1) && (pmatch[parenthesis].rm_eo != -1) ) {
      char * matched = (char *) calloc(pmatch[parenthesis].rm_eo - pmatch[parenthesis].rm_so + 1, sizeof(char));
      strncpy(matched, mystring.c_str() + pmatch[parenthesis].rm_so, pmatch[parenthesis].rm_eo - pmatch[parenthesis].rm_so);
      matched[pmatch[parenthesis].rm_eo - pmatch[parenthesis].rm_so] = 0;
      value = strtod(matched, 0);
#ifdef DEBUG
      printToLog( OT::OSS() << "matched='" << matched << "' / value=" << value );
#endif
      free(matched);
    }
  }

  if ( rc ) {
    char * msg;
    size_t msg_len;

    msg_len = regerror(rc, compiled, 0, 0);
    msg = (char *) calloc(msg_len, sizeof(char));
    regerror(rc, compiled, msg, msg_len);
#ifdef DEBUG
    printToLog( OT::OSS() << "Error in matching regular expression '" << newRegexp << "' (from '" << origRegexp << "') in string '" << mystring << "'. Message is: " << msg );
#endif
    free(msg);
    regfree(compiled);
    free(pmatch);
    free(compiled);
    return 0;
  }

  regfree(compiled);
  free(pmatch);
  free(compiled);

  return value;
}


/* Pick up data from the file */
extern long retrieveVariables(char * buf,
                        const struct WrapperExchangedData * p_exchangedData,
                        struct point * p_point)
{
  long coord = 0;
  const struct WrapperVariableList * currentVariableElement = p_exchangedData->variableList_;
  while (currentVariableElement) {
    if (currentVariableElement->variable_->type_ == WRAPPER_OUT) {
      std::string origRegexp = currentVariableElement->variable_->regexp_;
      std::string origFormat = currentVariableElement->variable_->format_;
      std::string newRegexp;
      std::string newFormat;

      if ( origFormat.size() == 0 ) origFormat = "\\1";

      ShortcutMap shMap = getShortcutMap( p_exchangedData );
      struct regexp_match regmatch = createRegexpMatchArray( origRegexp );
      substituteShortcuts( shMap, origRegexp, origFormat, newRegexp, newFormat, regmatch );

      double value = retrieve(buf, origRegexp, origFormat, newRegexp, newFormat, regmatch );
      p_point->data_[coord] = value;
      ++coord;
    }
    currentVariableElement = currentVariableElement->next_;
  }

  /* OK */
  return 0;
}

#define IS_READABLE_FOR_ME(s, uid)       ( ( (s).st_mode & S_IRUSR ) && ( (s).st_uid == (uid) ) )
#define IS_READABLE_FOR_MY_GROUP(s, gid) ( ( (s).st_mode & S_IRGRP ) && ( (s).st_gid == (gid) ) )
#define IS_READABLE_FOR_ANYBODY(s)         ( (s).st_mode & S_IROTH )
#define IS_READABLE(s,uid,gid) (IS_READABLE_FOR_ME( (s) , (uid) ) || IS_READABLE_FOR_MY_GROUP( (s) , (gid) ) || IS_READABLE_FOR_ANYBODY( (s) ))
#define IS_WRITABLE_FOR_ME(s, uid)       ( ( (s).st_mode & S_IWUSR ) && ( (s).st_uid == (uid) ) )
#define IS_WRITABLE_FOR_MY_GROUP(s, gid) ( ( (s).st_mode & S_IWGRP ) && ( (s).st_gid == (gid) ) )
#define IS_WRITABLE_FOR_ANYBODY(s)         ( (s).st_mode & S_IWOTH )
#define IS_WRITABLE(s,uid,gid) (IS_WRITABLE_FOR_ME( (s) , (uid) ) || IS_WRITABLE_FOR_MY_GROUP( (s) , (gid) ) || IS_WRITABLE_FOR_ANYBODY( (s) ))
#define IS_READWRITABLE(s,uid,gid) ( IS_READABLE( (s) , (uid) , (gid) ) && IS_WRITABLE( (s) , (uid) , (gid) ) )

/* Check that the directory is usable (existence and read/write access) */
extern long checkDirectory(const char * directory)
{
  struct stat dir_stat;
  uid_t my_euid = geteuid();
  gid_t my_egid = getegid();

  /* Check if the directory exists and if we can read/write to it. Exits otherwise */
  if (stat(directory, &dir_stat)) {
    printToLog( OT::OSS() << "directory or file " << directory << " does NOT exists" );
    return 1;
  }
  if (!S_ISDIR(dir_stat.st_mode)) {
    printToLog( OT::OSS() << directory << " is NOT a directory" );
    return 1;
  }
  if (!IS_READWRITABLE(dir_stat, my_euid, my_egid)) {
    printToLog( OT::OSS() << directory << " is NOT readable or writable for uid=" << my_euid << " gid=" << my_egid );
    return 1;
  }

  /* OK */
  return 0;
}

Generated by  Doxygen 1.6.0   Back to index