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

📄 parse.cxx

📁 eCos1.31版
💻 CXX
📖 第 1 页 / 共 3 页
字号:
//{{{  Banner                                   //============================================================================////     parse.cxx////     Miscellaneous parsing routines////============================================================================//####COPYRIGHTBEGIN####//                                                                          // ----------------------------------------------------------------------------// Copyright (C) 1999, 2000 Red Hat, Inc.//// This file is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.//// ----------------------------------------------------------------------------//                                                                          //####COPYRIGHTEND####//============================================================================//#####DESCRIPTIONBEGIN####//// Author(s):   bartv// Contact(s):  bartv// Date:        1999/02/23// Version:     0.02////####DESCRIPTIONEND####//============================================================================//}}}//{{{  #include's                               // ----------------------------------------------------------------------------#include "cdlconfig.h"// Get the infrastructure types, assertions, tracing and similar// facilities.#include <cyg/infra/cyg_ass.h>#include <cyg/infra/cyg_trac.h>// <cdlcore.hxx> defines everything implemented in this module.// It implicitly supplies <string>, <vector> and <map> because// the class definitions rely on these headers.#include <cdlcore.hxx>//}}}//{{{  Description                              // ----------------------------------------------------------------------------// All CDL data is read via a Tcl interpreter, so the parsing is done by// procedures that appear as Tcl commands. This has obvious advantages in// terms of expressive power, but does result in a little bit of confusion// when producing diagnostics.//// Errors should not bypass the Tcl interpreter, to ensure that that// stays in a consistent state. In particular it is not possible to let// arbitrary C++ exceptions to go straight through the Tcl interpreter,// this is likely to result in a corrupted interpreter.// // Also, it is not a good idea to abort parsing as soon as anything// goes wrong. Instead there should be an error handling callback associated// with the interpreter, which can be used to report errors. This// callback may choose to raise an exception.//// Consider the case of parsing a property (which accounts for most of// the code in this module). A property does not exist in isolation,// only within the context of a suitable CDL entity such as an option.// If parsing succeeds and a property object is created then it must// be added to the current CDL entity.//// Therefore a typical parse routine looks like this:////  1) get the current CDL node from the interpreter//  2) do basic parsing of the data. Any errors should be reported//     via the callback.//  3) create a suitable CdlProperty object//  4) add the property to the current entity//// std::bad_alloc and CdlStringException exceptions can be thrown, they// will be intercepted by the CdlInterpreter class.//}}}//{{{  Statics                                  // ----------------------------------------------------------------------------// The string "property " is needed in various places. Provide it as a static// to cut down the number of times the string constructor has to run.static std::string property_string = "property ";//}}}//{{{  Generic parsing-related utilities        //{{{  argv manipulation                        // ----------------------------------------------------------------------------// Some of the properties have aliases in the CDL data, so argv[0] has to be// used to work out what is actually being parsed. However the Tcl interpreter// may prefix the command name with :: to indicate the global namespace.const char*CdlParse::get_tcl_cmd_name(const char* name){    if ((name[0] == ':') && (name[1] == ':')) {        return &(name[2]);    } else {        return name;    }}// Given a list of arguments, concatenate them together into a C++ string.// This makes expression parsing easier. The final argument should be an// index into the array, typically the result of a call to skip_argv_options().std::stringCdlParse::concatenate_argv(int argc, char** argv, int index){    CYG_REPORT_FUNCNAME("CdlParse::concatenate_argv");    std::string result = "";    for ( int i = index ; i < argc; i++) {        if (i > index) {            result += ' ';        }        result += std::string(argv[i]);    }        CYG_REPORT_RETURN();    return result;}// ----------------------------------------------------------------------------// Option parsing.//// Some properties accept modifiers in their argument list. For example,// by default a "compile" property is just a list of source files that// should be compiled and added to the current library. It is possible// to specify an alternative library via a modifier:////    ...//    compile -library=libextras.a dummy.cxx//    ...//// The rules applied for such options are intended to follow common Tcl// practice://// 1) any initial arguments beginning with a - are assumed to be//    options.//// 2) the first argument which does not begin with a - stops option//    processing.//// 3) option processing can also be terminated with a -- argument.//    This may occasionally be required, e.g. to have -ve constants//    in an expression.//// 4) the parsing code does not distinguish between single and double//    hyphens. If there happens to be a second - in an option then this//    is just ignored.//// 5) it is not necessary to supply the whole option name, as long as//    what is provided is unambiguous. For example -lib=libextras.a is//    acceptable (for now anyway, conceivably it would break in future).//    Option processing is case sensitive.//// 6) name/value pairs can take the form -name=value or the form//    -name value, whichever is appropriate.//// The parse_options() function takes the current interpreter (so that// it can generate diagnostics), a prefix such as `property// "requires"' or `package CYGPKG_HAL', details of the options to be// parsed, an argc/argv list, an index, and a reference to a vector.// The parsed options get placed in the vector, and the index argument// gets updated to point at the first non-option argument. It will// report problems via report_warning().//// The options description consists of a pointer to an array of// C strings (allowing static initialization). Passing a zero// argument indicates that the property takes no options. Otherwise// the array should be zero terminated.//// Each entry in the array takes the form "name:flags". The optional// flags consist of zero or more characters indicating how the option// should be interpreted. Valid flags are://// f    - this option takes no data, it is just a boolean flag. The//        default behaviour assumes name/value pairs.//// m    - this option can occur multiple times. The default behaviour//        is that each option can only occur once.// Utility function to get hold of an option name without the colon// or terminating flags.static std::stringget_option_string(char* name){    std::string result = "";    while ((*name != ':') && (*name != '\0')) {        result += *name++;    }    return result;}intCdlParse::parse_options(CdlInterpreter interp, std::string diag_prefix, char** options,                                 int argc, char** argv, int index,                                 std::vector<std::pair<std::string,std::string> >& result){    CYG_REPORT_FUNCNAMETYPE("CdlParse::parse_options", "final index %d");    CYG_REPORT_FUNCARG4XV(interp, options, argc, argv);    CYG_PRECONDITION_CLASSC(interp);    CYG_PRECONDITIONC(argc > 0);        // The property name must be present.    // It is possible for some of the arguments to have been processed already.    CYG_PRECONDITIONC((index > 0) && (index <= argc));    while((index < argc) && ('-' == argv[index][0])) {        std::string name  = "";        std::string value = "";        // The sequence -- should always terminate option processing.        if (0 == strcmp(argv[index], "--")) {            index++;            break;        }        char* arg_ptr       = argv[index];        // Skip the initial -, and the second one as well if it is present.        if ('-' == *++arg_ptr) {            arg_ptr++;        }        // Construct the option name. This is the current argument up        // to but not including the '=' character or EOD.        while (('=' != *arg_ptr) && ('\0' != *arg_ptr)) {            name += *arg_ptr++;        }        if ("" == name) {            // One of "-", "-=xxx", or "--=x"            CdlParse::report_warning(interp, diag_prefix + ", invalid option string " + argv[index]);        }        // Do not try to extract the value unless we are sure there        // should be one. Instead try to match the option name. The        // current value of name should be a unique substring of        // one of the known option strings.        //        // Note that the supplied options descriptor can be NULL,        // since most properties do not yet take any options.        // In that case opt_index will remain at -1, and we should        // get an "invalid option" diagnostic.        unsigned int i;        int opt_index = -1;        if (0 != options) {            for (i = 0; 0 != options[i]; i++) {                if (0 == strncmp(name.c_str(), options[i], name.size())) {                    if (-1 != opt_index) {                        CdlParse::report_warning(interp, diag_prefix + ", ambiguous option name " + name +                                                 ", it can match " + get_option_string(options[opt_index]) +                                                 " or " + get_option_string(options[i]));                        index++;                        break;                    } else {                        opt_index = i;                    }                }            }        }        if (-1 == opt_index) {            CdlParse::report_warning(interp, diag_prefix + ", invalid option " + name);            index++;            break;        }        // The option has been identified successfully. Extract the flags.        bool    flag_flag       = false;        bool    multiple_flag   = false;        char*   tmp = options[opt_index];        while (('\0' != *tmp) && (':' != *tmp)) {            tmp++;        }        if (':' == *tmp) {            do {                tmp++;                if ('f' == *tmp) {                    flag_flag = true;                } else if ('m' == *tmp) {                    multiple_flag = true;                } else if ('\0' != *tmp) {                    CYG_FAIL("Invalid property option");                }            } while ('\0' != *tmp);        }        // We now know the full option name. Use it for future diagnostics.        name = get_option_string(options[opt_index]);        // Take care of the value.        if (flag_flag) {            // There should not be a value. If the current argument is of the            // form x=y then this is an error.            if ('=' == *arg_ptr) {                CdlParse::report_warning(interp, diag_prefix + ", option " + name + " does not take any data");            }            // Leave index pointing at the next argument to be processed.            index++;        } else {            if ('=' == *arg_ptr) {                value = std::string(++arg_ptr);            } else if (++index == argc) {                CdlParse::report_warning(interp, diag_prefix + ", missing data for option " + name);

⌨️ 快捷键说明

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