static NumType readnum (ParseState *ps) { char m[128], c; int p = 0; ps->pos--; while (isdigit(c = curchar(ps))) { m[p++] = c; ps->pos++; } m[p] = 0; return castnum(m); }
/* Return next comma-delimited argument, but do not cross a close-brace boundary. Clean up whitespace, too. If EXPAND is nonzero, replace the entire brace-delimited argument list with its expansion before looking for the next comma. */ char * get_xref_token (int expand) { char *string = 0; if (docbook) xml_in_xref_token = 1; if (expand) { int old_offset = input_text_offset; int old_lineno = line_number; get_until_in_braces ("}", &string); if (curchar () == '}') /* as opposed to end of text */ input_text_offset++; if (input_text_offset > old_offset) { int limit = input_text_offset; input_text_offset = old_offset; line_number = old_lineno; only_macro_expansion++; replace_with_expansion (input_text_offset, &limit); only_macro_expansion--; } free (string); } get_until_in_braces (",", &string); if (curchar () == ',') input_text_offset++; fix_whitespace (string); if (docbook) xml_in_xref_token = 0; return string; }
static char *readid (ParseState *ps) { char s[MAX_ID_LEN], c; char *r; int p = 0; ps->pos--; while (isidstr(c = curchar(ps))) { s[p++] = c; ps->pos++; } s[p] = 0; r = (char*) malloc(p+1); strcpy(r, s); return r; }
static char *readstr (ParseState *ps) { char s[MAX_STR_LEN], c; char *r; int p = 0; while ((c = curchar(ps)) != '"') { s[p++] = c; ps->pos++; } ps->pos++; /* eat '"' */ s[p] = 0; r = (char*) malloc(p+1); strcpy(r, s); return r; }
Token cp_token (ParseState *ps) { for (; curchar(ps); ) { char c = ps->str[ps->pos++]; if (c == ',') return deftoken(T_COMMA); if (c == '.') return deftoken(T_DOT); if (isdigit(c)) { NumType num = readnum(ps); return numtoken(num); } if (c == '"') { char *s = readstr(ps); return strtoken(s); } if (isidstr(c)) { char *s = readid(ps); return idtoken(s); } } return deftoken(T_EOF); }
int Re::CompileS(const char *ptr, int caseflag, int &errindex) { expr=ptr; origexpr=expr; init(); nextid=0; first=0; isCaret=0; isDummy=0; casesensitive=caseflag; matchFull=0; int rc=0; try { RegExpNode **p=CompileOrClause(&first); if (*expr == '!') { int dummy; ++expr; if ((chainedre=new Re) == 0) outofmem(); if ( chainedre->CompileS(expr, caseflag, dummy) < 0) { expr += dummy; throw -1; } chainedre->prevre=this; if (VerboseLevel() > 7) merr.write("\n*** CHAINED TO ***\n"); } else if (curchar()) throw -1; final=*p=allocnode(); final->thechar=REFINAL;
/* Handle a "footnote". footnote *{this is a footnote} where "*" is the (optional) marker character for this note. */ void cm_footnote (void) { char *marker; char *note; get_until ("{", &marker); canon_white (marker); if (macro_expansion_output_stream && !executing_string) append_to_expansion_output (input_text_offset + 1); /* include the { */ /* Read the argument in braces. */ if (curchar () != '{') { line_error (_("`%c%s' needs an argument `{...}', not just `%s'"), COMMAND_PREFIX, command, marker); free (marker); return; } else { int len; int braces = 1; int loc = ++input_text_offset; while (braces) { if (loc == input_text_length) { line_error (_("No closing brace for footnote `%s'"), marker); return; } if (input_text[loc] == '{') braces++; else if (input_text[loc] == '}') braces--; else if (input_text[loc] == '\n') line_number++; loc++; } len = (loc - input_text_offset) - 1; note = xmalloc (len + 1); memcpy (note, &input_text[input_text_offset], len); note[len] = 0; input_text_offset = loc; } /* Must write the macro-expanded argument to the macro expansion output stream. This is like the case in index_add_arg. */ if (macro_expansion_output_stream && !executing_string) { /* Calling me_execute_string on a lone } provokes an error, since as far as the reader knows there is no matching {. We wrote the { above in the call to append_to_expansion_output. */ me_execute_string_keep_state (note, "}"); } if (!current_node || !*current_node) { line_error (_("Footnote defined without parent node")); free (marker); free (note); return; } /* output_pending_notes is non-reentrant (it uses a global data structure pending_notes, which it frees before it returns), and TeX doesn't grok footnotes inside footnotes anyway. Disallow that. */ if (already_outputting_pending_notes) { line_error (_("Footnotes inside footnotes are not allowed")); free (marker); free (note); return; } if (!*marker) { free (marker); if (number_footnotes) { marker = xmalloc (10); sprintf (marker, "%d", current_footnote_number); } else marker = xstrdup ("*"); } if (xml) xml_insert_footnote (note); else { remember_note (marker, note); /* fixme: html: footnote processing needs work; we currently ignore the style requested; we could clash with a node name of the form `fn-<n>', though that's unlikely. */ if (html) { /* Hyperlink also serves as an anchor (mnemonic: fnd is footnote definition.) */ add_html_elt ("<a rel=\"footnote\" href="); add_word_args ("\"#fn-%d\" name=\"fnd-%d\"><sup>%s</sup></a>", current_footnote_number, current_footnote_number, marker); } else /* Your method should at least insert MARKER. */ switch (footnote_style) { case separate_node: add_word_args ("(%s)", marker); execute_string (" (*note %s-Footnote-%d::)", current_node, current_footnote_number); if (first_footnote_this_node) { char *temp_string, *expanded_ref; temp_string = xmalloc (strlen (current_node) + strlen ("-Footnotes") + 1); strcpy (temp_string, current_node); strcat (temp_string, "-Footnotes"); expanded_ref = expansion (temp_string, 0); remember_node_reference (expanded_ref, line_number, followed_reference); free (temp_string); free (expanded_ref); first_footnote_this_node = 0; } break; case end_node: add_word_args ("(%s)", marker); break; default: break; } current_footnote_number++; } free (marker); free (note); }
void Lexer::token2(Token &t) { int c; t.Type(Token::error); // Eat whitespace & comments for (;;) { while ((c=curchar()) >= 0 && isspace(c)) { nextchar(); if (c == '\n' || c == '\r') // Treat as semicolon { t.Type(Token::semicolon); return; } } if (c == '\\') // Continued line? { nextchar(); c=curchar(); if (c < 0 || !isspace(c)) { return; // Error } while (c >= 0 && c != '\n') { nextchar(); c=curchar(); } if (c == '\n') nextchar(); continue; } if (c != '#') break; while ( (c=nextchar()) >= 0 && c != '\n') ; if (c == '\n') { t.Type(Token::semicolon); return; } } if (c < 0) { t.Type(lasttokentype == Token::semicolon ? Token::eof : Token::semicolon); return; } // String, quoted by ", ', or ` Buffer &pattern=t.String(); pattern.reset(); if (c == '\'' || c == '"' || c == '`') { Token::tokentype ttype=Token::qstring; int quote_char=c; if (c == '\'') ttype=Token::sqstring; if (c == '`') ttype=Token::btstring; nextchar(); int q; // Grab string until matching close is found. while ((q=curchar()) != c) { if (q < 0 || q == '\n' || q == '\r') { missquote: error("maildrop: Missing ', \", or `.\n"); return; } // Backslash escape if (q != '\\') { nextchar(); pattern.push(q); continue; } nextchar(); // Look what's after the backslash. // If it's whitespace, we may have a continuation // on the next line. int qq=curchar(); if (qq < 0) goto missquote; if (!isspace(qq) && qq != '\r' && qq != '\n') { if (qq != quote_char && qq != '\\') pattern.push('\\'); pattern.push(qq); nextchar(); continue; } // If it's not a continuation, we need to dutifully // save the characters as the string. So, save the // current length of the string, and backtrack if // necessary. int l=pattern.Length(); pattern.push('\\'); // Collect all whitespace after the backslash, // not including newline characters. while ((q=curchar()) >= 0 && isspace(q) && q != '\r' && q != '\n') { pattern.push(q); nextchar(); } if (q < 0) goto missquote; // If the next character is a newline char, or // a comment, we have a continuation. if (q != '#' && q != '\r' && q != '\n') continue; pattern.Length(l); // Discard padding while (q != '\n') { if (q < 0) goto missquote; nextchar(); q=curchar(); } // Discard all whitespace at the beginning of the // next line. nextchar(); while ( (q=curchar()) >= 0 && isspace(q)) nextchar(); if (q < 0) goto missquote; } nextchar(); t.Type(ttype); return; } // A pattern - "/", then arbitrary text, terminated by "/" if (c == '/' && lasttokentype != Token::equals && lasttokentype != Token::tokento && lasttokentype != Token::tokencc) { pattern.push(c); nextchar(); c=curchar(); if (c == '\r' || c == '\n' || c < 0 || isspace(c)) { t.Type(Token::divi); return; } while ( (c=curchar()) != '/') { if (c < 0 || c == '\r' || c == '\n') return; // Error token - let parser throw // an error if (c == '\\') { pattern.push(c); nextchar(); c=curchar(); if (c < 0 || c == '\r' || c == '\n') return; } pattern.push(c); nextchar(); } pattern.push(c); nextchar(); if ((c=curchar()) == ':') { pattern.push(c); nextchar(); while ( (c=curchar()) >= 0 && (isalnum(c) || c == '-' || c == '+' || c == '.' || c == ',')) { pattern.push(c); nextchar(); } } t.Type(Token::regexpr); return; } // Letters, digits, -, ., :, /, can be in an unquoted string #define ISUNQSTRING(x) (x >= 0 && (isalnum(x) || (x) == '_' || x == '-' || \ (x) == '@' || (x) == '.' || x == ':' || x == SLASH_CHAR || x == '$' || \ x == '{' || x == '}')) // Unquoted string may not begin with {} #define ISLUNQSTRING(x) (x >= 0 && (isalnum(x) || (x) == '_' || x == '-' || \ (x) == '@' || (x) == '.' || x == ':' || x == SLASH_CHAR || x == '$')) if (ISLUNQSTRING(c)) { do { nextchar(); pattern.push(c); c=curchar(); } while ( ISUNQSTRING(c) ); while ( c >= 0 && isspace(c) && c != '\r' && c != '\n') { nextchar(); c=curchar(); } if (pattern.Length() == 2) { int n= ((int)(unsigned char)*(const char *)pattern) << 8 | (unsigned char)((const char *)pattern)[1]; switch (n) { case (('l' << 8) | 't'): t.Type(Token::slt); return; case (('l' << 8) | 'e'): t.Type(Token::sle); return; case (('g' << 8) | 't'): t.Type(Token::sgt); return; case (('g' << 8) | 'e'): t.Type(Token::sge); return; case (('e' << 8) | 'q'): t.Type(Token::seq); return; case (('n' << 8) | 'e'): t.Type(Token::sne); return; case (('t' << 8) | 'o'): t.Type(Token::tokento); return; case (('c' << 8) | 'c'): t.Type(Token::tokencc); return; } } if (pattern == "length") t.Type(Token::length); else if (pattern == "substr") t.Type(Token::substr); else if (pattern == "if") t.Type(Token::tokenif); else if (pattern == "elsif") t.Type(Token::tokenelsif); else if (pattern == "else") t.Type(Token::tokenelse); else if (pattern == "while") t.Type(Token::tokenwhile); else if (pattern == "exception") t.Type(Token::exception); else if (pattern == "echo") t.Type(Token::echo); else if (pattern == "xfilter") t.Type(Token::tokenxfilter); else if (pattern == "dotlock") t.Type(Token::dotlock); else if (pattern == "flock") t.Type(Token::flock); else if (pattern == "logfile") t.Type(Token::logfile); else if (pattern == "log") t.Type(Token::log); else if (pattern == "include") t.Type(Token::include); else if (pattern == "exit") t.Type(Token::exit); else if (pattern == "foreach") t.Type(Token::foreach); else if (pattern == "getaddr") t.Type(Token::getaddr); else if (pattern == "lookup") t.Type(Token::lookup); else if (pattern == "escape") t.Type(Token::escape); else if (pattern == "tolower") t.Type(Token::to_lower); else if (pattern == "toupper") t.Type(Token::to_upper); else if (pattern == "hasaddr") t.Type(Token::hasaddr); else if (pattern == "gdbmopen") t.Type(Token::gdbmopen); else if (pattern == "gdbmclose") t.Type(Token::gdbmclose); else if (pattern == "gdbmfetch") t.Type(Token::gdbmfetch); else if (pattern == "gdbmstore") t.Type(Token::gdbmstore); else if (pattern == "time") t.Type(Token::timetoken); else if (pattern == "import") t.Type(Token::importtoken); else if (pattern == "-") // Hack t.Type(Token::minus); else if (pattern == "unset") t.Type(Token::unset); else t.Type(Token::qstring); return; } switch (c) { case '&': nextchar(); if ( curchar() == '&') { t.Type(Token::land); nextchar(); return; } t.Type(Token::band); return; case '|': nextchar(); if ( curchar() == '|') { t.Type(Token::lor); nextchar(); return; } t.Type(Token::bor); return; case '{': t.Type(Token::lbrace); nextchar(); return; case '}': t.Type(Token::rbrace); nextchar(); return; case '(': t.Type(Token::lparen); nextchar(); return; case ')': t.Type(Token::rparen); nextchar(); return; case ';': t.Type(Token::semicolon); nextchar(); return; case '+': t.Type(Token::plus); nextchar(); return; case '*': t.Type(Token::mult); nextchar(); return; case '~': t.Type(Token::bitwisenot); nextchar(); return; case '<': nextchar(); if ( curchar() == '=') { nextchar(); t.Type(Token::le); return; } t.Type(Token::lt); return; case '>': nextchar(); if ( curchar() == '=') { nextchar(); t.Type(Token::ge); return; } t.Type(Token::gt); return; case '=': nextchar(); if ( curchar() == '~') { nextchar(); t.Type(Token::strregexp); return; } if ( curchar() != '=') { t.Type(Token::equals); return; } nextchar(); t.Type(Token::eq); return; case '!': nextchar(); if ( curchar() != '=') { t.Type(Token::logicalnot); return; } nextchar(); t.Type(Token::ne); return; case ',': nextchar(); t.Type(Token::comma); return; } nextchar(); // Let the parser throw an error. }