Remove broken c based parser code

git-svn-id: https://svn.o-hand.com/repos/poky/trunk@3192 311d38ba-8fff-0310-9ca6-ca027cbcb966
This commit is contained in:
Richard Purdie 2007-11-17 22:21:42 +00:00
parent 688eca78c0
commit 636e360eea
14 changed files with 0 additions and 5629 deletions

View File

@ -1,188 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""class for handling .bb files (using a C++ parser)
Reads a .bb file and obtains its metadata (using a C++ parser)
Copyright (C) 2006 Tim Robert Ansell
Copyright (C) 2006 Holger Hans Peter Freyther
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.
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, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
import os, sys
# The Module we will use here
import bb
from bitbakec import parsefile
#
# This is the Python Part of the Native Parser Implementation.
# We will only parse .bbclass, .inc and .bb files but no
# configuration files.
# supports, init and handle are the public methods used by
# parser module
#
# The rest of the methods are internal implementation details.
def _init(fn, d):
"""
Initialize the data implementation with values of
the environment and data from the file.
"""
pass
#
# public
#
def supports(fn, data):
return fn[-3:] == ".bb" or fn[-8:] == ".bbclass" or fn[-4:] == ".inc" or fn[-5:] == ".conf"
def init(fn, data):
if not bb.data.getVar('TOPDIR', data):
bb.data.setVar('TOPDIR', os.getcwd(), data)
if not bb.data.getVar('BBPATH', data):
bb.data.setVar('BBPATH', os.path.join(sys.prefix, 'share', 'bitbake'), data)
def handle_inherit(d):
"""
Handle inheriting of classes. This will load all default classes.
It could be faster, it could detect infinite loops but this is todo
Also this delayed loading of bb.parse could impose a penalty
"""
from bb.parse import handle
files = (data.getVar('INHERIT', d, True) or "").split()
if not "base" in i:
files[0:0] = ["base"]
__inherit_cache = data.getVar('__inherit_cache', d) or []
for f in files:
file = data.expand(f, d)
if file[0] != "/" and file[-8:] != ".bbclass":
file = os.path.join('classes', '%s.bbclass' % file)
if not file in __inherit_cache:
debug(2, "BB %s:%d: inheriting %s" % (fn, lineno, file))
__inherit_cache.append( file )
try:
handle(file, d, True)
except IOError:
print "Failed to inherit %s" % file
data.setVar('__inherit_cache', __inherit_cache, d)
def handle(fn, d, include):
from bb import data, parse
(root, ext) = os.path.splitext(os.path.basename(fn))
base_name = "%s%s" % (root,ext)
# initialize with some data
init(fn,d)
# check if we include or are the beginning
oldfile = None
if include:
oldfile = d.getVar('FILE', False)
is_conf = False
elif ext == ".conf":
is_conf = True
data.inheritFromOS(d)
# find the file
if not os.path.isabs(fn):
abs_fn = bb.which(d.getVar('BBPATH', True), fn)
else:
abs_fn = fn
# check if the file exists
if not os.path.exists(abs_fn):
raise IOError("file '%(fn)s' not found" % locals() )
# now we know the file is around mark it as dep
if include:
parse.mark_dependency(d, abs_fn)
# manipulate the bbpath
if ext != ".bbclass" and ext != ".conf":
old_bb_path = data.getVar('BBPATH', d)
data.setVar('BBPATH', os.path.dirname(abs_fn) + (":%s" %old_bb_path) , d)
# handle INHERITS and base inherit
if ext != ".bbclass" and ext != ".conf":
data.setVar('FILE', fn, d)
handle_interit(d)
# now parse this file - by defering it to C++
parsefile(abs_fn, d, is_conf)
# Finish it up
if include == 0:
data.expandKeys(d)
data.update_data(d)
#### !!! XXX Finish it up by executing the anonfunc
# restore the original FILE
if oldfile:
d.setVar('FILE', oldfile)
# restore bbpath
if ext != ".bbclass" and ext != ".conf":
data.setVar('BBPATH', old_bb_path, d )
return d
# Needed for BitBake files...
__pkgsplit_cache__={}
def vars_from_file(mypkg, d):
if not mypkg:
return (None, None, None)
if mypkg in __pkgsplit_cache__:
return __pkgsplit_cache__[mypkg]
myfile = os.path.splitext(os.path.basename(mypkg))
parts = myfile[0].split('_')
__pkgsplit_cache__[mypkg] = parts
exp = 3 - len(parts)
tmplist = []
while exp != 0:
exp -= 1
tmplist.append(None)
parts.extend(tmplist)
return parts
# Inform bitbake that we are a parser
# We need to define all three
from bb.parse import handlers
handlers.append( {'supports' : supports, 'handle': handle, 'init' : init})
del handlers

View File

@ -1,36 +0,0 @@
buil: bitbakec.so
echo "Done"
bitbakescanner.cc: bitbakescanner.l
flex -t bitbakescanner.l > bitbakescanner.cc
bitbakeparser.cc: bitbakeparser.y python_output.h
lemon bitbakeparser.y
mv bitbakeparser.c bitbakeparser.cc
bitbakec.c: bitbakec.pyx
pyrexc bitbakec.pyx
bitbakec-processed.c: bitbakec.c
cat bitbakec.c | sed -e"s/__pyx_f_8bitbakec_//" > bitbakec-processed.c
bitbakec.o: bitbakec-processed.c
gcc -c bitbakec-processed.c -o bitbakec.o -fPIC -I/usr/include/python2.4
bitbakeparser.o: bitbakeparser.cc
g++ -c bitbakeparser.cc -fPIC -I/usr/include/python2.4
bitbakescanner.o: bitbakescanner.cc
g++ -c bitbakescanner.cc -fPIC -I/usr/include/python2.4
bitbakec.so: bitbakec.o bitbakeparser.o bitbakescanner.o
g++ -shared -fPIC bitbakeparser.o bitbakescanner.o bitbakec.o -o bitbakec.so
clean:
rm -f *.out
rm -f *.cc
rm -f bitbakec.c
rm -f bitbakec-processed.c
rm -f *.o
rm -f *.so

View File

@ -1,12 +0,0 @@
To ease portability (lemon, flex, etc) we keep the
result of flex and lemon in the source code. We agree
to not manually change the scanner and parser.
How we create the files:
flex -t bitbakescanner.l > bitbakescanner.cc
lemon bitbakeparser.y
mv bitbakeparser.c bitbakeparser.cc
Now manually create two files

View File

@ -1,28 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2006 Holger Hans Peter Freyther
#
# 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, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
# THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
__version__ = '0.1'
__all__ = [ 'BBHandler' ]
import BBHandler

View File

@ -1,253 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
cdef extern from "stdio.h":
ctypedef int FILE
FILE *fopen(char*, char*)
int fclose(FILE *fp)
cdef extern from "string.h":
int strlen(char*)
cdef extern from "lexerc.h":
ctypedef struct lex_t:
void* parser
void* scanner
char* name
FILE* file
int config
void* data
int lineError
int errorParse
cdef extern int parse(FILE*, char*, object, int)
def parsefile(object file, object data, object config):
#print "parsefile: 1", file, data
# Open the file
cdef FILE* f
f = fopen(file, "r")
#print "parsefile: 2 opening file"
if (f == NULL):
raise IOError("No such file %s." % file)
#print "parsefile: 3 parse"
parse(f, file, data, config)
# Close the file
fclose(f)
cdef public void e_assign(lex_t* container, char* key, char* what):
#print "e_assign", key, what
if what == NULL:
print "FUTURE Warning empty string: use \"\""
what = ""
d = <object>container.data
d.setVar(key, what)
cdef public void e_export(lex_t* c, char* what):
#print "e_export", what
#exp:
# bb.data.setVarFlag(key, "export", 1, data)
d = <object>c.data
d.setVarFlag(what, "export", 1)
cdef public void e_immediate(lex_t* c, char* key, char* what):
#print "e_immediate", key, what
#colon:
# val = bb.data.expand(groupd["value"], data)
d = <object>c.data
d.setVar(key, d.expand(what,d))
cdef public void e_cond(lex_t* c, char* key, char* what):
#print "e_cond", key, what
#ques:
# val = bb.data.getVar(key, data)
# if val == None:
# val = groupd["value"]
if what == NULL:
print "FUTURE warning: Use \"\" for", key
what = ""
d = <object>c.data
d.setVar(key, (d.getVar(key,False) or what))
cdef public void e_prepend(lex_t* c, char* key, char* what):
#print "e_prepend", key, what
#prepend:
# val = "%s %s" % (groupd["value"], (bb.data.getVar(key, data) or ""))
d = <object>c.data
d.setVar(key, what + " " + (d.getVar(key,0) or ""))
cdef public void e_append(lex_t* c, char* key, char* what):
#print "e_append", key, what
#append:
# val = "%s %s" % ((bb.data.getVar(key, data) or ""), groupd["value"])
d = <object>c.data
d.setVar(key, (d.getVar(key,0) or "") + " " + what)
cdef public void e_precat(lex_t* c, char* key, char* what):
#print "e_precat", key, what
#predot:
# val = "%s%s" % (groupd["value"], (bb.data.getVar(key, data) or ""))
d = <object>c.data
d.setVar(key, what + (d.getVar(key,0) or ""))
cdef public void e_postcat(lex_t* c, char* key, char* what):
#print "e_postcat", key, what
#postdot:
# val = "%s%s" % ((bb.data.getVar(key, data) or ""), groupd["value"])
d = <object>c.data
d.setVar(key, (d.getVar(key,0) or "") + what)
cdef public int e_addtask(lex_t* c, char* name, char* before, char* after) except -1:
#print "e_addtask", name
# func = m.group("func")
# before = m.group("before")
# after = m.group("after")
# if func is None:
# return
# var = "do_" + func
#
# data.setVarFlag(var, "task", 1, d)
#
# if after is not None:
# # set up deps for function
# data.setVarFlag(var, "deps", after.split(), d)
# if before is not None:
# # set up things that depend on this func
# data.setVarFlag(var, "postdeps", before.split(), d)
# return
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No tasks allowed in config files")
return -1
d = <object>c.data
do = "do_%s" % name
d.setVarFlag(do, "task", 1)
if before != NULL and strlen(before) > 0:
#print "Before", before
d.setVarFlag(do, "postdeps", ("%s" % before).split())
if after != NULL and strlen(after) > 0:
#print "After", after
d.setVarFlag(do, "deps", ("%s" % after).split())
return 0
cdef public int e_addhandler(lex_t* c, char* h) except -1:
#print "e_addhandler", h
# data.setVarFlag(h, "handler", 1, d)
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No handlers allowed in config files")
return -1
d = <object>c.data
d.setVarFlag(h, "handler", 1)
return 0
cdef public int e_export_func(lex_t* c, char* function) except -1:
#print "e_export_func", function
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No functions allowed in config files")
return -1
return 0
cdef public int e_inherit(lex_t* c, char* file) except -1:
#print "e_inherit", file
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No inherits allowed in config files")
return -1
return 0
cdef public void e_include(lex_t* c, char* file):
from bb.parse import handle
d = <object>c.data
try:
handle(d.expand(file,d), d, True)
except IOError:
print "Could not include file", file
cdef public int e_require(lex_t* c, char* file) except -1:
#print "e_require", file
from bb.parse import handle
d = <object>c.data
try:
handle(d.expand(file,d), d, True)
except IOError:
print "ParseError", file
from bb.parse import ParseError
raise ParseError("Could not include required file %s" % file)
return -1
return 0
cdef public int e_proc(lex_t* c, char* key, char* what) except -1:
#print "e_proc", key, what
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No inherits allowed in config files")
return -1
return 0
cdef public int e_proc_python(lex_t* c, char* key, char* what) except -1:
#print "e_proc_python"
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No pythin allowed in config files")
return -1
if key != NULL:
pass
#print "Key", key
if what != NULL:
pass
#print "What", what
return 0
cdef public int e_proc_fakeroot(lex_t* c, char* key, char* what) except -1:
#print "e_fakeroot", key, what
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No fakeroot allowed in config files")
return -1
return 0
cdef public int e_def(lex_t* c, char* a, char* b, char* d) except -1:
#print "e_def", a, b, d
if c.config == 1:
from bb.parse import ParseError
raise ParseError("No defs allowed in config files")
return -1
return 0
cdef public int e_parse_error(lex_t* c) except -1:
print "e_parse_error", c.name, "line:", lineError, "parse:", errorParse
from bb.parse import ParseError
raise ParseError("There was an parse error, sorry unable to give more information at the current time. File: %s Line: %d" % (c.name,lineError) )
return -1

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
#define T_SYMBOL 1
#define T_VARIABLE 2
#define T_EXPORT 3
#define T_OP_ASSIGN 4
#define T_STRING 5
#define T_OP_PREDOT 6
#define T_OP_POSTDOT 7
#define T_OP_IMMEDIATE 8
#define T_OP_COND 9
#define T_OP_PREPEND 10
#define T_OP_APPEND 11
#define T_TSYMBOL 12
#define T_BEFORE 13
#define T_AFTER 14
#define T_ADDTASK 15
#define T_ADDHANDLER 16
#define T_FSYMBOL 17
#define T_EXPORT_FUNC 18
#define T_ISYMBOL 19
#define T_INHERIT 20
#define T_INCLUDE 21
#define T_REQUIRE 22
#define T_PROC_BODY 23
#define T_PROC_OPEN 24
#define T_PROC_CLOSE 25
#define T_PYTHON 26
#define T_FAKEROOT 27
#define T_DEF_BODY 28
#define T_DEF_ARGS 29

View File

@ -1,179 +0,0 @@
/* bbp.lemon
written by Marc Singer
6 January 2005
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.
DESCRIPTION
-----------
lemon parser specification file for a BitBake input file parser.
Most of the interesting shenanigans are done in the lexer. The
BitBake grammar is not regular. In order to emit tokens that
the parser can properly interpret in LALR fashion, the lexer
manages the interpretation state. This is why there are ISYMBOLs,
SYMBOLS, and TSYMBOLS.
This parser was developed by reading the limited available
documentation for BitBake and by analyzing the available BB files.
There is no assertion of correctness to be made about this parser.
*/
%token_type {token_t}
%name bbparse
%token_prefix T_
%extra_argument {lex_t* lex}
%include {
#include "token.h"
#include "lexer.h"
#include "python_output.h"
}
%token_destructor { $$.release_this (); }
%syntax_error { e_parse_error( lex ); }
program ::= statements.
statements ::= statements statement.
statements ::= .
variable(r) ::= SYMBOL(s).
{ r.assignString( (char*)s.string() );
s.assignString( 0 );
s.release_this(); }
variable(r) ::= VARIABLE(v).
{
r.assignString( (char*)v.string() );
v.assignString( 0 );
v.release_this(); }
statement ::= EXPORT variable(s) OP_ASSIGN STRING(v).
{ e_assign( lex, s.string(), v.string() );
e_export( lex, s.string() );
s.release_this(); v.release_this(); }
statement ::= EXPORT variable(s) OP_PREDOT STRING(v).
{ e_precat( lex, s.string(), v.string() );
e_export( lex, s.string() );
s.release_this(); v.release_this(); }
statement ::= EXPORT variable(s) OP_POSTDOT STRING(v).
{ e_postcat( lex, s.string(), v.string() );
e_export( lex, s.string() );
s.release_this(); v.release_this(); }
statement ::= EXPORT variable(s) OP_IMMEDIATE STRING(v).
{ e_immediate ( lex, s.string(), v.string() );
e_export( lex, s.string() );
s.release_this(); v.release_this(); }
statement ::= EXPORT variable(s) OP_COND STRING(v).
{ e_cond( lex, s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_ASSIGN STRING(v).
{ e_assign( lex, s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_PREDOT STRING(v).
{ e_precat( lex, s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_POSTDOT STRING(v).
{ e_postcat( lex, s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_PREPEND STRING(v).
{ e_prepend( lex, s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_APPEND STRING(v).
{ e_append( lex, s.string() , v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_IMMEDIATE STRING(v).
{ e_immediate( lex, s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_COND STRING(v).
{ e_cond( lex, s.string(), v.string() );
s.release_this(); v.release_this(); }
task ::= TSYMBOL(t) BEFORE TSYMBOL(b) AFTER TSYMBOL(a).
{ e_addtask( lex, t.string(), b.string(), a.string() );
t.release_this(); b.release_this(); a.release_this(); }
task ::= TSYMBOL(t) AFTER TSYMBOL(a) BEFORE TSYMBOL(b).
{ e_addtask( lex, t.string(), b.string(), a.string());
t.release_this(); a.release_this(); b.release_this(); }
task ::= TSYMBOL(t).
{ e_addtask( lex, t.string(), NULL, NULL);
t.release_this();}
task ::= TSYMBOL(t) BEFORE TSYMBOL(b).
{ e_addtask( lex, t.string(), b.string(), NULL);
t.release_this(); b.release_this(); }
task ::= TSYMBOL(t) AFTER TSYMBOL(a).
{ e_addtask( lex, t.string(), NULL, a.string());
t.release_this(); a.release_this(); }
tasks ::= tasks task.
tasks ::= task.
statement ::= ADDTASK tasks.
statement ::= ADDHANDLER SYMBOL(s).
{ e_addhandler( lex, s.string()); s.release_this (); }
func ::= FSYMBOL(f). { e_export_func( lex, f.string()); f.release_this(); }
funcs ::= funcs func.
funcs ::= func.
statement ::= EXPORT_FUNC funcs.
inherit ::= ISYMBOL(i). { e_inherit( lex, i.string() ); i.release_this (); }
inherits ::= inherits inherit.
inherits ::= inherit.
statement ::= INHERIT inherits.
statement ::= INCLUDE ISYMBOL(i).
{ e_include( lex, i.string() ); i.release_this(); }
statement ::= REQUIRE ISYMBOL(i).
{ e_require( lex, i.string() ); i.release_this(); }
proc_body(r) ::= proc_body(l) PROC_BODY(b).
{ /* concatenate body lines */
r.assignString( token_t::concatString(l.string(), b.string()) );
l.release_this ();
b.release_this ();
}
proc_body(b) ::= . { b.assignString(0); }
statement ::= variable(p) PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc( lex, p.string(), b.string() );
p.release_this(); b.release_this(); }
statement ::= PYTHON SYMBOL(p) PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc_python ( lex, p.string(), b.string() );
p.release_this(); b.release_this(); }
statement ::= PYTHON PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc_python( lex, NULL, b.string());
b.release_this (); }
statement ::= FAKEROOT SYMBOL(p) PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc_fakeroot( lex, p.string(), b.string() );
p.release_this (); b.release_this (); }
def_body(r) ::= def_body(l) DEF_BODY(b).
{ /* concatenate body lines */
r.assignString( token_t::concatString(l.string(), b.string()) );
l.release_this (); b.release_this ();
}
def_body(b) ::= . { b.assignString( 0 ); }
statement ::= SYMBOL(p) DEF_ARGS(a) def_body(b).
{ e_def( lex, p.string(), a.string(), b.string());
p.release_this(); a.release_this(); b.release_this(); }

File diff suppressed because it is too large Load Diff

View File

@ -1,319 +0,0 @@
/* bbf.flex
written by Marc Singer
6 January 2005
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.
DESCRIPTION
-----------
flex lexer specification for a BitBake input file parser.
Unfortunately, flex doesn't welcome comments within the rule sets.
I say unfortunately because this lexer is unreasonably complex and
comments would make the code much easier to comprehend.
The BitBake grammar is not regular. In order to interpret all
of the available input files, the lexer maintains much state as it
parses. There are places where this lexer will emit tokens that
are invalid. The parser will tend to catch these.
The lexer requires C++ at the moment. The only reason for this has
to do with a very small amount of managed state. Producing a C
lexer should be a reasonably easy task as long as the %reentrant
option is used.
NOTES
-----
o RVALUES. There are three kinds of RVALUES. There are unquoted
values, double quote enclosed strings, and single quote
strings. Quoted strings may contain unescaped quotes (of either
type), *and* any type may span more than one line by using a
continuation '\' at the end of the line. This requires us to
recognize all types of values with a single expression.
Moreover, the only reason to quote a value is to include
trailing or leading whitespace. Whitespace within a value is
preserved, ugh.
o CLASSES. C_ patterns define classes. Classes ought not include
a repitition operator, instead letting the reference to the class
define the repitition count.
C_SS - symbol start
C_SB - symbol body
C_SP - whitespace
*/
%option never-interactive
%option yylineno
%option noyywrap
%option reentrant stack
%{
#include "token.h"
#include "lexer.h"
#include "bitbakeparser.h"
#include <ctype.h>
extern void *bbparseAlloc(void *(*mallocProc)(size_t));
extern void bbparseFree(void *p, void (*freeProc)(void*));
extern void *bbparseAlloc(void *(*mallocProc)(size_t));
extern void *bbparse(void*, int, token_t, lex_t*);
extern void bbparseTrace(FILE *TraceFILE, char *zTracePrompt);
//static const char* rgbInput;
//static size_t cbInput;
extern "C" {
int lineError;
int errorParse;
enum {
errorNone = 0,
errorUnexpectedInput,
errorUnsupportedFeature,
};
}
#define YY_EXTRA_TYPE lex_t*
/* Read from buffer */
#define YY_INPUT(buf,result,max_size) \
{ yyextra->input(buf, &result, max_size); }
//#define YY_DECL static size_t yylex ()
#define ERROR(e) \
do { lineError = yylineno; errorParse = e; yyterminate (); } while (0)
static const char* fixup_escapes (const char* sz);
%}
C_SP [ \t]
COMMENT #.*\n
OP_ASSIGN "="
OP_PREDOT ".="
OP_POSTDOT "=."
OP_IMMEDIATE ":="
OP_PREPEND "=+"
OP_APPEND "+="
OP_COND "?="
B_OPEN "{"
B_CLOSE "}"
K_ADDTASK "addtask"
K_ADDHANDLER "addhandler"
K_AFTER "after"
K_BEFORE "before"
K_DEF "def"
K_INCLUDE "include"
K_REQUIRE "require"
K_INHERIT "inherit"
K_PYTHON "python"
K_FAKEROOT "fakeroot"
K_EXPORT "export"
K_EXPORT_FUNC "EXPORT_FUNCTIONS"
STRING \"([^\n\r]|"\\\n")*\"
SSTRING \'([^\n\r]|"\\\n")*\'
VALUE ([^'" \t\n])|([^'" \t\n]([^\n]|(\\\n))*[^'" \t\n])
C_SS [a-zA-Z_]
C_SB [a-zA-Z0-9_+-./]
REF $\{{C_SS}{C_SB}*\}
SYMBOL {C_SS}{C_SB}*
VARIABLE $?{C_SS}({C_SB}*|{REF})*(\[[a-zA-Z0-9_]*\])?
FILENAME ([a-zA-Z_./]|{REF})(([-+a-zA-Z0-9_./]*)|{REF})*
PROC \({C_SP}*\)
%s S_DEF
%s S_DEF_ARGS
%s S_DEF_BODY
%s S_FUNC
%s S_INCLUDE
%s S_INHERIT
%s S_REQUIRE
%s S_PROC
%s S_RVALUE
%s S_TASK
%%
{OP_APPEND} { BEGIN S_RVALUE;
yyextra->accept (T_OP_APPEND); }
{OP_PREPEND} { BEGIN S_RVALUE;
yyextra->accept (T_OP_PREPEND); }
{OP_IMMEDIATE} { BEGIN S_RVALUE;
yyextra->accept (T_OP_IMMEDIATE); }
{OP_ASSIGN} { BEGIN S_RVALUE;
yyextra->accept (T_OP_ASSIGN); }
{OP_PREDOT} { BEGIN S_RVALUE;
yyextra->accept (T_OP_PREDOT); }
{OP_POSTDOT} { BEGIN S_RVALUE;
yyextra->accept (T_OP_POSTDOT); }
{OP_COND} { BEGIN S_RVALUE;
yyextra->accept (T_OP_COND); }
<S_RVALUE>\\\n{C_SP}* { }
<S_RVALUE>{STRING} { BEGIN INITIAL;
size_t cb = yyleng;
while (cb && isspace (yytext[cb - 1]))
--cb;
yytext[cb - 1] = 0;
yyextra->accept (T_STRING, yytext + 1); }
<S_RVALUE>{SSTRING} { BEGIN INITIAL;
size_t cb = yyleng;
while (cb && isspace (yytext[cb - 1]))
--cb;
yytext[cb - 1] = 0;
yyextra->accept (T_STRING, yytext + 1); }
<S_RVALUE>{VALUE} { ERROR (errorUnexpectedInput); }
<S_RVALUE>{C_SP}*\n+ { BEGIN INITIAL;
yyextra->accept (T_STRING, NULL); }
{K_INCLUDE} { BEGIN S_INCLUDE;
yyextra->accept (T_INCLUDE); }
{K_REQUIRE} { BEGIN S_REQUIRE;
yyextra->accept (T_REQUIRE); }
{K_INHERIT} { BEGIN S_INHERIT;
yyextra->accept (T_INHERIT); }
{K_ADDTASK} { BEGIN S_TASK;
yyextra->accept (T_ADDTASK); }
{K_ADDHANDLER} { yyextra->accept (T_ADDHANDLER); }
{K_EXPORT_FUNC} { BEGIN S_FUNC;
yyextra->accept (T_EXPORT_FUNC); }
<S_TASK>{K_BEFORE} { yyextra->accept (T_BEFORE); }
<S_TASK>{K_AFTER} { yyextra->accept (T_AFTER); }
<INITIAL>{K_EXPORT} { yyextra->accept (T_EXPORT); }
<INITIAL>{K_FAKEROOT} { yyextra->accept (T_FAKEROOT); }
<INITIAL>{K_PYTHON} { yyextra->accept (T_PYTHON); }
{PROC}{C_SP}*{B_OPEN}{C_SP}*\n* { BEGIN S_PROC;
yyextra->accept (T_PROC_OPEN); }
<S_PROC>{B_CLOSE}{C_SP}*\n* { BEGIN INITIAL;
yyextra->accept (T_PROC_CLOSE); }
<S_PROC>([^}][^\n]*)?\n* { yyextra->accept (T_PROC_BODY, yytext); }
{K_DEF} { BEGIN S_DEF; }
<S_DEF>{SYMBOL} { BEGIN S_DEF_ARGS;
yyextra->accept (T_SYMBOL, yytext); }
<S_DEF_ARGS>[^\n:]*: { yyextra->accept (T_DEF_ARGS, yytext); }
<S_DEF_ARGS>{C_SP}*\n { BEGIN S_DEF_BODY; }
<S_DEF_BODY>{C_SP}+[^\n]*\n { yyextra->accept (T_DEF_BODY, yytext); }
<S_DEF_BODY>\n { yyextra->accept (T_DEF_BODY, yytext); }
<S_DEF_BODY>. { BEGIN INITIAL; unput (yytext[0]); }
{COMMENT} { }
<INITIAL>{SYMBOL} { yyextra->accept (T_SYMBOL, yytext); }
<INITIAL>{VARIABLE} { yyextra->accept (T_VARIABLE, yytext); }
<S_TASK>{SYMBOL} { yyextra->accept (T_TSYMBOL, yytext); }
<S_FUNC>{SYMBOL} { yyextra->accept (T_FSYMBOL, yytext); }
<S_INHERIT>{SYMBOL} { yyextra->accept (T_ISYMBOL, yytext); }
<S_INCLUDE>{FILENAME} { BEGIN INITIAL;
yyextra->accept (T_ISYMBOL, yytext); }
<S_REQUIRE>{FILENAME} { BEGIN INITIAL;
yyextra->accept (T_ISYMBOL, yytext); }
<S_TASK>\n { BEGIN INITIAL; }
<S_FUNC>\n { BEGIN INITIAL; }
<S_INHERIT>\n { BEGIN INITIAL; }
[ \t\r\n] /* Insignificant whitespace */
. { ERROR (errorUnexpectedInput); }
/* Check for premature termination */
<<EOF>> { return T_EOF; }
%%
void lex_t::accept (int token, const char* sz)
{
token_t t;
memset (&t, 0, sizeof (t));
t.copyString(sz);
/* tell lemon to parse the token */
parse (parser, token, t, this);
}
void lex_t::input (char *buf, int *result, int max_size)
{
/* printf("lex_t::input %p %d\n", buf, max_size); */
*result = fread(buf, 1, max_size, file);
/* printf("lex_t::input result %d\n", *result); */
}
int lex_t::line ()const
{
/* printf("lex_t::line\n"); */
return yyget_lineno (scanner);
}
extern "C" {
void parse (FILE* file, char* name, PyObject* data, int config)
{
/* printf("parse bbparseAlloc\n"); */
void* parser = bbparseAlloc (malloc);
yyscan_t scanner;
lex_t lex;
/* printf("parse yylex_init\n"); */
yylex_init (&scanner);
lex.parser = parser;
lex.scanner = scanner;
lex.file = file;
lex.name = name;
lex.data = data;
lex.config = config;
lex.parse = bbparse;
/*printf("parse yyset_extra\n"); */
yyset_extra (&lex, scanner);
/* printf("parse yylex\n"); */
int result = yylex (scanner);
/* printf("parse result %d\n", result); */
lex.accept (0);
/* printf("parse lex.accept\n"); */
bbparseTrace (NULL, NULL);
/* printf("parse bbparseTrace\n"); */
if (result != T_EOF)
printf ("premature end of file\n");
yylex_destroy (scanner);
bbparseFree (parser, free);
}
}

View File

@ -1,48 +0,0 @@
/*
Copyright (C) 2005 Holger Hans Peter Freyther
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, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LEXER_H
#define LEXER_H
#include "Python.h"
extern "C" {
struct lex_t {
void* parser;
void* scanner;
FILE* file;
char *name;
PyObject *data;
int config;
void* (*parse)(void*, int, token_t, lex_t*);
void accept(int token, const char* sz = NULL);
void input(char *buf, int *result, int max_size);
int line()const;
};
}
#endif

View File

@ -1,19 +0,0 @@
#ifndef LEXERC_H
#define LEXERC_H
#include <stdio.h>
extern int lineError;
extern int errorParse;
typedef struct {
void *parser;
void *scanner;
FILE *file;
char *name;
PyObject *data;
int config;
} lex_t;
#endif

View File

@ -1,56 +0,0 @@
#ifndef PYTHON_OUTPUT_H
#define PYTHON_OUTPUT_H
/*
Copyright (C) 2006 Holger Hans Peter Freyther
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, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This is the glue:
It will be called from the lemon grammar and will call into
python to set certain things.
*/
extern "C" {
struct lex_t;
extern void e_assign(lex_t*, const char*, const char*);
extern void e_export(lex_t*, const char*);
extern void e_immediate(lex_t*, const char*, const char*);
extern void e_cond(lex_t*, const char*, const char*);
extern void e_prepend(lex_t*, const char*, const char*);
extern void e_append(lex_t*, const char*, const char*);
extern void e_precat(lex_t*, const char*, const char*);
extern void e_postcat(lex_t*, const char*, const char*);
extern void e_addtask(lex_t*, const char*, const char*, const char*);
extern void e_addhandler(lex_t*,const char*);
extern void e_export_func(lex_t*, const char*);
extern void e_inherit(lex_t*, const char*);
extern void e_include(lex_t*, const char*);
extern void e_require(lex_t*, const char*);
extern void e_proc(lex_t*, const char*, const char*);
extern void e_proc_python(lex_t*, const char*, const char*);
extern void e_proc_fakeroot(lex_t*, const char*, const char*);
extern void e_def(lex_t*, const char*, const char*, const char*);
extern void e_parse_error(lex_t*);
}
#endif // PYTHON_OUTPUT_H

View File

@ -1,96 +0,0 @@
/*
Copyright (C) 2005 Holger Hans Peter Freyther
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, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef TOKEN_H
#define TOKEN_H
#include <ctype.h>
#include <string.h>
#define PURE_METHOD
/**
* Special Value for End Of File Handling. We set it to
* 1001 so we can have up to 1000 Terminal Symbols on
* grammar. Currenlty we have around 20
*/
#define T_EOF 1001
struct token_t {
const char* string()const PURE_METHOD;
static char* concatString(const char* l, const char* r);
void assignString(char* str);
void copyString(const char* str);
void release_this();
private:
char *m_string;
size_t m_stringLen;
};
inline const char* token_t::string()const
{
return m_string;
}
/*
* append str to the current string
*/
inline char* token_t::concatString(const char* l, const char* r)
{
size_t cb = (l ? strlen (l) : 0) + strlen (r) + 1;
char *r_sz = new char[cb];
*r_sz = 0;
if (l)
strcat (r_sz, l);
strcat (r_sz, r);
return r_sz;
}
inline void token_t::assignString(char* str)
{
m_string = str;
m_stringLen = str ? strlen(str) : 0;
}
inline void token_t::copyString(const char* str)
{
if( str ) {
m_stringLen = strlen(str);
m_string = new char[m_stringLen+1];
strcpy(m_string, str);
}
}
inline void token_t::release_this()
{
delete m_string;
m_string = 0;
}
#endif