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; }