#include <phantasmal/log.h> #include <phantasmal/lpc_names.h> #include <limits.h> #include <type.h> #include <trace.h> string parser; static void create(varargs int clone) { parser = read_file("/usr/common/obj/unq_parser.dpd", 0, MAX_STRING_SIZE - 1); if(strlen(parser) > MAX_STRING_SIZE - 3) { error("Parser description too big loading file in unq_parser::create!"); } } private mixed do_backslash_escaping(mixed tmp); mixed* basic_unq_parse(string block) { mixed* tmp; catch { tmp = parse_string(parser, block); /* -- Tentatively changed this to just log if tmp == nil. */ if (tmp == nil) { LOGD->write_syslog("Warning: parse_string() returned nil " + "in basic_unq_parse()", LOG_WARN); return nil; } } : { if (block == nil) { LOGD->write_syslog("Error: no block passed to basic_unq_parse", LOG_WARN); } else { LOGD->write_syslog("Error parsing block: " + block, LOG_WARN); } return nil; } tmp = do_backslash_escaping(tmp); return tmp; } mixed* unq_parse_with_dtd(string block, object dtd, varargs string filename) { mixed* unq; mixed* struct; unq = basic_unq_parse(block); if(!unq) { if(filename) { error ("Can't tokenize/match file '" + filename + "' as UNQ in UNQ_PARSER::unq_parse_with_dtd!"); } else { error ("Can't tokenize/match as UNQ in UNQ_PARSER::unq_parse_with_dtd!"); } } struct = dtd->parse_to_dtd(unq); if(!struct) { if(filename) { error("*** UNQ from file '" + filename + "' doesn't fit DTD in unq_parse_with_dtd:\n" + dtd->get_parse_error_stack()); } else { error("*** UNQ input doesn't fit DTD in unq_parse_with_dtd:\n" + dtd->get_parse_error_stack()); } } return struct; } private string backslash_escape_string(string tmp) { string ret; int ctr; if(!tmp) return nil; ret = ""; for(ctr = 0; ctr < strlen(tmp); ctr++) { if(tmp[ctr] == '\\') { ctr++; /* Backslash at end of input... */ if(ctr >= strlen(tmp)) { ret += "\\"; break; } if(tmp[ctr] == '\\' || tmp[ctr] == '~' || tmp[ctr] == '{' || tmp[ctr] == '}') { ret += tmp[ctr..ctr]; continue; } if(tmp[ctr] == 'n') { ret += "\n"; continue; } if(tmp[ctr] == 'b') { ret += "\b"; continue; } if(tmp[ctr] == 't') { ret += "\t"; continue; } if(tmp[ctr] == 'r') { ret += "\r"; continue; } if(tmp[ctr] == 'a') { ret += "\a"; continue; } if(tmp[ctr] == 'f') { ret += "\f"; continue; } if(tmp[ctr] == 'v') { ret += "\v"; continue; } } else { ret += tmp[ctr..ctr]; } } return ret; } private mixed do_backslash_escaping(mixed tmp) { int ctr; if(tmp == nil) return nil; if(typeof(tmp) == T_STRING) return backslash_escape_string(tmp); if(typeof(tmp) == T_ARRAY) { for(ctr = 0; ctr < sizeof(tmp); ctr++) { tmp[ctr] = do_backslash_escaping(tmp[ctr]); } return tmp; } error("Unrecognized type " + typeof(tmp) + " in do_backslash_escaping!"); } mixed* trim_empty_tags(mixed* unq) { mixed* ret; int ctr; if(!unq) return unq; ret = ({ }); if(sizeof(unq) % 2) error("Odd-sized UNQ array passed to trim_empty_tags: " + STRINGD->mixed_sprint(unq)); for(ctr = 0; ctr < sizeof(unq); ctr += 2) { if((unq[ctr] && !STRINGD->is_whitespace(unq[ctr])) || typeof(unq[ctr + 1]) == T_ARRAY || !STRINGD->is_whitespace(unq[ctr + 1])) { ret += ({ unq[ctr], unq[ctr + 1] }); } } return ret; } /*** Functions callable by parse_string during parsing... ***/ /* From: unq_string: substring ? simple_anon_tag */ static mixed* simple_anon_tag(mixed* tokens) { return ({ nil, tokens[0] }); } /* From: unq_tag: '{' unq_string '}' ? anon_tag */ static mixed* anon_tag(mixed* tokens) { mixed* tag_val; int size; size = sizeof(tokens); if(size < 3) { error("Incorrect-sized array passed to anon_tag!"); } else if (size == 3) { error("Should never happen?"); return ({ "", tokens[1] }); } else if (size == 4 && tokens[2] == nil) { /* Previous was string returned by simple_anon_tag */ return ({ "", tokens[2] }); } else { tag_val = tokens[1..(size - 2)]; return ({ "", tag_val }); } } /* From: unq_tag: '{' '}' ? empty_anon_tag */ static mixed* empty_anon_tag(mixed* tokens) { return ({ "", ({ }) }); } /* From: unq_tag: '~' regularstring '{' '}' ? empty_named_tag */ static mixed* empty_named_tag(mixed* tokens) { return ({ tokens[1], ({ }) }); } /* From: unq_tag: '~' regularstring '{' unq_string '}' ? named_tag */ static mixed* named_tag(mixed* tokens) { string tag_name; mixed* tag_val; int size; size = sizeof(tokens); tag_name = tokens[1]; if(size < 5) { error("Incorrect-sized array passed to named_tag!"); } else if(size == 5) { error("Should never happen? [2]"); return ({ tag_name, tokens[3] }); } else if (size == 6 && tokens[3] == nil) { /* Previous was string returned by simple_anon_tag */ return ({ tag_name, tokens[4] }); } else { tag_val = tokens[3..(size-2)]; return ({ tag_name, tag_val }); } } /* From: substring: substring regularstring ? concat_strings */ static mixed* concat_strings(mixed* tokens) { int ctr; string tmp; tmp = ""; for(ctr = 0; ctr < sizeof(tokens); ctr++) { if(typeof(tokens[ctr] == T_STRING)) { tmp += tokens[ctr]; } else { error("Unknown type concatenating strings"); } } return ({ tmp }); } /* From: unq_string: unq_string substring ? concat_ustring_string */ static mixed* concat_ustring_string(mixed* tokens) { string tmp; int len; len = sizeof(tokens); tmp = tokens[len - 1]; return tokens[0..(len - 2)] + ({ nil, tmp }); } static mixed* package_args(mixed* tokens) { return ({ tokens }); }