Example #1
0
PARSE_TOKEN *newParseTokenDescriptive(int type, const char *format) {
  PARSE_TOKEN *token = newParseToken(type);
  // do we have a describer between ( and )?
  if(endswith(format, ")") && strchr(format, '(')) {
    format = format + next_letter_in(format, '(') + 1;
    token->flavor = strdup(format);
    token->flavor[strlen(token->flavor)-1] = '\0';
  }
  return token;
}
void expand_dynamic_descs_dict(BUFFER *desc, PyObject *dict,const char *locale){
  // make our new buffer
  BUFFER *new_desc = newBuffer(bufferLength(desc)*2);
  BUFFER     *code = newBuffer(1); // for things we have to evaluate
  bool   proc_cond = FALSE; // are we processing a conditional statement?

  // copy over all of our description that is not dynamic text
  int start, end, i, j, size = bufferLength(desc);
  for(i = 0; i < size; i++) {
    // figure out when our next dynamic desc is.
    start = next_letter_in(bufferString(desc) + i, '[');

    // no more
    if(start == -1) {
      // copy the rest and skip to the end of the buffer
      bprintf(new_desc, "%s", bufferString(desc) + i);
      i = size - 1;
    }
    // we have another desc
    else {
      // copy everything up to start
      while(start > 0) {
	bprintf(new_desc, "%c", *(bufferString(desc) + i));
	start--;
	i++;
      }

      // skip the start marker
      i++;

      // find our end
      end = next_letter_in(bufferString(desc) + i, ']');

      // make sure we have it
      if(end == -1)
	break;

      // copy everything between start and end, and format the code
      bufferClear(code);
      for(j = 0; j < end; j++)
	bprintf(code, "%c", *(bufferString(desc) + i + j));
      bufferReplace(code, "\n", " ", TRUE);
      bufferReplace(code, "\r", "", TRUE);

      // skip i up to the end
      i = i + end;

      // are we trying to process a conditional statement?
      if(!strncasecmp(bufferString(code), "if ", 3)) {
	// strip out the leading if and whitespace
	char *code_copy = strdup(bufferString(code));
	char       *ptr = code_copy + 3;
	while(isspace(*ptr)) ptr++;
	
	// copy over the cleaned-up code, signal we're processing a conditional
	bufferClear(code);
	bufferCat(code, ptr);
	proc_cond = TRUE;

	// garbage collection
	free(code_copy);
      }

      // evaluate the code
      PyObject *retval = eval_script(dict, bufferString(code), locale);

      // did we encounter an error?
      if(retval == NULL)
	break;
      // are we evaluating a conditional or no?
      else if(proc_cond) {
	BUFFER *cond_retval =
	  expand_dynamic_conditional(desc, dict, retval, locale, &i);

	// if we have something to print, expand its embedded python
	if(*bufferString(cond_retval))
	  expand_dynamic_descs_dict(cond_retval, dict, locale);

	bufferCat(new_desc, bufferString(cond_retval));
	deleteBuffer(cond_retval);
	proc_cond = FALSE;
      }
      // append the output
      else if(PyString_Check(retval))
	bprintf(new_desc, "%s", PyString_AsString(retval));
      else if(PyInt_Check(retval))
	bprintf(new_desc, "%ld", PyInt_AsLong(retval));
      else if(PyFloat_Check(retval))
	bprintf(new_desc, "%lf", PyFloat_AsDouble(retval));
      // invalid return type...
      else if(retval != Py_None)
	log_string("dynamic desc had invalid evaluation: %s", 
		   bufferString(code));

      // oddly, freeing retval here corrupt memory. 
      // And not freeing it doesn't cause a memory leak. So bizarre...
      //   Py_XDECREF(retval);
    }
  }

  // copy over our contents
  bufferCopyTo(new_desc, desc);

  // garbage collection
  deleteBuffer(code);
  deleteBuffer(new_desc);
}
//
// Tries to expand out a conditional statement. Returns whatever is expanded.
// Moves i to the proper place after the conditional has been expanded in the
// originating buffer.
BUFFER *expand_dynamic_conditional(BUFFER *desc,     PyObject *dict, 
				   PyObject *retval, const char *locale,
				   int *pos) {
  BUFFER *new_desc = newBuffer(bufferLength(desc)*2);
  BUFFER     *code = newBuffer(1); // code we have to evaluate
  int         j, i = *pos + 1;     // +1 to skip the current closing ]
  bool       match = PyObject_IsTrue(retval);

  while(TRUE) {
    // copy over all of our contents for the new desc and increment i
    while(*(bufferString(desc)+i) &&
	  !startswith(bufferString(desc)+i, "[else]") &&
	  !startswith(bufferString(desc)+i, "[elif ") &&
	  !startswith(bufferString(desc)+i, "[/if]")) {
      if(match == TRUE)
	bprintf(new_desc, "%c", *(bufferString(desc) + i));
      i++;
    }

    // did we terminate?
    if(match == TRUE || startswith(bufferString(desc)+i, "[/if]"))
      break;
    // we haven't had a match yet. Are we trying an else or elif?
    else if(startswith(bufferString(desc)+i, "[else]")) {
      match  = TRUE;
      i     += 6;
    }
    else if(startswith(bufferString(desc)+i, "[elif ")) {
      // skip the elif and spaces
      i += 6;
      while(isspace(*(bufferString(desc)+i)))
	i++;

      // find our end
      int end = next_letter_in(bufferString(desc) + i, ']');

      // make sure we have it
      if(end == -1)
	break;

      // copy everything between start and end, and format the code
      bufferClear(code);
      for(j = 0; j < end; j++)
	bprintf(code, "%c", *(bufferString(desc) + i + j));
      bufferReplace(code, "\n", "", TRUE);

      // skip i up to and beyond the ] marker
      i = i + end + 1;
      
      // evaluate the code
      PyObject *retval = eval_script(dict, bufferString(code), locale);
      match            = retval && PyObject_IsTrue(retval);

      // did we encounter an error?
      if(retval == NULL)
	break;
    }
  }

  // skip everything up to our closing [/if]
  while(*(bufferString(desc)+i) && !startswith(bufferString(desc)+i, "[/if]"))
    i++;
  if(startswith(bufferString(desc)+i, "[/if]"))
    i += 4; // put us at the closing ], not the end of the ending if block

  // garbage collection
  deleteBuffer(code);
 
  // return our expansion and move our i
  *pos = i;
  return new_desc;
}