⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lexert.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- c-basic-offset: 4 -*-/* * lexert.{cc,hh} -- configuration file parser for tools * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * Copyright (c) 2000 Mazu Networks, Inc. * Copyright (c) 2001-2003 International Computer Science Institute * Copyright (c) 2004-2007 Regents of the University of California * Copyright (c) 2008 Meraki, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "lexert.hh"#include "lexertinfo.hh"#include "routert.hh"#include <click/confparse.hh>#include <ctype.h>#include <stdlib.h>#include <string.h>static LexerTInfo *stub_lexinfo = 0;LexerT::LexerT(ErrorHandler *errh, bool ignore_line_directives)  : _data(0), _end(0), _pos(0), _lineno(1), _lset(0),    _ignore_line_directives(ignore_line_directives),    _tpos(0), _tfull(0), _router(0), _base_type_map(0), _errh(errh){    if (!_errh)	_errh = ErrorHandler::default_handler();    if (!stub_lexinfo)	stub_lexinfo = new LexerTInfo;    _lexinfo = stub_lexinfo;    clear();}LexerT::~LexerT(){    clear();    _router->unuse();    _lset->unref();}voidLexerT::reset(const String &data, const Vector<ArchiveElement> &archive, const String &filename){    clear();    _big_string = data;    _data = _pos = _big_string.begin();    _end = _big_string.end();    _original_filename = _filename = filename;    _lineno = 1;    _lset->new_line(0, _filename, _lineno);    // provide archive elements    for (int i = 0; i < archive.size(); i++)	if (archive[i].live() && archive[i].name != "config")	    _router->add_archive(archive[i]);}voidLexerT::clear(){    if (_router)	_router->unuse();    if (_lset)	_lset->unref();    _router = new RouterT();    _router->use();		// hold a reference to the router    _lset = new LandmarkSetT();    _big_string = "";    // _data was freed by _big_string    _data = 0;    _end = 0;    _pos = 0;    _filename = "";    _lineno = 0;    _tpos = 0;    _tfull = 0;    _base_type_map.clear();    _anonymous_offset = 0;    _anonymous_class_count = 0;}voidLexerT::set_lexinfo(LexerTInfo *li){    _lexinfo = (li ? li : stub_lexinfo);}// LEXING: LOWEST LEVELStringLexerT::remaining_text() const{    return _big_string.substring(_pos, _end);}voidLexerT::set_remaining_text(const String &s){    _big_string = s;    _data = _pos = s.begin();    _end = s.end();}const char *LexerT::skip_line(const char *s){  _lineno++;  for (; s < _end; s++)    if (*s == '\n')      return s + 1;    else if (*s == '\r') {      if (s + 1 < _end && s[1] == '\n')	return s + 2;      else	return s + 1;    }  _lineno--;  return s;}const char *LexerT::skip_slash_star(const char *s){  for (; s < _end; s++)    if (*s == '\n')      _lineno++;    else if (*s == '\r') {      if (s + 1 < _end && s[1] == '\n')	s++;      _lineno++;    } else if (*s == '*' && s + 1 < _end && s[1] == '/')      return s + 2;  return _end;}const char *LexerT::skip_backslash_angle(const char *s){  for (; s < _end; s++)    if (*s == '\n')      _lineno++;    else if (*s == '\r') {      if (s + 1 < _end && s[1] == '\n')	s++;      _lineno++;    } else if (*s == '/' && s + 1 < _end) {      if (s[1] == '/')	s = skip_line(s + 2) - 1;      else if (s[1] == '*')	s = skip_slash_star(s + 2) - 1;    } else if (*s == '>')      return s + 1;  return _end;}const char *LexerT::skip_quote(const char *s, char endc){  for (; s < _end; s++)    if (*s == '\n')      _lineno++;    else if (*s == '\r') {      if (s + 1 < _end && s[1] == '\n')	s++;      _lineno++;    } else if (*s == '\\' && endc == '\"' && s + 1 < _end) {      if (s[1] == '<')	s = skip_backslash_angle(s + 2) - 1;      else if (s[1] == '\"')	s++;    } else if (*s == endc)      return s + 1;  return _end;}const char *LexerT::process_line_directive(const char *s){  const char *first_pos = s;  for (s++; s < _end && (*s == ' ' || *s == '\t'); s++)    /* nada */;  if (s + 4 < _end && *s == 'l' && s[1] == 'i'      && s[2] == 'n' && s[3] == 'e'      && (s[4] == ' ' || s[4] == '\t')) {    for (s += 5; s < _end && (*s == ' ' || *s == '\t'); s++)      /* nada */;  }  if (s >= _end || !isdigit((unsigned char) *s)) {    // complain about bad directive    lerror(first_pos, s, "unknown preprocessor directive");    return skip_line(s);  } else if (_ignore_line_directives)    return skip_line(s);  // parse line number  for (_lineno = 0; s < _end && isdigit((unsigned char) *s); s++)    _lineno = _lineno * 10 + *s - '0';  _lineno--;			// account for extra line  for (; s < _end && (*s == ' ' || *s == '\t'); s++)    /* nada */;  if (s < _end && *s == '\"') {    // parse filename    const char *first_in_filename = s;    for (s++; s < _end && *s != '\"' && *s != '\n' && *s != '\r'; s++)      if (*s == '\\' && s + 1 < _end && s[1] != '\n' && s[1] != '\r')	s++;    _filename = cp_unquote(_big_string.substring(first_in_filename, s) + "\"");    // an empty filename means return to the input file's name    if (_filename == "")      _filename = _original_filename;  }  // reach end of line  for (; s < _end && *s != '\n' && *s != '\r'; s++)    /* nada */;  if (s + 1 < _end && *s == '\r' && s[1] == '\n')    s++;  return s;}LexemeLexerT::next_lexeme(){  const char *s = _pos;  while (true) {    while (s < _end && isspace((unsigned char) *s)) {      if (*s == '\n') {	_lineno++;	_lset->new_line(s + 1 - _big_string.begin(), _filename, _lineno);      } else if (*s == '\r') {	if (s + 1 < _end && s[1] == '\n')	  s++;	_lineno++;	_lset->new_line(s + 1 - _big_string.begin(), _filename, _lineno);      }      s++;    }    const char *opos = s;    if (s >= _end) {      _pos = _end;      return Lexeme(lexEOF, String(), _pos);    } else if (*s == '/' && s + 1 < _end) {      if (s[1] == '/')	s = skip_line(s + 2);      else if (s[1] == '*')	s = skip_slash_star(s + 2);      else	break;      _lexinfo->notify_comment(opos, s);    } else if (*s == '#' && (s == _data || s[-1] == '\n' || s[-1] == '\r')) {      s = process_line_directive(s);      _lexinfo->notify_line_directive(opos, s);    } else      break;  }  const char *word_pos = s;  // find length of current word  if (isalnum((unsigned char) *s) || *s == '_' || *s == '@') {   more_word_characters:    s++;    while (s < _end && (isalnum((unsigned char) *s) || *s == '_' || *s == '@'))      s++;    if (s + 1 < _end && *s == '/' && (isalnum((unsigned char) s[1]) || s[1] == '_' || s[1] == '@'))      goto more_word_characters;    _pos = s;    String word = _big_string.substring(word_pos, s);    if (word.equals("elementclass", 12)) {      _lexinfo->notify_keyword(word, word_pos, s);      return Lexeme(lexElementclass, word, word_pos);    } else if (word.equals("require", 7)) {      _lexinfo->notify_keyword(word, word_pos, s);      return Lexeme(lexRequire, word, word_pos);    } else if (word.equals("define", 6)) {      _lexinfo->notify_keyword(word, word_pos, s);      return Lexeme(lexDefine, word, word_pos);    } else      return Lexeme(lexIdent, word, word_pos);  }  // check for variable  if (*s == '$') {    s++;    while (s < _end && (isalnum((unsigned char) *s) || *s == '_'))      s++;    if (s > word_pos + 1) {      _pos = s;      return Lexeme(lexVariable, _big_string.substring(word_pos + 1, s), word_pos);    } else      s--;  }  if (s + 1 < _end) {    if (*s == '-' && s[1] == '>') {      _pos = s + 2;      return Lexeme(lexArrow, _big_string.substring(s, s + 2), word_pos);    } else if (*s == ':' && s[1] == ':') {      _pos = s + 2;      return Lexeme(lex2Colon, _big_string.substring(s, s + 2), word_pos);    } else if (*s == '|' && s[1] == '|') {      _pos = s + 2;      return Lexeme(lex2Bar, _big_string.substring(s, s + 2), word_pos);    }  }  if (s + 2 < _end && *s == '.' && s[1] == '.' && s[2] == '.') {    _pos = s + 3;    return Lexeme(lex3Dot, _big_string.substring(s, s + 3), word_pos);  }  _pos = s + 1;  return Lexeme(*s, _big_string.substring(s, s + 1), word_pos);}LexemeLexerT::lex_config(){  const char *config_pos = _pos;  const char *s = _pos;  unsigned paren_depth = 1;  for (; s < _end; s++)    if (*s == '(')      paren_depth++;    else if (*s == ')') {      paren_depth--;      if (!paren_depth)	break;    } else if (*s == '\n') {      _lineno++;      _lset->new_line(s + 1 - _big_string.begin(), _filename, _lineno);    } else if (*s == '\r') {      if (s + 1 < _end && s[1] == '\n')	s++;      _lineno++;      _lset->new_line(s + 1 - _big_string.begin(), _filename, _lineno);    } else if (*s == '/' && s + 1 < _end) {      if (s[1] == '/')	s = skip_line(s + 2) - 1;      else if (s[1] == '*')	s = skip_slash_star(s + 2) - 1;    } else if (*s == '\'' || *s == '\"')      s = skip_quote(s + 1, *s) - 1;    else if (*s == '\\' && s + 1 < _end && s[1] == '<')      s = skip_backslash_angle(s + 2) - 1;  _pos = s;  _lexinfo->notify_config_string(config_pos, s);  return Lexeme(lexConfig, _big_string.substring(config_pos, s),		config_pos);}StringLexerT::lexeme_string(int kind){    char buf[14];    if (kind == lexIdent)	return String::make_stable("identifier", 10);    else if (kind == lexVariable)	return String::make_stable("variable", 8);    else if (kind == lexArrow)	return String::make_stable("'->'", 4);    else if (kind == lex2Colon)	return String::make_stable("'::'", 4);    else if (kind == lex2Bar)	return String::make_stable("'||'", 4);    else if (kind == lex3Dot)	return String::make_stable("'...'", 5);    else if (kind == lexElementclass)	return String::make_stable("'elementclass'", 14);    else if (kind == lexRequire)	return String::make_stable("'require'", 9);    else if (kind == lexDefine)	return String::make_stable("'define'", 8);    else if (kind >= 32 && kind < 127) {	sprintf(buf, "'%c'", kind);	return buf;    } else {	sprintf(buf, "'\\%03d'", kind);	return buf;    }}// LEXING: MIDDLE LEVEL (WITH PUSHBACK)const Lexeme &LexerT::lex(){  int p = _tpos;  if (_tpos == _tfull) {    _tcircle[p] = next_lexeme();    _tfull = (_tfull + 1) % TCIRCLE_SIZE;  }  _tpos = (_tpos + 1) % TCIRCLE_SIZE;  return _tcircle[p];}voidLexerT::unlex(const Lexeme &t){  _tpos = (_tpos + TCIRCLE_SIZE - 1) % TCIRCLE_SIZE;  _tcircle[_tpos] = t;  assert(_tfull != _tpos);}boolLexerT::expect(int kind, bool report_error){    // Never adds anything to '_tcircle'. This requires a nonobvious    // implementation.    if (_tpos != _tfull) {	if (_tcircle[_tpos].is(kind)) {	    _tpos = (_tpos + 1) % TCIRCLE_SIZE;	    return true;	}	if (report_error)	    lerror(_tcircle[_tpos], "expected %s", lexeme_string(kind).c_str());    } else {	String old_filename = _filename;	unsigned old_lineno = _lineno;	const char *old_pos = _pos;	if (next_lexeme().is(kind))	    return true;	_filename = old_filename;	_lineno = old_lineno;	if (report_error)	    lerror(old_pos, _pos, "expected %s", lexeme_string(kind).c_str());	_pos = old_pos;    }    return false;}const char *LexerT::next_pos() const{    if (_tpos != _tfull)	return _tcircle[_tpos].pos1();    else	return _pos;}// ERRORSStringLexerT::landmark() const{    if (_filename && _filename.back() != ':' && !isspace((unsigned char) _filename.back()))	return _filename + ":" + String(_lineno);    else	return _filename + String(_lineno);}voidLexerT::vlerror(const char *pos1, const char *pos2, const String &lm, const char *fmt, va_list val){    String text = _errh->vformat(fmt, val);    _lexinfo->notify_error(text, pos1, pos2);    _errh->xmessage(lm, ErrorHandler::e_error, text);}intLexerT::lerror(const char *pos1, const char *pos2, const char *format, ...){    va_list val;    va_start(val, format);    vlerror(pos1, pos2, landmark(), format, val);    va_end(val);    return -1;}intLexerT::lerror(const Lexeme &t, const char *format, ...){    va_list val;    va_start(val, format);    vlerror(t.pos1(), t.pos2(), landmark(), format, val);    va_end(val);    return -1;}// ELEMENT TYPESElementClassT *LexerT::element_type(const Lexeme &t) const{    assert(t.is(lexIdent));    String name = t.string();    ElementClassT *type = _router->declared_type(name);    if (!type)	type = _base_type_map[name];    if (type)	_lexinfo->notify_class_reference(type, t.pos1(), t.pos2());    return type;}ElementClassT *LexerT::force_element_type(const Lexeme &t){    assert(t.is(lexIdent));    String name = t.string();    ElementClassT *type = _router->declared_type(name);    if (!type)	type = _base_type_map.get(name);    if (!type) {	if (_router->eindex(name) >= 0)	    lerror(t, "%<%s%> was previously used as an element name", name.c_str());	type = ElementClassT::base_type(name);	_base_type_map.set(name, type);    }    _lexinfo->notify_class_reference(type, t.pos1(), t.pos2());    return type;}// ELEMENTSStringLexerT::anon_element_name(const String &class_name) const{    int anonymizer = _router->nelements() - _anonymous_offset + 1;    return ";" + class_name + "@" + String(anonymizer);}intLexerT::make_element(String name, const Lexeme &location, const char *decl_pos2,		     ElementClassT *type, const String &conf){    // check 'name' for validity    for (int i = 0; i < name.length(); i++) {	bool ok = false;	for (; i < name.length() && name[i] != '/'; i++)	    if (!isdigit((unsigned char) name[i]))		ok = true;	if (!ok) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -