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

📄 from_l2.cpp

📁 vxworks的系统故障诊断项目
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/***
 *** See the file "mba/disclaimers-and-notices-L2.txt" for
 *** information on usage and redistribution of this file,
 *** and for a DISCLAIMER OF ALL WARRANTIES.
 ***/

/* $Id: from_l2.cpp,v 1.1.1.1 2006/10/09 06:58:18 shao Exp $ */

#include <errno.h> // errno, strerror
#include <readers/from_l2.h>
#include <readers/transition.h>

#define tostream(expr) expr

// The do-while(0) is the only portable way to block.
#ifdef ENABLE_L2_VERBOSE
#  define verbose(expr) do { if (isVerbose()) { tostream(expr); } } while(0)
#else
#  define verbose(expr)
#endif

/***************************************************************************
        Store a dictionary.  For now, it's very small and could probably
        just be an if/else if/...  ; but this way I argue it's easier to
        read the code, update, and make sure the abbreviations don't clash
 ***************************************************************************/

/// The sections of a model file in L2 format.

enum Section {
    NO_SECTION,
    CLAUSES,
    COMMANDS,
    ENUMS,
    MODES,
    OBSERVED,
    PROPOSITIONS,
    TRANSITIONS,
    VARIABLES,
    INITIAL,
    BACKGROUND
};


/// A (section name string, enum) pair used for mapping.

struct SectionName {
    const char *name;
    enum Section sect;
};


/// A map from section name strings to Section enum values.

SectionName section_names[] = {
    // abbreviated
    { "b",              BACKGROUND      },
    { "cl",             CLAUSES         },
    { "cm",             COMMANDS        },
    { "e",              ENUMS           },
    { "m",              MODES           },
    { "o",              OBSERVED        },
    { "p",              PROPOSITIONS    },
    { "t",              TRANSITIONS     },
    { "v",              VARIABLES       },
    { "i",              INITIAL         },

#ifdef ENABLE_L2_DEBUG_SECTIONS
    // full name
    { "background",     BACKGROUND      },
    { "clauses",        CLAUSES         },
    { "commands",       COMMANDS        },
    { "enums",          ENUMS           },
    { "modes",          MODES           },
    { "observed",       OBSERVED        },
    { "propositions",   PROPOSITIONS    },
    { "transitions",    TRANSITIONS     },
    { "variables",      VARIABLES       },
    { "initial",        INITIAL         }
#endif
};


/// The number of sections in a model file in L2 format.

const size_t num_sections = sizeof(section_names)/sizeof(SectionName);


/**
 * Map a section name string onto its Section enum.
 * \internal this is not a member function.
 * \param the section name string
 * \return the corresponding Section enum
 */

Section find_section(const char *name) {
    for(size_t i=0; i<num_sections; i++) {
        if(!strcmp(name, section_names[i].name))
            return section_names[i].sect;
    }
    return NO_SECTION;
}



/***************************************************************************
        Destructor.
 ***************************************************************************/

from_l2::~from_l2() {
    if(the_file) fclose(the_file);
}


/***************************************************************************
        Error handling and reporting.
 ***************************************************************************/

#ifdef ENABLE_L2_VERBOSE
void from_l2::print_parse_error() {
    _STD_ cerr <<"Parse error at line " << line_number
	      << ", index " << index << _STD_ endl
	      << line << _STD_ endl;
    for(size_t i=0; i<index; i++) { _STD_ cerr << ' '; }
    _STD_ cerr << "^\n";
}
#else
#  define print_parse_error()
#endif


/// Check that a section was parsed.
/// Argument 1 is typically a call to was_X_parsed().
/// Argument 2 is what we expect (true for prereqs, false
///     for the section we're now parsing).
/// Argument 3 is the name of the section we're checking.

bool from_l2::check_parsed(bool condition, bool expected, const char *msg) {
    if(condition == expected) {
        return true;
    } else {
        print_parse_error();
        if (condition) {
	  tostream(_STD_ cerr << "Section " << msg
		   << " has already been parsed.\n");
        } else {
	  tostream(_STD_ cerr<< "Prerequisite " << msg
		   << " not yet parsed.\n");
	}
        return false;
    }
}

/***************************************************************************
        Lexing functions
 ***************************************************************************/

/**
 * Is string[index] a word separator/terminator?
 * White space and the string terminator are word boundaries.
 * \internal This is not a member function.
 * \param string the string that may contain words
 * \param index the character within string that is being tested
 * \return whether string[index] is a word separator or terminator.
 */

static bool str_at_word_boundary(const char *string, size_t index) {
    switch(string[index]) {
        case ' ':
        case '\n':
        case '\t':
        case '\0':
            return true;
        default:
            return false;
    }
}


/**
 * Copy the next word from string to into and update the index to point to the
 * next boundary
 * \internal this is not a member function.
 * \param into the next word from string is copied into this out parameter
 * \param the current character within string; this out parameter is advanced
 * \param the string that may contain words
 */

static void str_get_next_word(char *into, size_t& index, const char *string) {
    size_t i=0;
    while(!str_at_word_boundary(string, index+i)) {
        into[i] = string[index+i];
        i++;
    }
    into[i] = 0;
    index += i;
}


/// Read a line from the file; leave the results in 'line'

bool from_l2::readline() {
    ++line_number;
    index = 0;
    char *ret = fgets(line, L2_MODEL_FILE_MAX_LINE_SIZE, the_file);
    // check for EOF
    if(!ret) return false;

    // check for overflow; also, get rid of the newline: it's annoying
    size_t len = strlen(line);

    // empty line?  I don't think this should ever actually happen.
    if(len == 0) return true;

    if(line[len-1] != '\n') {
        print_parse_error();
        tostream(_STD_ cerr
		 << "Max line length ("
		 << (L2_MODEL_FILE_MAX_LINE_SIZE - 1)
		 << ") exceeded."
		 << _STD_ endl
		 << "Re-compile with a larger value for "
		 << "L2_MODEL_FILE_MAX_LINE_SIZE"
		 << _STD_ endl);
        return false;
    }

    // kill the \n, thus reducing line length by one
    line[len-1] = 0;
    return true;
}


/// Intuitively: read the next integer.
/// More formally:
/// Read the substring of the line that starts at index
/// and ends at the next whitespace, newline, or the end
/// of the string.  Interpret that substring as a positive
/// integer.  Return the integer and set the index to point
/// to the next whitespace etc.
/// Currently we use base 10; the code is easy to modify to
/// other bases.
/// Argument: the name of the thing we're parsing, used for
/// debugging.
/// Errors: return a negative value (other than L2rTransition::ANY_MODE).
/// This occurs if:
///     the integer overflows
///     there are non-digits in the substring
/// If `acceptStar' is on, return L2rTransiton::ANY_MODE if we read a '*'

int from_l2::read_integer(const char *msg, bool acceptStar) {
    size_t retval = 0;
    unsigned index0 = index;
    // loop ends at line[index] in { ' ', '\n', '\t', '\0' },
    // or a non-digit line[index]; i's easier to write that as a switch
    // statement.
    // The line is guaranteed to end, so the loop is too.
    if(acceptStar && line[index] == '*') {
        index++;
        return L2rTransition::ANY_MODE;
    }
    for(;;++index) {

        if(line[index] >= '0' && line[index] <= '9') {
            retval *= 10;
            retval += line[index]-'0';
            continue;
        }
        // for base > 10, use line[index] >= 'a' && line[index] <= 'f'
        // or whatever; and change the *= above.

        if(str_at_word_boundary(line, index)) {
            if(index0==index) {
                print_parse_error();
                tostream(_STD_ cerr<< "No integer found while reading "
			<< msg << _STD_ endl);
                return NOT_AN_INTEGER;
            }
            return retval;
        } else {
            // printf("Non-digit character `%c' at index %d in:\n"
            //        "%s", ...);
            print_parse_error();
            tostream(_STD_ cerr<< "While reading " << msg << _STD_ endl);
            return NOT_AN_INTEGER;
        }

        // can't get here; we do a continue or return
        assert(0);
    }
    // can't get here; the loop runs until a return
    assert(0);
}


/// Skip the word boundary that index is currently in.
/// This advances index to the next non-(word boundary) character,
/// or returns 'false' if we're at the end of the line.
/// If print_error is true, call print_parse_error if we return
/// false.

bool from_l2::skip_word_boundary(bool print_error) {
    while(str_at_word_boundary(line, index)) {
        if(line[index] == '\0') {
            if(print_error)
                print_parse_error();
            return false;
        }
        index++;
    }
    return true;
}

/***************************************************************************
        The top-level function
 ***************************************************************************/

/// The top-level method.

bool from_l2::read() {
    // make sure read() hasn't already been called
    assert(!the_file);

    // open the file
    the_file = fopen(filename_.c_str(), "r");
    if(!the_file) {
#ifndef _MSC_VER
        tostream(_STD_ cerr<< "from_l2: error opening `" << filename_ << "'\n"
		 << strerror(errno) << _STD_ endl);
#else
        // Under Visual C++ we have not quite figured out the linking
        // to get errno to work.
        tostream(_STD_ cerr<< "from_l2: error opening `" << filename_ << "'\n"
		 << _STD_ endl);
#endif
        return false;
    }

    // first line in the file is a magic cookie to make sure it works.
    readline();
    if(0 != strcmp(line, L2_READER_MAGIC)) {
        tostream(_STD_ cerr<< "from_l2: error opening `" << filename_ << "':\n"
            << "Magic cookie `" << line << "' doesn't match expected " <<
            L2_READER_MAGIC << _STD_ endl);
        return false;
    }


    // the main loop; read a line, parse the section name,
    // pass it to the appropriate function
    while(readline()) {
        bool has_debug_info = false;
        char *linep = line;

        // skip empty lines
        if(line[0]=='\0') continue;

#ifdef ENABLE_L2_DEBUG_SECTIONS
        // it's a section with debug info; note the fact,
        // and search for a section that doesn't start in dbg_
        if(!strncmp(linep, "dbg_", 4)) {
            has_debug_info = true;
            linep+=4;
        }
#endif

        switch(find_section(linep)) {
            case ENUMS:

⌨️ 快捷键说明

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