Example #1
0
        std.pair <string, bool> process_line(string line_in)
        {
            bool line_cont = plib.pg.right(line_in, 1) == "\\";

            string line = line_cont ? plib.pg.left(line_in, line_in.length() - 1) : line_in;

            if (m_state == state_e.LINE_CONTINUATION)
            {
                m_line += line;
            }
            else
            {
                m_line = line;
            }

            if (line_cont)
            {
                m_state = state_e.LINE_CONTINUATION;
                return(new std.pair <string, bool>("", false));
            }

            m_state = state_e.PROCESS;

            line = process_comments(m_line);

            string lt = plib.pg.trim(plib.pg.replace_all(line, "\t", " "));

            if (plib.pg.startsWith(lt, "#"))
            {
                ppreprocessor_string_list lti = plib.pg.psplit(lt, ' ', true);
                if (lti[0] == "#if")
                {
                    m_if_level++;
                    m_if_seen |= (1U << m_if_level);
                    if (m_if_flag == 0)
                    {
                        lt = replace_macros(lt);
                        simple_iter t   = new simple_iter(this, tokenize(lt.substr(3), m_expr_sep, true, true)); //simple_iter<ppreprocessor> t(this, tokenize(lt.substr(3), m_expr_sep, true, true));
                        var         val = (int)prepro_expr(t, 255);
                        t.skip_ws();
                        if (!t.eod())
                        {
                            error("found unprocessed content at end of line");
                        }
                        if (val == 0)
                        {
                            m_if_flag |= (1U << m_if_level);
                        }
                        else
                        {
                            m_elif |= (1U << m_if_level);
                        }
                    }
                }
                else if (lti[0] == "#ifdef")
                {
                    m_if_level++;
                    m_if_seen |= (1U << m_if_level);
                    if (get_define(lti[1]) == null)
                    {
                        m_if_flag |= (1U << m_if_level);
                    }
                    else
                    {
                        m_elif |= (1U << m_if_level);
                    }
                }
                else if (lti[0] == "#ifndef")
                {
                    m_if_level++;
                    m_if_seen |= (1U << m_if_level);
                    if (get_define(lti[1]) != null)
                    {
                        m_if_flag |= (1U << m_if_level);
                    }
                    else
                    {
                        m_elif |= (1U << m_if_level);
                    }
                }
                else if (lti[0] == "#else") // basically #elif (1)
                {
                    if ((m_if_seen & (1U << m_if_level)) == 0)
                    {
                        error("#else without #if");
                    }

                    if ((m_elif & (1U << m_if_level)) != 0) // elif disabled
                    {
                        m_if_flag |= (1U << m_if_level);
                    }
                    else
                    {
                        m_if_flag &= ~(1U << m_if_level);
                    }

                    m_elif |= (1U << m_if_level);
                }
                else if (lti[0] == "#elif")
                {
                    if ((m_if_seen & (1U << m_if_level)) == 0)
                    {
                        error("#elif without #if");
                    }

                    //if ((m_if_flag & (1 << m_if_level)) == 0)
                    //  m_if_flag ^= (1 << m_if_level);
                    if ((m_elif & (1U << m_if_level)) != 0) // elif disabled
                    {
                        m_if_flag |= (1U << m_if_level);
                    }
                    else
                    {
                        m_if_flag &= ~(1U << m_if_level);
                    }

                    if (m_if_flag == 0)
                    {
                        //m_if_flag ^= (1 << m_if_level);
                        lt = replace_macros(lt);
                        simple_iter t   = new simple_iter(this, tokenize(lt.substr(5), m_expr_sep, true, true)); //simple_iter<ppreprocessor> t(this, tokenize(lt.substr(5), m_expr_sep, true, true));
                        var         val = (int)prepro_expr(t, 255);
                        t.skip_ws();
                        if (!t.eod())
                        {
                            error("found unprocessed content at end of line");
                        }
                        if (val == 0)
                        {
                            m_if_flag |= (1U << m_if_level);
                        }
                        else
                        {
                            m_elif |= (1U << m_if_level);
                        }
                    }
                }
                else if (lti[0] == "#endif")
                {
                    if ((m_if_seen & (1U << m_if_level)) == 0)
                    {
                        error("#else without #if");
                    }
                    m_if_seen &= ~(1U << m_if_level);
                    m_elif    &= ~(1U << m_if_level);
                    m_if_flag &= ~(1U << m_if_level);
                    m_if_level--;
                }
                else if (lti[0] == "#include")
                {
                    if (m_if_flag == 0)
                    {
                        string arg = "";
                        for (size_t i = 1; i < lti.size(); i++)
                        {
                            arg += (lti[i] + " ");
                        }

                        arg = plib.pg.trim(arg);

                        if (plib.pg.startsWith(arg, "\"") && plib.pg.endsWith(arg, "\""))
                        {
                            arg = arg.substr(1, arg.length() - 2);
                            // first try local context
                            var l     = plib.util.buildpath(m_stack.back().m_local_path, arg);
                            var lstrm = m_sources.get_stream(l);
                            if (!lstrm.empty())
                            {
                                m_stack.emplace_back(new input_context(lstrm, plib.util.path(l), l));  //m_stack.emplace_back(input_context(lstrm.release_stream(), plib::util::path(l), l));
                            }
                            else
                            {
                                var strm = m_sources.get_stream(arg);
                                if (!strm.empty())
                                {
                                    m_stack.emplace_back(new input_context(strm, plib.util.path(arg), arg));  //m_stack.emplace_back(input_context(strm.release_stream(), plib::util::path(arg), arg));
                                }
                                else
                                {
                                    error("include not found:" + arg);
                                }
                            }
                        }
                        else
                        {
                            error("include misspelled:" + arg);
                        }

                        string linemarker = new pfmt("# {0} \"{1}\" 1\n").op(m_stack.back().m_lineno, m_stack.back().m_name);
                        push_out(linemarker);
                    }
                }
                else if (lti[0] == "#pragma")
                {
                    if (m_if_flag == 0 && lti.size() > 3 && lti[1] == "NETLIST")
                    {
                        if (lti[2] == "warning")
                        {
                            error("NETLIST: " + catremainder(lti, 3, " "));
                        }
                    }
                }
                else if (lti[0] == "#define")
                {
                    if (m_if_flag == 0)
                    {
                        if (lti.size() < 2)
                        {
                            error("define needs at least one argument");
                        }

                        simple_iter args = new simple_iter(this, tokenize(lt.substr(8), m_expr_sep, false, false));  //simple_iter<ppreprocessor> args(this, tokenize(lt.substr(8), m_expr_sep, false, false));
                        string      n    = args.next();
                        if (!is_valid_token(n))
                        {
                            error("define expected identifier");
                        }

                        var prevdef = get_define(n);
                        if (lti.size() == 2)
                        {
                            if (prevdef != null && !prevdef.m_replace.empty())
                            {
                                error("redefinition of " + n);
                            }

                            m_defines.insert(n, new define_t(n, ""));
                        }
                        else if (args.next_ws() == "(")
                        {
                            define_t def = new define_t(n);
                            def.m_has_params = true;
                            var token = args.next();
                            while (true)
                            {
                                if (token == ")")
                                {
                                    break;
                                }

                                def.m_params.push_back(token);
                                token = args.next();
                                if (token != "," && token != ")")
                                {
                                    error(new pfmt("expected , or ), found <{0}>").op(token));
                                }
                                if (token == ",")
                                {
                                    token = args.next();
                                }
                            }

                            string r = "";
                            while (!args.eod())
                            {
                                r += args.next_ws();
                            }

                            def.m_replace = r;
                            if (prevdef != null && prevdef.m_replace != r)
                            {
                                error("redefinition of " + n);
                            }

                            m_defines.insert(n, def);
                        }
                        else
                        {
                            string r = "";
                            while (!args.eod())
                            {
                                r += args.next_ws();
                            }

                            if (prevdef != null && prevdef.m_replace != r)
                            {
                                error("redefinition of " + n);
                            }

                            m_defines.insert(n, new define_t(n, r));
                        }
                    }
                }
                else if (lti[0] == "#undef")
                {
                    if (m_if_flag == 0)
                    {
                        if (lti.size() < 2)
                        {
                            error("undef needs at least one argument");
                        }

                        simple_iter args = new simple_iter(this, tokenize(lt.substr(7), m_expr_sep, false, false));  //simple_iter<ppreprocessor> args(this, tokenize(lt.substr(7), m_expr_sep, false, false));
                        string      n    = args.next();
                        if (!is_valid_token(n))
                        {
                            error("undef expected identifier");
                        }

                        m_defines.erase(n);
                    }
                }
                else
                {
                    if (m_if_flag == 0)
                    {
                        error("unknown directive");
                    }
                }
                return(new std.pair <string, bool>("", false));
            }

            if (m_if_flag == 0)
            {
                return(new std.pair <string, bool>(replace_macros(lt), true));
            }

            return(new std.pair <string, bool>("", false));
        }
Example #2
0
        string replace_macros(string line)
        {
            //std::vector<pstring> elems(psplit(line, m_expr_sep));
            bool   repeat = false;
            string tmpret = line;

            do
            {
                repeat = false;
                simple_iter elems = new simple_iter(this, tokenize(tmpret, m_expr_sep, false, true));  //simple_iter<ppreprocessor> elems(this, tokenize(tmpret, m_expr_sep, false, true));
                tmpret = "";
                while (!elems.eod())
                {
                    var      token = elems.next_ws();
                    define_t def   = get_define(token);
                    if (def == null)
                    {
                        tmpret += token;
                    }
                    else if (!def.m_has_params)
                    {
                        tmpret += def.m_replace;
                        repeat  = true;
                    }
                    else
                    {
                        token = elems.next();
                        if (token != "(")
                        {
                            error("expected '(' in macro expansion of " + def.m_name);
                        }

                        ppreprocessor_string_list rep = new ppreprocessor_string_list();
                        token = elems.next();
                        while (token != ")")
                        {
                            string par  = "";
                            int    pcnt = 1;
                            while (true)
                            {
                                if (pcnt == 1 && token == ",")
                                {
                                    token = elems.next();
                                    break;
                                }

                                if (token == "(")
                                {
                                    pcnt++;
                                }

                                if (token == ")")
                                {
                                    if (--pcnt == 0)
                                    {
                                        break;
                                    }
                                }

                                par  += token;
                                token = elems.next();
                            }

                            rep.push_back(par);
                        }

                        repeat = true;
                        if (def.m_params.size() != rep.size())
                        {
                            error(new pfmt("Expected {0} parameters, got {1}").op(def.m_params.size(), rep.size()));
                        }

                        simple_iter r = new simple_iter(this, tokenize(def.m_replace, m_expr_sep, false, false));  //simple_iter<ppreprocessor> r(this, tokenize(def->m_replace, m_expr_sep, false, false));
                        bool        stringify_next = false;
                        while (!r.eod())
                        {
                            token = r.next();
                            if (token == "#")
                            {
                                stringify_next = true;
                            }
                            else if (token != " " && token != "\t")
                            {
                                for (size_t i = 0; i < def.m_params.size(); i++)
                                {
                                    if (def.m_params[i] == token)
                                    {
                                        if (stringify_next)
                                        {
                                            stringify_next = false;
                                            token          = "\"" + rep[i] + "\"";
                                        }
                                        else
                                        {
                                            token = rep[i];
                                        }
                                        break;
                                    }
                                }

                                if (stringify_next)
                                {
                                    error("'#' is not followed by a macro parameter");
                                }

                                tmpret += token;
                                tmpret += " "; // make sure this is not concatenated with next token
                            }
                            else
                            {
                                tmpret += token;
                            }
                        }
                    }
                }
            } while (repeat);

            return(tmpret);
        }