| 
      
      
      From: <ssm...@us...> - 2007-02-21 17:11:28
       | 
| Revision: 2247
          http://svn.sourceforge.net/selinux/?rev=2247&view=rev
Author:   ssmalley
Date:     2007-02-21 09:11:26 -0800 (Wed, 21 Feb 2007)
Log Message:
-----------
Author: Daniel J Walsh
Email: dw...@re...
Subject: sepolgen fixes.
Date: Tue, 20 Feb 2007 09:55:41 -0500
    Change to Makefile to get proper python library path even on 64 bit 
platforms.
    Empty or poorly formated interface files cause sepol-ifgen to crash. 
Modified Paths:
--------------
    trunk/sepolgen/src/sepolgen/Makefile
    trunk/sepolgen/src/sepolgen/refparser.py
Modified: trunk/sepolgen/src/sepolgen/Makefile
===================================================================
--- trunk/sepolgen/src/sepolgen/Makefile	2007-02-21 17:09:32 UTC (rev 2246)
+++ trunk/sepolgen/src/sepolgen/Makefile	2007-02-21 17:11:26 UTC (rev 2247)
@@ -1,4 +1,4 @@
-PYTHONLIBDIR ?= `python -c "from distutils.sysconfig import *; print get_python_lib()"`
+PYTHONLIBDIR ?= $(shell  python -c "from distutils.sysconfig import *; print get_python_lib(1)")
 PACKAGEDIR ?= $(DESTDIR)/$(PYTHONLIBDIR)/sepolgen
 
 install:
Modified: trunk/sepolgen/src/sepolgen/refparser.py
===================================================================
--- trunk/sepolgen/src/sepolgen/refparser.py	2007-02-21 17:09:32 UTC (rev 2246)
+++ trunk/sepolgen/src/sepolgen/refparser.py	2007-02-21 17:11:26 UTC (rev 2247)
@@ -691,11 +691,13 @@
             output.write(msg)
 
     def parse_file(f, module, spt=None):
-        fd = open(f)
-        txt = fd.read()
-        fd.close()
         try:
+            fd = open(f)
+            txt = fd.read()
+            fd.close()
             parse(txt, module, spt)
+        except IOError, e:
+            return
         except ValueError, e:
             raise ValueError("error parsing file %s: %s" % (f, str(e)))
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 | 
| 
      
      
      From: <ssm...@us...> - 2007-02-22 14:41:02
       | 
| Revision: 2261
          http://svn.sourceforge.net/selinux/?rev=2261&view=rev
Author:   ssmalley
Date:     2007-02-22 06:40:29 -0800 (Thu, 22 Feb 2007)
Log Message:
-----------
Author: Karl MacMillan
Email: kma...@me...
Subject: sepolgen: update ply to the latest version
Date: Wed, 21 Feb 2007 13:14:18 -0500
Update the PLY parsing library to the latest upstream version.
Signed-off-by: Karl MacMillan <kma...@me...>
Modified Paths:
--------------
    trunk/sepolgen/src/sepolgen/lex.py
    trunk/sepolgen/src/sepolgen/refparser.py
    trunk/sepolgen/src/sepolgen/yacc.py
Modified: trunk/sepolgen/src/sepolgen/lex.py
===================================================================
--- trunk/sepolgen/src/sepolgen/lex.py	2007-02-22 14:38:28 UTC (rev 2260)
+++ trunk/sepolgen/src/sepolgen/lex.py	2007-02-22 14:40:29 UTC (rev 2261)
@@ -5,8 +5,6 @@
 #
 # Copyright (C) 2001-2006, David M. Beazley
 #
-# $Header: /cvs/projects/PLY/lex.py,v 1.1.1.1 2004/05/21 15:34:10 beazley Exp $
-#
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # License as published by the Free Software Foundation; either
@@ -22,242 +20,180 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 # 
 # See the file COPYING for a complete copy of the LGPL.
-#
-# 
-# This module automatically constructs a lexical analysis module from regular
-# expression rules defined in a user-defined module.  The idea is essentially the same
-# as that used in John Aycock's Spark framework, but the implementation works
-# at the module level rather than requiring the use of classes.
-#
-# This module tries to provide an interface that is closely modeled after
-# the traditional lex interface in Unix.  It also differs from Spark
-# in that:
-#
-#   -  It provides more extensive error checking and reporting if
-#      the user supplies a set of regular expressions that can't
-#      be compiled or if there is any other kind of a problem in
-#      the specification.
-#
-#   -  The interface is geared towards LALR(1) and LR(1) parser
-#      generators.  That is tokens are generated one at a time
-#      rather than being generated in advanced all in one step.
-#
-# There are a few limitations of this module
-#
-#   -  The module interface makes it somewhat awkward to support more
-#      than one lexer at a time.  Although somewhat inelegant from a
-#      design perspective, this is rarely a practical concern for
-#      most compiler projects.
-#
-#   -  The lexer requires that the entire input text be read into
-#      a string before scanning.  I suppose that most machines have
-#      enough memory to make this a minor issues, but it makes
-#      the lexer somewhat difficult to use in interactive sessions
-#      or with streaming data.
-#
 #-----------------------------------------------------------------------------
 
-r"""
-lex.py
+__version__ = "2.2"
 
-This module builds lex-like scanners based on regular expression rules.
-To use the module, simply write a collection of regular expression rules
-and actions like this:
+import re, sys, types
 
-# lexer.py
-import lex
+# Regular expression used to match valid token names
+_is_identifier = re.compile(r'^[a-zA-Z0-9_]+$')
 
-# Define a list of valid tokens
-tokens = (
-    'IDENTIFIER', 'NUMBER', 'PLUS', 'MINUS'
-    )
-
-# Define tokens as functions
-def t_IDENTIFIER(t):
-    r' ([a-zA-Z_](\w|_)* '
-    return t
-
-def t_NUMBER(t):
-    r' \d+ '
-    return t
-
-# Some simple tokens with no actions
-t_PLUS = r'\+'
-t_MINUS = r'-'
-
-# Initialize the lexer
-lex.lex()
-
-The tokens list is required and contains a complete list of all valid
-token types that the lexer is allowed to produce.  Token types are
-restricted to be valid identifiers.  This means that 'MINUS' is a valid
-token type whereas '-' is not.
-
-Rules are defined by writing a function with a name of the form
-t_rulename.  Each rule must accept a single argument which is
-a token object generated by the lexer. This token has the following
-attributes:
-
-    t.type   = type string of the token.  This is initially set to the
-               name of the rule without the leading t_
-    t.value  = The value of the lexeme.
-    t.lineno = The value of the line number where the token was encountered
-    
-For example, the t_NUMBER() rule above might be called with the following:
-    
-    t.type  = 'NUMBER'
-    t.value = '42'
-    t.lineno = 3
-
-Each rule returns the token object it would like to supply to the
-parser.  In most cases, the token t is returned with few, if any
-modifications.  To discard a token for things like whitespace or
-comments, simply return nothing.  For instance:
-
-def t_whitespace(t):
-    r' \s+ '
-    pass
-
-For faster lexing, you can also define this in terms of the ignore set like this:
-
-t_ignore = ' \t'
-
-The characters in this string are ignored by the lexer. Use of this feature can speed
-up parsing significantly since scanning will immediately proceed to the next token.
-
-lex requires that the token returned by each rule has an attribute
-t.type.  Other than this, rules are free to return any kind of token
-object that they wish and may construct a new type of token object
-from the attributes of t (provided the new object has the required
-type attribute).
-
-If illegal characters are encountered, the scanner executes the
-function t_error(t) where t is a token representing the rest of the
-string that hasn't been matched.  If this function isn't defined, a
-LexError exception is raised.  The .text attribute of this exception
-object contains the part of the string that wasn't matched.
-
-The t.skip(n) method can be used to skip ahead n characters in the
-input stream.  This is usually only used in the error handling rule.
-For instance, the following rule would print an error message and
-continue:
-
-def t_error(t):
-    print "Illegal character in input %s" % t.value[0]
-    t.skip(1)
-
-Of course, a nice scanner might wish to skip more than one character
-if the input looks very corrupted.
-
-The lex module defines a t.lineno attribute on each token that can be used
-to track the current line number in the input.  The value of this
-variable is not modified by lex so it is up to your lexer module
-to correctly update its value depending on the lexical properties
-of the input language.  To do this, you might write rules such as
-the following:
-
-def t_newline(t):
-    r' \n+ '
-    t.lineno += t.value.count("\n")
-
-To initialize your lexer so that it can be used, simply call the lex.lex()
-function in your rule file.  If there are any errors in your
-specification, warning messages or an exception will be generated to
-alert you to the problem.
-
-To use the newly constructed lexer from another module, simply do
-this:
-
-    import lex
-    import lexer
-    lex.input("position = initial + rate*60")
-
-    while 1:
-        token = lex.token()       # Get a token
-        if not token: break        # No more tokens
-        ... do whatever ...
-
-Assuming that the module 'lexer' has initialized lex as shown
-above, parsing modules can safely import 'lex' without having
-to import the rule file or any additional imformation about the
-scanner you have defined.
-"""    
-
-# -----------------------------------------------------------------------------
-
-
-__version__ = "2.0"
-
-import re, types, sys, copy
-
 # Available instance types.  This is used when lexers are defined by a class.
-# it's a little funky because I want to preserve backwards compatibility
+# It's a little funky because I want to preserve backwards compatibility
 # with Python 2.0 where types.ObjectType is undefined.
 
 try:
    _INSTANCETYPE = (types.InstanceType, types.ObjectType)
 except AttributeError:
    _INSTANCETYPE = types.InstanceType
+   class object: pass       # Note: needed if no new-style classes present
 
-# Exception thrown when invalid token encountered and no default
+# Exception thrown when invalid token encountered and no default error
+# handler is defined.
 class LexError(Exception):
     def __init__(self,message,s):
          self.args = (message,)
          self.text = s
 
 # Token class
-class LexToken:
+class LexToken(object):
     def __str__(self):
-        return "LexToken(%s,%r,%d)" % (self.type,self.value,self.lineno)
+        return "LexToken(%s,%r,%d,%d)" % (self.type,self.value,self.lineno,self.lexpos)
     def __repr__(self):
         return str(self)
     def skip(self,n):
-        try:
-            self._skipn += n
-        except AttributeError:
-            self._skipn = n
+        self.lexer.skip(n)
 
 # -----------------------------------------------------------------------------
 # Lexer class
 #
+# This class encapsulates all of the methods and data associated with a lexer.
+#
 #    input()          -  Store a new string in the lexer
 #    token()          -  Get the next token
 # -----------------------------------------------------------------------------
 
 class Lexer:
     def __init__(self):
-        self.lexre = None           # Master regular expression
-        self.lexreflags = 0         # Option re compile flags
-        self.lexdata = None         # Actual input data (as a string)
-        self.lexpos = 0             # Current position in input text
-        self.lexlen = 0             # Length of the input text
-        self.lexindexfunc = [ ]     # Reverse mapping of groups to functions and types
-        self.lexerrorf = None       # Error rule (if any)
-        self.lextokens = None       # List of valid tokens
-        self.lexignore = None       # Ignored characters
-        self.lineno = 1             # Current line number
-        self.debug = 0              # Debugging mode
-        self.optimize = 0           # Optimized mode
-        self.token = self.errtoken
+        self.lexre = None             # Master regular expression. This is a list of 
+                                      # tuples (re,findex) where re is a compiled
+                                      # regular expression and findex is a list
+                                      # mapping regex group numbers to rules
+        self.lexretext = None         # Current regular expression strings
+        self.lexstatere = {}          # Dictionary mapping lexer states to master regexs
+        self.lexstateretext = {}      # Dictionary mapping lexer states to regex strings
+        self.lexstate = "INITIAL"     # Current lexer state
+        self.lexstatestack = []       # Stack of lexer states
+        self.lexstateinfo = None      # State information
+        self.lexstateignore = {}      # Dictionary of ignored characters for each state
+        self.lexstateerrorf = {}      # Dictionary of error functions for each state
+        self.lexreflags = 0           # Optional re compile flags
+        self.lexdata = None           # Actual input data (as a string)
+        self.lexpos = 0               # Current position in input text
+        self.lexlen = 0               # Length of the input text
+        self.lexerrorf = None         # Error rule (if any)
+        self.lextokens = None         # List of valid tokens
+        self.lexignore = ""           # Ignored characters
+        self.lexliterals = ""         # Literal characters that can be passed through
+        self.lexmodule = None         # Module
+        self.lineno = 1               # Current line number
+        self.lexdebug = 0             # Debugging mode
+        self.lexoptimize = 0          # Optimized mode
 
-    def __copy__(self):
+    def clone(self,object=None):
         c = Lexer()
-        c.lexre = self.lexre
+        c.lexstatere = self.lexstatere
+        c.lexstateinfo = self.lexstateinfo
+        c.lexstateretext = self.lexstateretext
+        c.lexstate = self.lexstate
+        c.lexstatestack = self.lexstatestack
+        c.lexstateignore = self.lexstateignore
+        c.lexstateerrorf = self.lexstateerrorf
         c.lexreflags = self.lexreflags
         c.lexdata = self.lexdata
         c.lexpos = self.lexpos
         c.lexlen = self.lexlen
-        c.lexindexfunc = self.lexindexfunc
-        c.lexerrorf = self.lexerrorf
         c.lextokens = self.lextokens
-        c.lexignore = self.lexignore
-        c.debug = self.debug
+        c.lexdebug = self.lexdebug
         c.lineno = self.lineno
-        c.optimize = self.optimize
-        c.token = c.realtoken
+        c.lexoptimize = self.lexoptimize
+        c.lexliterals = self.lexliterals
+        c.lexmodule   = self.lexmodule
+
+        # If the object parameter has been supplied, it means we are attaching the
+        # lexer to a new object.  In this case, we have to rebind all methods in
+        # the lexstatere and lexstateerrorf tables.
+
+        if object:
+            newtab = { }
+            for key, ritem in self.lexstatere.items():
+                newre = []
+                for cre, findex in ritem:
+                     newfindex = []
+                     for f in findex:
+                         if not f or not f[0]:
+                             newfindex.append(f)
+                             continue
+                         newfindex.append((getattr(object,f[0].__name__),f[1]))
+                newre.append((cre,newfindex))
+                newtab[key] = newre
+            c.lexstatere = newtab
+            c.lexstateerrorf = { }
+            for key, ef in self.lexstateerrorf.items():
+                c.lexstateerrorf[key] = getattr(object,ef.__name__)
+            c.lexmodule = object
+
+        # Set up other attributes
+        c.begin(c.lexstate)
         return c
 
     # ------------------------------------------------------------
+    # writetab() - Write lexer information to a table file
+    # ------------------------------------------------------------
+    def writetab(self,tabfile):
+        tf = open(tabfile+".py","w")
+        tf.write("# %s.py. This file automatically created by PLY (version %s). Don't edit!\n" % (tabfile,__version__))
+        tf.write("_lextokens    = %s\n" % repr(self.lextokens))
+        tf.write("_lexreflags   = %s\n" % repr(self.lexreflags))
+        tf.write("_lexliterals  = %s\n" % repr(self.lexliterals))
+        tf.write("_lexstateinfo = %s\n" % repr(self.lexstateinfo))
+        
+        tabre = { }
+        for key, lre in self.lexstatere.items():
+             titem = []
+             for i in range(len(lre)):
+                  titem.append((self.lexstateretext[key][i],_funcs_to_names(lre[i][1])))
+             tabre[key] = titem
+
+        tf.write("_lexstatere   = %s\n" % repr(tabre))
+        tf.write("_lexstateignore = %s\n" % repr(self.lexstateignore))
+
+        taberr = { }
+        for key, ef in self.lexstateerrorf.items():
+             if ef:
+                  taberr[key] = ef.__name__
+             else:
+                  taberr[key] = None
+        tf.write("_lexstateerrorf = %s\n" % repr(taberr))
+        tf.close()
+
+    # ------------------------------------------------------------
+    # readtab() - Read lexer information from a tab file
+    # ------------------------------------------------------------
+    def readtab(self,tabfile,fdict):
+        exec "import %s as lextab" % tabfile
+        self.lextokens      = lextab._lextokens
+        self.lexreflags     = lextab._lexreflags
+        self.lexliterals    = lextab._lexliterals
+        self.lexstateinfo   = lextab._lexstateinfo
+        self.lexstateignore = lextab._lexstateignore
+        self.lexstatere     = { }
+        self.lexstateretext = { }
+        for key,lre in lextab._lexstatere.items():
+             titem = []
+             txtitem = []
+             for i in range(len(lre)):
+                  titem.append((re.compile(lre[i][0],lextab._lexreflags),_names_to_funcs(lre[i][1],fdict)))
+                  txtitem.append(lre[i][0])
+             self.lexstatere[key] = titem
+             self.lexstateretext[key] = txtitem
+        self.lexstateerrorf = { }
+        for key,ef in lextab._lexstateerrorf.items():
+             self.lexstateerrorf[key] = fdict[ef]
+        self.begin('INITIAL')
+         
+    # ------------------------------------------------------------
     # input() - Push a new string into the lexer
     # ------------------------------------------------------------
     def input(self,s):
@@ -266,33 +202,58 @@
         self.lexdata = s
         self.lexpos = 0
         self.lexlen = len(s)
-        self.token = self.realtoken
-        
-        # Change the token routine to point to realtoken()
-        global token
-        if token == self.errtoken:
-            token = self.token
 
     # ------------------------------------------------------------
-    # errtoken() - Return error if token is called with no data
+    # begin() - Changes the lexing state
     # ------------------------------------------------------------
-    def errtoken(self):
-        raise RuntimeError, "No input string given with input()"
-    
+    def begin(self,state):
+        if not self.lexstatere.has_key(state):
+            raise ValueError, "Undefined state"
+        self.lexre = self.lexstatere[state]
+        self.lexretext = self.lexstateretext[state]
+        self.lexignore = self.lexstateignore.get(state,"")
+        self.lexerrorf = self.lexstateerrorf.get(state,None)
+        self.lexstate = state
+
     # ------------------------------------------------------------
+    # push_state() - Changes the lexing state and saves old on stack
+    # ------------------------------------------------------------
+    def push_state(self,state):
+        self.lexstatestack.append(self.lexstate)
+        self.begin(state)
+
+    # ------------------------------------------------------------
+    # pop_state() - Restores the previous state
+    # ------------------------------------------------------------
+    def pop_state(self):
+        self.begin(self.lexstatestack.pop())
+
+    # ------------------------------------------------------------
+    # current_state() - Returns the current lexing state
+    # ------------------------------------------------------------
+    def current_state(self):
+        return self.lexstate
+
+    # ------------------------------------------------------------
+    # skip() - Skip ahead n characters
+    # ------------------------------------------------------------
+    def skip(self,n):
+        self.lexpos += n
+
+    # ------------------------------------------------------------
     # token() - Return the next token from the Lexer
     #
     # Note: This function has been carefully implemented to be as fast
     # as possible.  Don't make changes unless you really know what
     # you are doing
     # ------------------------------------------------------------
-    def realtoken(self):
+    def token(self):
         # Make local copies of frequently referenced attributes
         lexpos    = self.lexpos
         lexlen    = self.lexlen
         lexignore = self.lexignore
         lexdata   = self.lexdata
-        
+
         while lexpos < lexlen:
             # This code provides some short-circuit code for whitespace, tabs, and other ignored characters
             if lexdata[lexpos] in lexignore:
@@ -300,71 +261,96 @@
                 continue
 
             # Look for a regular expression match
-            m = self.lexre.match(lexdata,lexpos)
-            if m:
-                i = m.lastindex
-                lexpos = m.end()
+            for lexre,lexindexfunc in self.lexre:
+                m = lexre.match(lexdata,lexpos)
+                if not m: continue
+
+                # Set last match in lexer so that rules can access it if they want
+                self.lexmatch = m
+
+                # Create a token for return
                 tok = LexToken()
                 tok.value = m.group()
                 tok.lineno = self.lineno
+                tok.lexpos = lexpos
                 tok.lexer = self
-                func,tok.type = self.lexindexfunc[i]
+
+                lexpos = m.end()
+                i = m.lastindex
+                func,tok.type = lexindexfunc[i]
+                self.lexpos = lexpos
+
                 if not func:
-                    self.lexpos = lexpos
-                    return tok
-                
+                   # If no token type was set, it's an ignored token
+                   if tok.type: return tok      
+                   break
+
+                # if func not callable, it means it's an ignored token                
+                if not callable(func):
+                   break 
+
                 # If token is processed by a function, call it
-                self.lexpos = lexpos
                 newtok = func(tok)
-                self.lineno = tok.lineno     # Update line number
                 
                 # Every function must return a token, if nothing, we just move to next token
-                if not newtok: continue
+                if not newtok: 
+                    lexpos = self.lexpos        # This is here in case user has updated lexpos.
+                    break
                 
                 # Verify type of the token.  If not in the token map, raise an error
-                if not self.optimize:
+                if not self.lexoptimize:
                     if not self.lextokens.has_key(newtok.type):
                         raise LexError, ("%s:%d: Rule '%s' returned an unknown token type '%s'" % (
                             func.func_code.co_filename, func.func_code.co_firstlineno,
                             func.__name__, newtok.type),lexdata[lexpos:])
 
                 return newtok
+            else:
+                # No match, see if in literals
+                if lexdata[lexpos] in self.lexliterals:
+                    tok = LexToken()
+                    tok.value = lexdata[lexpos]
+                    tok.lineno = self.lineno
+                    tok.lexer = self
+                    tok.type = tok.value
+                    tok.lexpos = lexpos
+                    self.lexpos = lexpos + 1
+                    return tok
+        
+                # No match. Call t_error() if defined.
+                if self.lexerrorf:
+                    tok = LexToken()
+                    tok.value = self.lexdata[lexpos:]
+                    tok.lineno = self.lineno
+                    tok.type = "error"
+                    tok.lexer = self
+                    tok.lexpos = lexpos
+                    self.lexpos = lexpos
+                    newtok = self.lexerrorf(tok)
+                    if lexpos == self.lexpos:
+                        # Error method didn't change text position at all. This is an error.
+                        raise LexError, ("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:])
+                    lexpos = self.lexpos
+                    if not newtok: continue
+                    return newtok
 
-            # No match. Call t_error() if defined.
-            if self.lexerrorf:
-                tok = LexToken()
-                tok.value = self.lexdata[lexpos:]
-                tok.lineno = self.lineno
-                tok.type = "error"
-                tok.lexer = self
-                oldpos = lexpos
-                newtok = self.lexerrorf(tok)
-                lexpos += getattr(tok,"_skipn",0)
-                if oldpos == lexpos:
-                    # Error method didn't change text position at all. This is an error.
-                    self.lexpos = lexpos
-                    raise LexError, ("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:])
-                if not newtok: continue
                 self.lexpos = lexpos
-                return newtok
+                raise LexError, ("Illegal character '%s' at index %d" % (lexdata[lexpos],lexpos), lexdata[lexpos:])
 
-            self.lexpos = lexpos
-            raise LexError, ("No match found", lexdata[lexpos:])
-
-        # No more input data
         self.lexpos = lexpos + 1
+        if self.lexdata is None:
+             raise RuntimeError, "No input string given with input()"
         return None
-
         
 # -----------------------------------------------------------------------------
-# validate_file()
+# _validate_file()
 #
 # This checks to see if there are duplicated t_rulename() functions or strings
 # in the parser input file.  This is done using a simple regular expression
 # match on each line in the filename.
 # -----------------------------------------------------------------------------
 
-def validate_file(filename):
+def _validate_file(filename):
     import os.path
     base,ext = os.path.splitext(filename)
     if ext != '.py': return 1        # No idea what the file is. Return OK
@@ -397,41 +383,120 @@
     return noerror
 
 # -----------------------------------------------------------------------------
-# _read_lextab(module)
+# _funcs_to_names()
 #
-# Reads lexer table from a lextab file instead of using introspection.
+# Given a list of regular expression functions, this converts it to a list
+# suitable for output to a table file
 # -----------------------------------------------------------------------------
 
-def _read_lextab(lexer, fdict, module):
-    exec "import %s as lextab" % module
-    lexer.lexre = re.compile(lextab._lexre, re.VERBOSE | lextab._lexreflags)
-    lexer.lexreflags = lextab._lexreflags
-    lexer.lexindexfunc = lextab._lextab
-    for i in range(len(lextab._lextab)):
-        t = lexer.lexindexfunc[i]
-        if t:
-            if t[0]:
-                lexer.lexindexfunc[i] = (fdict[t[0]],t[1])
-    lexer.lextokens = lextab._lextokens
-    lexer.lexignore = lextab._lexignore
-    if lextab._lexerrorf:
-        lexer.lexerrorf = fdict[lextab._lexerrorf]
-        
+def _funcs_to_names(funclist):
+    result = []
+    for f in funclist:
+         if f and f[0]:
+             result.append((f[0].__name__,f[1]))
+         else:
+             result.append(f)
+    return result
+
 # -----------------------------------------------------------------------------
+# _names_to_funcs()
+#
+# Given a list of regular expression function names, this converts it back to
+# functions.
+# -----------------------------------------------------------------------------
+
+def _names_to_funcs(namelist,fdict):
+     result = []
+     for n in namelist:
+          if n and n[0]:
+              result.append((fdict[n[0]],n[1]))
+          else:
+              result.append(n)
+     return result
+
+# -----------------------------------------------------------------------------
+# _form_master_re()
+#
+# This function takes a list of all of the regex components and attempts to
+# form the master regular expression.  Given limitations in the Python re
+# module, it may be necessary to break the master regex into separate expressions.
+# -----------------------------------------------------------------------------
+
+def _form_master_re(relist,reflags,ldict):
+    if not relist: return []
+    regex = "|".join(relist)
+    try:
+        lexre = re.compile(regex,re.VERBOSE | reflags)
+
+        # Build the index to function map for the matching engine
+        lexindexfunc = [ None ] * (max(lexre.groupindex.values())+1)
+        for f,i in lexre.groupindex.items():
+            handle = ldict.get(f,None)
+            if type(handle) in (types.FunctionType, types.MethodType):
+                lexindexfunc[i] = (handle,handle.__name__[2:])
+            elif handle is not None:
+                # If rule was specified as a string, we build an anonymous
+                # callback function to carry out the action
+                if f.find("ignore_") > 0:
+                    lexindexfunc[i] = (None,None)
+                    print "IGNORE", f
+                else:
+                    lexindexfunc[i] = (None, f[2:])
+         
+        return [(lexre,lexindexfunc)],[regex]
+    except Exception,e:
+        m = int(len(relist)/2)
+        if m == 0: m = 1
+        llist, lre = _form_master_re(relist[:m],reflags,ldict)
+        rlist, rre = _form_master_re(relist[m:],reflags,ldict)
+        return llist+rlist, lre+rre
+
+# -----------------------------------------------------------------------------
+# def _statetoken(s,names)
+#
+# Given a declaration name s of the form "t_" and a dictionary whose keys are
+# state names, this function returns a tuple (states,tokenname) where states
+# is a tuple of state names and tokenname is the name of the token.  For example,
+# calling this with s = "t_foo_bar_SPAM" might return (('foo','bar'),'SPAM')
+# -----------------------------------------------------------------------------
+
+def _statetoken(s,names):
+    nonstate = 1
+    parts = s.split("_")
+    for i in range(1,len(parts)):
+         if not names.has_key(parts[i]) and parts[i] != 'ANY': break
+    if i > 1:
+       states = tuple(parts[1:i])
+    else:
+       states = ('INITIAL',)
+
+    if 'ANY' in states:
+       states = tuple(names.keys())
+      
+    tokenname = "_".join(parts[i:])
+    return (states,tokenname)
+
+# -----------------------------------------------------------------------------
 # lex(module)
 #
 # Build all of the regular expression rules from definitions in the supplied module
 # -----------------------------------------------------------------------------
-def lex(module=None,debug=0,optimize=0,lextab="lextab",reflags=0):
+def lex(module=None,object=None,debug=0,optimize=0,lextab="lextab",reflags=0,nowarn=0):
+    global lexer
     ldict = None
-    regex = ""
+    stateinfo  = { 'INITIAL' : 'inclusive'}
     error = 0
     files = { }
-    lexer = Lexer()
-    lexer.debug = debug
-    lexer.optimize = optimize
+    lexobj = Lexer()
+    lexobj.lexdebug = debug
+    lexobj.lexoptimize = optimize
     global token,input
+
+    if nowarn: warn = 0
+    else: warn = 1
     
+    if object: module = object
+
     if module:
         # User supplied a module object.
         if isinstance(module, types.ModuleType):
@@ -443,6 +508,7 @@
                 ldict[i] = v
         else:
             raise ValueError,"Expected a module or instance"
+        lexobj.lexmodule = module
         
     else:
         # No...
 
[truncated message content] | 
| 
      
      
      From: <ssm...@us...> - 2007-09-10 19:21:57
       | 
| Revision: 2551
          http://selinux.svn.sourceforge.net/selinux/?rev=2551&view=rev
Author:   ssmalley
Date:     2007-09-10 12:21:52 -0700 (Mon, 10 Sep 2007)
Log Message:
-----------
Author: Karl MacMillan
Email: kma...@me...
Subject: Expand sepolgen parser to parse all modules
Date: Mon, 03 Sep 2007 12:21:11 -0400
Expand the sepolgen parser so that it is capable of parsing all of the current
reference policy modules in addition to the headers. The parser likely needs
some more cleanup (it is currently very ambigius, though this doesn't seem to
cause any harm in practice).
Signed-off-by: User "Karl MacMillan <kma...@me...>"
Modified Paths:
--------------
    trunk/sepolgen/src/sepolgen/refparser.py
    trunk/sepolgen/src/sepolgen/refpolicy.py
Modified: trunk/sepolgen/src/sepolgen/refparser.py
===================================================================
--- trunk/sepolgen/src/sepolgen/refparser.py	2007-09-10 19:20:32 UTC (rev 2550)
+++ trunk/sepolgen/src/sepolgen/refparser.py	2007-09-10 19:21:52 UTC (rev 2551)
@@ -1,6 +1,6 @@
 # Authors: Karl MacMillan <kma...@me...>
 #
-# Copyright (C) 2006 Red Hat
+# Copyright (C) 2006-2007 Red Hat
 # see file 'COPYING' for use and warranty information
 #
 # This program is free software; you can redistribute it and/or
@@ -32,6 +32,7 @@
 import sys
 import os
 import re
+import traceback
 
 import refpolicy
 import access
@@ -65,7 +66,23 @@
     'EXPL',
     'EQUAL',
     'IDENTIFIER',
+    'NUMBER',
+    'PATH',
+    'IPV6_ADDR',
     # reserved words
+    #   module
+    'MODULE',
+    'POLICY_MODULE',
+    'REQUIRE',
+    #   flask
+    'SID',
+    'GENFSCON',
+    'FS_USE_XATTR',
+    'FS_USE_TRANS',
+    'FS_USE_TASK',
+    'PORTCON',
+    'NODECON',
+    'NETIFCON',
     #   object classes
     'CLASS',
     #   types and attributes
@@ -76,6 +93,8 @@
     'TYPEALIAS',
     #   conditional policy
     'BOOL',
+    'TRUE',
+    'FALSE',
     'IF',
     'ELSE',
     #   users and roles
@@ -85,6 +104,7 @@
     'ALLOW',
     'DONTAUDIT',
     'AUDITALLOW',
+    'NEVERALLOW',
     'TYPE_TRANSITION',
     'TYPE_CHANGE',
     'TYPE_MEMBER',
@@ -96,6 +116,7 @@
     'TUNABLE_POLICY',
     'GEN_REQ',
     'TEMPLATE',
+    'GEN_CONTEXT',
     #   m4
     'IFDEF',
     'IFNDEF',
@@ -105,6 +126,19 @@
 # All reserved keywords - see t_IDENTIFIER for how these are matched in
 # the lexer.
 reserved = {
+    # module
+    'module' : 'MODULE',
+    'policy_module' : 'POLICY_MODULE',
+    'require' : 'REQUIRE',
+    # flask
+    'sid' : 'SID',
+    'genfscon' : 'GENFSCON',
+    'fs_use_xattr' : 'FS_USE_XATTR',
+    'fs_use_trans' : 'FS_USE_TRANS',
+    'fs_use_task' : 'FS_USE_TASK',
+    'portcon' : 'PORTCON',
+    'nodecon' : 'NODECON',
+    'netifcon' : 'NETIFCON',
     # object classes
     'class' : 'CLASS',
     # types and attributes
@@ -115,6 +149,8 @@
     'typealias' : 'TYPEALIAS',
     # conditional policy
     'bool' : 'BOOL',
+    'true' : 'TRUE',
+    'false' : 'FALSE',
     'if' : 'IF',
     'else' : 'ELSE',
     # users and roles
@@ -124,6 +160,7 @@
     'allow' : 'ALLOW',
     'dontaudit' : 'DONTAUDIT',
     'auditallow' : 'AUDITALLOW',
+    'neverallow' : 'NEVERALLOW',
     'type_transition' : 'TYPE_TRANSITION',
     'type_change' : 'TYPE_CHANGE',
     'type_member' : 'TYPE_MEMBER',
@@ -135,6 +172,7 @@
     'tunable_policy' : 'TUNABLE_POLICY',
     'gen_require' : 'GEN_REQ',
     'template' : 'TEMPLATE',
+    'gen_context' : 'GEN_CONTEXT',
     # M4
     'ifndef' : 'IFNDEF',
     'ifdef' : 'IFDEF',
@@ -162,26 +200,34 @@
 t_BAR       = r'\|'
 t_EXPL      = r'\!'
 t_EQUAL     = r'\='
+t_NUMBER    = r'[0-9\.]+'
+t_PATH      = r'/[a-zA-Z0-9)_\.\*/]*'
+#t_IPV6_ADDR = r'[a-fA-F0-9]{0,4}:[a-fA-F0-9]{0,4}:([a-fA-F0-9]{0,4}:)*'
 
 # Ignore whitespace - this is a special token for ply that more efficiently
 # ignores uninteresting tokens.
 t_ignore    = " \t"
 
 # More complex tokens
+def t_IPV6_ADDR(t):
+    r'[a-fA-F0-9]{0,4}:[a-fA-F0-9]{0,4}:([a-fA-F0-9]|:)*'
+    # This is a function simply to force it sooner into
+    # the regex list
+    return t
 
 def t_m4comment(t):
     r'dnl.*\n'
     # Ignore all comments
-    t.lineno += 1
+    t.lexer.lineno += 1
 
 def t_refpolicywarn(t):
     r'refpolicywarn\(.*\n'
     # Ignore refpolicywarn statements - they sometimes
     # contain text that we can't parse.
-    t.lineno += 1
-    
+    t.lexer.lineno += 1
+
 def t_IDENTIFIER(t):
-    r'[a-zA-Z_\$][a-zA-Z0-9_\.\$\*]*'
+    r'[a-zA-Z_\$][a-zA-Z0-9_\-\.\$\*]*'
     # Handle any keywords
     t.type = reserved.get(t.value,'IDENTIFIER')
     return t
@@ -189,7 +235,7 @@
 def t_comment(t):
     r'\#.*\n'
     # Ignore all comments
-    t.lineno += 1
+    t.lexer.lineno += 1
 
 def t_error(t):
     print "Illegal character '%s'" % t.value[0]
@@ -197,7 +243,7 @@
 
 def t_newline(t):
     r'\n+'
-    t.lineno += len(t.value)
+    t.lexer.lineno += len(t.value)
 
 # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
 #
@@ -243,137 +289,40 @@
                   | statements statement
                   | empty
     '''
-    if len(p) == 2:
+    if len(p) == 2 and p[1]:
         m.children.append(p[1])
-    elif len(p) > 2:
+    elif len(p) > 2 and p[2]:
         m.children.append(p[2])
 
 def p_statement(p):
     '''statement : interface
                  | template
                  | obj_perm_set
+                 | policy
+                 | policy_module_stmt
+                 | module_stmt
     '''
     p[0] = p[1]
 
-# Basic terminals - identifiers and lists of identifiers. These must
-# be handled somewhat gracefully. Names returns an IdSet and care must
-# be taken that this is _assigned_ to an object to correctly update
-# all of the flags (as opposed to using update). The other terminals
-# return list - this is to preserve ordering if it is important for
-# parsing (for example, interface_call must retain the ordering). Other
-# times the list should be used to update an IdSet.
-
-def p_names(p):
-    '''names : identifier
-             | nested_id_set
-             | asterisk
-             | TILDE identifier
-             | TILDE nested_id_set
-             | IDENTIFIER MINUS IDENTIFIER
-    '''
-    s = refpolicy.IdSet()
-    if len(p) < 3:
-        expand(p[1], s)
-    elif len(p) == 3:
-        expand(p[2], s)
-        s.compliment = True
-    else:
-        expand([p[1]])
-        s.add("-" + p[3])
-    p[0] = s
-
-def p_identifier(p):
-    'identifier : IDENTIFIER'
-    p[0] = [p[1]]
-
-def p_asterisk(p):
-    'asterisk : ASTERISK'
-    p[0] = [p[1]]
-
-def p_nested_id_set(p):
-    '''nested_id_set : OBRACE nested_id_list CBRACE
-    '''
-    p[0] = p[2]
-
-def p_nested_id_list(p):
-    '''nested_id_list : nested_id_element
-                      | nested_id_list nested_id_element
-    '''
-    if len(p) == 2:
-        p[0] = p[1]
-    else:
-        p[0] = p[1] + p[2]
-
-def p_nested_id_element(p):
-    '''nested_id_element : identifier
-                         | MINUS IDENTIFIER
-                         | nested_id_set
-    '''
-    if len(p) == 2:
-        p[0] = p[1]
-    else:
-        # For now just leave the '-'
-        str = "-" + p[2]
-        p[0] = [str]
-
-def p_interface_call_param(p):
-    '''interface_call_param : IDENTIFIER
-                            | IDENTIFIER MINUS IDENTIFIER
-                            | nested_id_set
-    '''
-    # Intentionally let single identifiers pass through
-    # List means set, non-list identifier
-    if len(p) == 2:
-        p[0] = p[1]
-    else:
-        p[0] = [p[1], "-" + p[3]]
-
-def p_interface_call_param_list(p):
-    '''interface_call_param_list : interface_call_param
-                                 | interface_call_param_list COMMA interface_call_param
-    '''
-    if len(p) == 2:
-        p[0] = [p[1]]
-    else:
-        p[0] = p[1] + [p[3]]
-
-
-def p_comma_list(p):
-    '''comma_list : nested_id_list
-                  | comma_list COMMA nested_id_list
-    '''
-    if len(p) > 2:
-        p[1] = p[1] + p[3]
-    p[0] = p[1]
-
-def p_optional_semi(p):
-    '''optional_semi : SEMI
-                   | empty'''
-    pass
-
-def p_cond_expr(p):
-    '''cond_expr : IDENTIFIER
-                 | EXPL cond_expr
-                 | cond_expr AMP AMP cond_expr
-                 | cond_expr BAR BAR cond_expr
-                 | cond_expr EQUAL EQUAL cond_expr
-                 | cond_expr EXPL EQUAL cond_expr
-    '''
-    l = len(p)
-    if l == 2:
-        p[0] = [p[1]]
-    elif l == 3:
-        p[0] = [p[1]] + p[2]
-    else:
-        p[0] = p[1] + [p[2] + p[3]] + p[4]
-
-
 def p_empty(p):
     'empty :'
     pass
 
+#
 # Reference policy language constructs
+#
 
+# This is for the policy module statement (e.g., policy_module(foo,1.2.0)).
+# We have a separate terminal for either the basic language module statement
+# and interface calls to make it easier to identifier.
+def p_policy_module_stmt(p):
+    'policy_module_stmt : POLICY_MODULE OPAREN IDENTIFIER COMMA NUMBER CPAREN'
+    m = refpolicy.ModuleDeclaration()
+    m.name = p[3]
+    m.version = p[5]
+    m.refpolicy = True
+    p[0] = m
+
 def p_interface(p):
     '''interface : INTERFACE OPAREN TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN
     '''
@@ -389,22 +338,37 @@
     collect(p[8], x)
     p[0] = x
 
+def p_define(p):
+    '''define : DEFINE OPAREN TICK IDENTIFIER SQUOTE CPAREN'''
+    # This is for defining single M4 values (to be used later in ifdef statements).
+    # Example: define(`sulogin_no_pam'). We don't currently do anything with these
+    # but we should in the future when we correctly resolve ifdef statements.
+    p[0] = None
+
 def p_interface_stmts(p):
     '''interface_stmts : policy
                        | interface_stmts policy
                        | empty
     '''
-    if len(p) == 2:
+    if len(p) == 2 and p[1]:
         p[0] = p[1]
     elif len(p) > 2:
-        p[0] = p[1] + p[2]
+        if not p[1]:
+            if p[2]:
+                p[0] = p[2]
+        elif not p[2]:
+            p[0] = p[1]
+        else:
+            p[0] = p[1] + p[2]
 
 def p_optional_policy(p):
+    '''optional_policy : OPT_POLICY OPAREN TICK interface_stmts SQUOTE CPAREN
+                       | OPT_POLICY OPAREN TICK interface_stmts SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN
     '''
-    optional_policy : OPT_POLICY OPAREN TICK interface_stmts SQUOTE CPAREN
-    '''
     o = refpolicy.OptionalPolicy()
-    o.children = p[4]
+    collect(p[4], o, val=True)
+    if len(p) > 7:
+        collect(p[8], o, val=False)
     p[0] = [o]
 
 def p_tunable_policy(p):
@@ -434,19 +398,48 @@
     p[0] = [x]
 
 def p_interface_call(p):
-    'interface_call : IDENTIFIER OPAREN interface_call_param_list CPAREN'
+    '''interface_call : IDENTIFIER OPAREN interface_call_param_list CPAREN
+                      | IDENTIFIER OPAREN CPAREN
+                      | IDENTIFIER OPAREN interface_call_param_list CPAREN SEMI'''
+    # Allow spurious semi-colons at the end of interface calls
     i = refpolicy.InterfaceCall(ifname=p[1])
-
-    i.args.extend(p[3])
+    if len(p) > 4:
+        i.args.extend(p[3])
     p[0] = i
 
+def p_interface_call_param(p):
+    '''interface_call_param : IDENTIFIER
+                            | IDENTIFIER MINUS IDENTIFIER
+                            | nested_id_set
+                            | TRUE
+                            | FALSE
+    '''
+    # Intentionally let single identifiers pass through
+    # List means set, non-list identifier
+    if len(p) == 2:
+        p[0] = p[1]
+    else:
+        p[0] = [p[1], "-" + p[3]]
+
+def p_interface_call_param_list(p):
+    '''interface_call_param_list : interface_call_param
+                                 | interface_call_param_list COMMA interface_call_param
+    '''
+    if len(p) == 2:
+        p[0] = [p[1]]
+    else:
+        p[0] = p[1] + [p[3]]
+
+
 def p_obj_perm_set(p):
     'obj_perm_set : DEFINE OPAREN TICK IDENTIFIER SQUOTE COMMA TICK names SQUOTE CPAREN'
     s = refpolicy.ObjPermSet(p[4])
     s.perms = p[8]
     p[0] = s
-
+    
+#
 # Basic SELinux policy language
+#
 
 def p_policy(p):
     '''policy : policy_stmt
@@ -470,11 +463,29 @@
                    | attribute_def
                    | range_transition_def
                    | role_transition_def
+                   | bool
+                   | define
+                   | initial_sid
+                   | genfscon
+                   | fs_use
+                   | portcon
+                   | nodecon
+                   | netifcon
     '''
-    p[0] = [p[1]]
+    if p[1]:
+        p[0] = [p[1]]
 
+def p_module_stmt(p):
+    'module_stmt : MODULE IDENTIFIER NUMBER SEMI'
+    m = refpolicy.ModuleDeclaration()
+    m.name = p[2]
+    m.version = p[3]
+    m.refpolicy = False
+    p[0] = m
+
 def p_gen_require(p):
-    'gen_require : GEN_REQ OPAREN TICK requires SQUOTE CPAREN'
+    '''gen_require : GEN_REQ OPAREN TICK requires SQUOTE CPAREN
+                   | REQUIRE OBRACE requires CBRACE'''
     # We ignore the require statements - they are redundant data from our point-of-view.
     # Checkmodule will verify them later anyway so we just assume that they match what
     # is in the rest of the interface.
@@ -497,6 +508,121 @@
     '''
     pass
 
+def p_security_context(p):
+    '''security_context : IDENTIFIER COLON IDENTIFIER COLON IDENTIFIER
+                        | IDENTIFIER COLON IDENTIFIER COLON IDENTIFIER COLON mls_range_def'''
+    # This will likely need some updates to handle complex levels
+    s = refpolicy.SecurityContext()
+    s.user = p[1]
+    s.role = p[3]
+    s.type = p[5]
+    if len(p) > 6:
+        s.level = p[7]
+
+    p[0] = s
+
+def p_gen_context(p):
+    '''gen_context : GEN_CONTEXT OPAREN security_context COMMA mls_range_def CPAREN
+    '''
+    # We actually store gen_context statements in a SecurityContext
+    # object - it knows how to output either a bare context or a
+    # gen_context statement.
+    s = p[3]
+    s.level = p[5]
+    
+    p[0] = s
+
+def p_context(p):
+    '''context : security_context
+               | gen_context
+    '''
+    p[0] = p[1]
+
+def p_initial_sid(p):
+    '''initial_sid : SID IDENTIFIER context'''
+    s = refpolicy.InitialSid()
+    s.name = p[2]
+    s.context = p[3]
+    p[0] = s
+
+def p_genfscon(p):
+    '''genfscon : GENFSCON IDENTIFIER PATH context'''
+    
+    g = refpolicy.GenfsCon()
+    g.filesystem = p[2]
+    g.path = p[3]
+    g.context = p[4]
+
+    p[0] = g
+
+def p_fs_use(p):
+    '''fs_use : FS_USE_XATTR IDENTIFIER context SEMI
+              | FS_USE_TASK IDENTIFIER context SEMI
+              | FS_USE_TRANS IDENTIFIER context SEMI
+    '''
+    f = refpolicy.FilesystemUse()
+    if p[1] == "fs_use_xattr":
+        f.type = refpolicy.FilesystemUse.XATTR
+    elif p[1] == "fs_use_task":
+        f.type = refpolicy.FilesystemUse.TASK
+    elif p[1] == "fs_use_trans":
+        f.type = refpolicy.FilesystemUse.TRANS
+
+    f.filesystem = p[2]
+    f.context = p[3]
+
+    p[0] = f
+
+def p_portcon(p):
+    '''portcon : PORTCON IDENTIFIER NUMBER context
+               | PORTCON IDENTIFIER NUMBER MINUS NUMBER context'''
+    c = refpolicy.PortCon()
+    c.port_type = p[2]
+    if len(p) == 5:
+        c.port_number = p[3]
+        c.context = p[4]
+    else:
+        c.port_number = p[3] + "-" + p[4]
+        c.context = p[5]
+
+    p[0] = c
+
+def p_nodecon(p):
+    '''nodecon : NODECON NUMBER NUMBER context
+               | NODECON IPV6_ADDR IPV6_ADDR context
+    '''
+    n = refpolicy.NodeCon()
+    n.start = p[2]
+    n.end = p[3]
+    n.context = p[4]
+
+    p[0] = n
+
+def p_netifcon(p):
+    'netifcon : NETIFCON IDENTIFIER context context'
+    n = refpolicy.NetifCon()
+    n.interface = p[2]
+    n.interface_context = p[3]
+    n.packet_context = p[4]
+
+    p[0] = n
+
+def p_mls_range_def(p):
+    '''mls_range_def : mls_level_def MINUS mls_level_def
+                     | mls_level_def
+    '''
+    p[0] = p[1]
+    if len(p) > 2:
+        p[0] = p[0] + "-" + p[3]
+
+def p_mls_level_def(p):
+    '''mls_level_def : IDENTIFIER COLON comma_list
+                     | IDENTIFIER
+    '''
+    p[0] = p[1]
+    if len(p) > 2:
+        p[0] = p[0] + ":" + ",".join(p[3])
+    
 def p_type_def(p):
     '''type_def : TYPE IDENTIFIER COMMA comma_list SEMI
                 | TYPE IDENTIFIER SEMI
@@ -528,10 +654,12 @@
     p[0] = t
 
 def p_role_def(p):
-    'role_def : ROLE IDENTIFIER TYPES comma_list SEMI'
+    '''role_def : ROLE IDENTIFIER TYPES comma_list SEMI
+                | ROLE IDENTIFIER SEMI'''
     r = refpolicy.Role()
     r.role = p[2]
-    r.types.update(p[4])
+    if len(p) > 4:
+        r.types.update(p[4])
     p[0] = r
 
 def p_role_allow(p):
@@ -545,12 +673,15 @@
     '''avrule_def : ALLOW names names COLON names names SEMI
                   | DONTAUDIT names names COLON names names SEMI
                   | AUDITALLOW names names COLON names names SEMI
+                  | NEVERALLOW names names COLON names names SEMI
     '''
     a = refpolicy.AVRule()
     if p[1] == 'dontaudit':
         a.rule_type = refpolicy.AVRule.DONTAUDIT
     elif p[1] == 'auditallow':
         a.rule_type = refpolicy.AVRule.AUDITALLOW
+    elif p[1] == 'neverallow':
+        a.rule_type = refpolicy.AVRule.NEVERALLOW
     a.src_types = p[2]
     a.tgt_types = p[3]
     a.obj_classes = p[5]
@@ -573,6 +704,17 @@
     t.dest_type = p[6]
     p[0] = t
 
+def p_bool(p):
+    '''bool : BOOL IDENTIFIER TRUE SEMI
+            | BOOL IDENTIFIER FALSE SEMI'''
+    b = refpolicy.Bool()
+    b.name = p[2]
+    if p[3] == "true":
+        b.state = True
+    else:
+        b.state = False
+    p[0] = b
+
 def p_conditional(p):
     ''' conditional : IF OPAREN cond_expr CPAREN OBRACE interface_stmts CBRACE
                     | IF OPAREN cond_expr CPAREN OBRACE interface_stmts CBRACE ELSE OBRACE interface_stmts CBRACE
@@ -591,18 +733,6 @@
     t.attributes.update(p[3])
     p[0] = t
 
-def p_mls_level_def(p):
-    '''mls_level_def : IDENTIFIER COLON comma_list
-                     | IDENTIFIER'''
-    pass
-
-def p_mls_range_def(p):
-    '''mls_range_def : mls_level_def MINUS mls_level_def
-                     | mls_level_def
-    '''
-    pass
-
-
 def p_range_transition_def(p):
     '''range_transition_def : RANGE_TRANSITION names names COLON names mls_range_def SEMI
                             | RANGE_TRANSITION names names names SEMI'''
@@ -612,6 +742,106 @@
     '''role_transition_def : ROLE_TRANSITION names names names SEMI'''
     pass
 
+def p_cond_expr(p):
+    '''cond_expr : IDENTIFIER
+                 | EXPL cond_expr
+                 | cond_expr AMP AMP cond_expr
+                 | cond_expr BAR BAR cond_expr
+                 | cond_expr EQUAL EQUAL cond_expr
+                 | cond_expr EXPL EQUAL cond_expr
+    '''
+    l = len(p)
+    if l == 2:
+        p[0] = [p[1]]
+    elif l == 3:
+        p[0] = [p[1]] + p[2]
+    else:
+        p[0] = p[1] + [p[2] + p[3]] + p[4]
+
+
+#
+# Basic terminals
+#
+
+# Identifiers and lists of identifiers. These must
+# be handled somewhat gracefully. Names returns an IdSet and care must
+# be taken that this is _assigned_ to an object to correctly update
+# all of the flags (as opposed to using update). The other terminals
+# return list - this is to preserve ordering if it is important for
+# parsing (for example, interface_call must retain the ordering). Other
+# times the list should be used to update an IdSet.
+
+def p_names(p):
+    '''names : identifier
+             | nested_id_set
+             | asterisk
+             | TILDE identifier
+             | TILDE nested_id_set
+             | IDENTIFIER MINUS IDENTIFIER
+    '''
+    s = refpolicy.IdSet()
+    if len(p) < 3:
+        expand(p[1], s)
+    elif len(p) == 3:
+        expand(p[2], s)
+        s.compliment = True
+    else:
+        expand([p[1]])
+        s.add("-" + p[3])
+    p[0] = s
+
+def p_identifier(p):
+    'identifier : IDENTIFIER'
+    p[0] = [p[1]]
+
+def p_asterisk(p):
+    'asterisk : ASTERISK'
+    p[0] = [p[1]]
+
+def p_nested_id_set(p):
+    '''nested_id_set : OBRACE nested_id_list CBRACE
+    '''
+    p[0] = p[2]
+
+def p_nested_id_list(p):
+    '''nested_id_list : nested_id_element
+                      | nested_id_list nested_id_element
+    '''
+    if len(p) == 2:
+        p[0] = p[1]
+    else:
+        p[0] = p[1] + p[2]
+
+def p_nested_id_element(p):
+    '''nested_id_element : identifier
+                         | MINUS IDENTIFIER
+                         | nested_id_set
+    '''
+    if len(p) == 2:
+        p[0] = p[1]
+    else:
+        # For now just leave the '-'
+        str = "-" + p[2]
+        p[0] = [str]
+
+def p_comma_list(p):
+    '''comma_list : nested_id_list
+                  | comma_list COMMA nested_id_list
+    '''
+    if len(p) > 2:
+        p[1] = p[1] + p[3]
+    p[0] = p[1]
+
+def p_optional_semi(p):
+    '''optional_semi : SEMI
+                   | empty'''
+    pass
+
+
+#
+# Interface to the parser
+#
+
 def p_error(tok):
     global error
     error = "Syntax error on line %d %s [type=%s]" % (tok.lineno, tok.value, tok.type)
@@ -624,8 +854,6 @@
     for x in spt:
         map[x.name] = x
 
-
-
 parser = None
 lexer = None
 def create_globals(module, support, debug):
@@ -648,12 +876,13 @@
     create_globals(module, support, debug)
     lexer.lexdata = []
     lexer.lexpos = 0
+    lexer.lineno = 1
 
     try:
         parser.parse(text, debug=debug)
     except Exception, e:
         global error
-        error = "internal parser error: %s" % str(e)
+        error = "internal parser error: %s" % str(e) + "\n" + traceback.format_exc()
 
     if error is not None:
         msg = 'could not parse text: "%s"' % error
@@ -733,7 +962,7 @@
         headers.children.append(spt)
 
         # FIXME: Total hack - add in can_exec rather than parse the insanity
-        # of misc_macros. We are just going to preten that this is an interface
+        # of misc_macros. We are just going to pretend that this is an interface
         # to make the expansion work correctly.
         can_exec = refpolicy.Interface("can_exec")
         av = access.AccessVector(["$1","$2","file","execute_no_trans","read",
Modified: trunk/sepolgen/src/sepolgen/refpolicy.py
===================================================================
--- trunk/sepolgen/src/sepolgen/refpolicy.py	2007-09-10 19:20:32 UTC (rev 2550)
+++ trunk/sepolgen/src/sepolgen/refpolicy.py	2007-09-10 19:21:52 UTC (rev 2551)
@@ -49,7 +49,12 @@
 
 # Base Classes
 
-class Node:
+class PolicyBase:
+    def __init__(self, parent=None):
+        self.parent = None
+        self.comment = None
+
+class Node(PolicyBase):
     """Base class objects produced from parsing the reference policy.
 
     The Node class is used as the base class for any non-leaf
@@ -67,9 +72,8 @@
     """
 
     def __init__(self, parent=None):
-        self.parent = parent
+        PolicyBase.__init__(self, parent)
         self.children = []
-        self.comment = None
 
     def __iter__(self):
         return iter(self.children)
@@ -131,9 +135,9 @@
         return ""
 
 
-class Leaf:
-    def __init__(self):
-        self.comment = None
+class Leaf(PolicyBase):
+    def __init__(self, parent=None):
+        PolicyBase.__init__(self, parent)
 
     def __str__(self):
         if self.comment:
@@ -244,14 +248,14 @@
 
 class SecurityContext(Leaf):
     """An SELinux security context with optional MCS / MLS fields."""
-    def __init__(self, context=None):
+    def __init__(self, context=None, parent=None):
         """Create a SecurityContext object, optionally from a string.
 
         Parameters:
            [context] - string representing a security context. Same format
               as a string passed to the from_string method.
         """
-        Leaf.__init__(self)
+        Leaf.__init__(self, parent)
         self.user = ""
         self.role = ""
         self.type = ""
@@ -314,7 +318,7 @@
             fields.append(self.level)
         return ":".join(fields)
 
-class ObjectClass:
+class ObjectClass(Leaf):
     """SELinux object class and permissions.
 
     This class is a basic representation of an SELinux object
@@ -322,7 +326,8 @@
     just the union of the common and class specific permissions.
     It is meant to be convenient for policy generation.
     """
-    def __init__(self, name=""):
+    def __init__(self, name="", parent=None):
+        Leaf.__init__(self, parent)
         self.name = name
         self.perms = IdSet()
 
@@ -333,8 +338,8 @@
 
     This class represents a typeattribute statement.
     """
-    def __init__(self):
-        Leaf.__init__(self)
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
         self.type = ""
         self.attributes = IdSet()
 
@@ -342,8 +347,8 @@
         return "typeattribute %s %s;" % (self.type, self.attributes.to_comma_str())
 
 class Role(Leaf):
-    def __init__(self):
-        Leaf.__init__(self)
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
         self.role = ""
         self.types = IdSet()
 
@@ -351,8 +356,8 @@
         return "role %s types %s;" % (self.role, self.types.to_comma_str())
 
 class Type(Leaf):
-    def __init__(self, name=""):
-        Leaf.__init__(self)
+    def __init__(self, name="", parent=None):
+        Leaf.__init__(self, parent)
         self.name = name
         self.attributes = IdSet()
         self.aliases = IdSet()
@@ -366,8 +371,8 @@
         return s + ";"
 
 class TypeAlias(Leaf):
-    def __init__(self):
-        Leaf.__init__(self)
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
         self.type = ""
         self.aliases = IdSet()
 
@@ -375,8 +380,8 @@
         return "typealias %s alias %s;" % (self.type, self.aliases.to_space_str())
 
 class Attribute(Leaf):
-    def __init__(self, name=""):
-        Leaf.__init__(self)
+    def __init__(self, name="", parent=None):
+        Leaf.__init__(self, parent)
         self.name = name
 
     def to_string(self):
@@ -403,9 +408,10 @@
     ALLOW = 0
     DONTAUDIT = 1
     AUDITALLOW = 2
+    NEVERALLOW = 3
 
-    def __init__(self, av=None):
-        Leaf.__init__(self)
+    def __init__(self, av=None, parent=None):
+        Leaf.__init__(self, parent)
         self.src_types = IdSet()
         self.tgt_types = IdSet()
         self.obj_classes = IdSet()
@@ -455,8 +461,8 @@
     TYPE_CHANGE = 1
     TYPE_MEMBER = 2
 
-    def __init__(self):
-        Leaf.__init__(self)
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
         self.src_types = IdSet()
         self.tgt_types = IdSet()
         self.obj_classes = IdSet()
@@ -479,8 +485,8 @@
                                      self.dest_type)
 
 class RoleAllow(Leaf):
-    def __init__(self):
-        Leaf.__init__(self)
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
         self.src_roles = IdSet()
         self.tgt_roles = IdSet()
 
@@ -489,8 +495,8 @@
                                  self.tgt_roles.to_comma_str())
 
 class ModuleDeclaration(Leaf):
-    def __init__(self):
-        Leaf.__init__(self)
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
         self.name = ""
         self.version = ""
         self.refpolicy = False
@@ -501,8 +507,99 @@
         else:
             return "module %s %s;" % (self.name, self.version)
 
+class Conditional(Node):
+    def __init__(self, parent=None):
+        Node.__init__(self, parent)
+        self.cond_expr = []
 
+    def to_string(self):
+        return "[If %s]" % list_to_space_str(self.cond_expr, cont=("", ""))
 
+class Bool(Leaf):
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
+        self.name = ""
+        self.state = False
+
+    def to_string(self):
+        s = "bool %s " % self.name
+        if s.state:
+            return s + "true"
+        else:
+            return s + "false"
+
+class InitialSid(Leaf):
+    def __init(self, parent=None):
+        Leaf.__init__(self, parent)
+        self.name = ""
+        self.context = None
+
+    def to_string(self):
+        return "sid %s %s" % (self.name, str(self.context))
+
+class GenfsCon(Leaf):
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
+        self.filesystem = ""
+        self.path = ""
+        self.context = None
+
+    def to_string(self):
+        return "genfscon %s %s %s" % (self.filesystem, self.path, str(self.context))
+
+class FilesystemUse(Leaf):
+    XATTR = 1
+    TRANS = 2
+    TASK = 3
+    
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
+        self.type = self.XATTR
+        self.filesystem = ""
+        self.context = None
+
+    def to_string(self):
+        s = ""
+        if self.type == XATTR:
+            s = "fs_use_xattr "
+        elif self.type == TRANS:
+            s = "fs_use_trans "
+        elif self.type == TASK:
+            s = "fs_use_task "
+
+        return "%s %s %s;" % (s, self.filesystem, str(self.context))
+
+class PortCon(Leaf):
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
+        self.port_type = ""
+        self.port_number = ""
+        self.context = None
+
+    def to_string(self):
+        return "portcon %s %s %s" % (self.port_type, self.port_number, str(self.context))
+
+class NodeCon(Leaf):
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
+        self.start = ""
+        self.end = ""
+        self.context = None
+
+    def to_string(self):
+        return "nodecon %s %s %s" % (self.start, self.end, str(self.context))
+
+class NetifCon(Leaf):
+    def __init__(self, parent=None):
+        Leaf.__init__(self, parent)
+        self.interface = ""
+        self.interface_context = None
+        self.packet_context = None
+
+    def to_string(self):
+        return "netifcon %s %s %s" % (self.interface, str(self.interface_context),
+                                   str(self.packet_context))
+
 # Reference policy specific types
 
 def print_tree(head):
@@ -564,17 +661,9 @@
     def to_string(self):
         return "[Ifdef name: %s]" % self.name
 
-class Conditional(Node):
-    def __init__(self, parent=None):
-        Node...
 
[truncated message content] | 
| 
      
      
      From: <ssm...@us...> - 2008-01-23 14:13:24
       | 
| Revision: 2734
          http://selinux.svn.sourceforge.net/selinux/?rev=2734&view=rev
Author:   ssmalley
Date:     2008-01-23 06:13:23 -0800 (Wed, 23 Jan 2008)
Log Message:
-----------
Author: Daniel J Walsh
Email: dw...@re...
Subject: Patch to improve sepopolgen error reporting
Date: Fri, 11 Jan 2008 16:22:56 -0500
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Resent minus patch for blacklist.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iEYEARECAAYFAkeH3i8ACgkQrlYvE4MpobNQKwCgoJ2EgHctehpYyJSHQb5uxgud
YdoAoNV7KfTw6DopBWUlXjqjo2A5QmcS
=T56w
-----END PGP SIGNATURE-----
Modified Paths:
--------------
    trunk/sepolgen/src/sepolgen/audit.py
    trunk/sepolgen/src/sepolgen/refparser.py
Modified: trunk/sepolgen/src/sepolgen/audit.py
===================================================================
--- trunk/sepolgen/src/sepolgen/audit.py	2008-01-23 13:59:29 UTC (rev 2733)
+++ trunk/sepolgen/src/sepolgen/audit.py	2008-01-23 14:13:23 UTC (rev 2734)
@@ -32,7 +32,7 @@
        string contain all of the audit messages returned by ausearch.
     """
     import subprocess
-    output = subprocess.Popen(["/sbin/ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START"],
+    output = subprocess.Popen(["/sbin/ausearch", "-m", "AVC,USER_AVC,MAC_POLICY_LOAD,DAEMON_START,SELINUX_ERR"],
                               stdout=subprocess.PIPE).communicate()[0]
     return output
 
@@ -251,7 +251,9 @@
             self.type = refpolicy.SecurityContext(dict["tcontext"]).type
         except:
             raise ValueError("Split string does not represent a valid compute sid message")
-
+    def output(self):
+        return "role %s types %s;\n" % (self.role, self.type)
+        
 # Parser for audit messages
 
 class AuditParser:
@@ -402,6 +404,26 @@
             self.__parse(l)
         self.__post_process()
 
+    def to_role(self, role_filter=None):
+        """Return list of SELINUX_ERR messages matching the specified filter
+
+        Filter out types that match the filer, or all roles
+
+        Params:
+           role_filter - [optional] Filter object used to filter the
+              output.
+        Returns:
+           Access vector set representing the denied access in the
+           audit logs parsed by this object.
+        """
+        roles = []
+        if role_filter:
+            for selinux_err in self.compute_sid_msgs:
+                if role_filter.filter(selinux_err):
+                    roles.append(selinux_err)
+            return roles
+        return self.compute_sid_msgs
+
     def to_access(self, avc_filter=None, only_denials=True):
         """Convert the audit logs access into a an access vector set.
 
Modified: trunk/sepolgen/src/sepolgen/refparser.py
===================================================================
--- trunk/sepolgen/src/sepolgen/refparser.py	2008-01-23 13:59:29 UTC (rev 2733)
+++ trunk/sepolgen/src/sepolgen/refparser.py	2008-01-23 14:13:23 UTC (rev 2734)
@@ -118,6 +118,7 @@
     'TEMPLATE',
     'GEN_CONTEXT',
     #   m4
+    'IFELSE',
     'IFDEF',
     'IFNDEF',
     'DEFINE'
@@ -174,6 +175,7 @@
     'template' : 'TEMPLATE',
     'gen_context' : 'GEN_CONTEXT',
     # M4
+    'ifelse' : 'IFELSE',
     'ifndef' : 'IFNDEF',
     'ifdef' : 'IFDEF',
     'define' : 'DEFINE'
@@ -220,6 +222,12 @@
     # Ignore all comments
     t.lexer.lineno += 1
 
+def t_refpolicywarn1(t):
+    r'define.*refpolicywarn\(.*\n'
+    # Ignore refpolicywarn statements - they sometimes
+    # contain text that we can't parse.
+    t.skip(1)
+
 def t_refpolicywarn(t):
     r'refpolicywarn\(.*\n'
     # Ignore refpolicywarn statements - they sometimes
@@ -258,10 +266,12 @@
 m = None
 #   error is either None (indicating no error) or a string error message.
 error = None
+parse_file = ""
 #   spt is the support macros (e.g., obj/perm sets) - it is an instance of
 #     refpolicy.SupportMacros and should always be present during parsing
 #     though it may not contain any macros.
 spt = None
+success=True
 
 # utilities
 def collect(stmts, parent, val=None):
@@ -382,6 +392,19 @@
         collect(p[12], x, val=False)
     p[0] = [x]
 
+def p_ifelse(p):
+    '''ifelse : IFELSE OPAREN TICK IDENTIFIER SQUOTE COMMA COMMA TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN optional_semi
+              | IFELSE OPAREN TICK IDENTIFIER SQUOTE COMMA TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN optional_semi
+    '''
+#    x = refpolicy.IfDef(p[4])
+#    v = True
+#    collect(p[8], x, val=v)
+#    if len(p) > 12:
+#        collect(p[12], x, val=False)
+#    p[0] = [x]
+    pass
+
+
 def p_ifdef(p):
     '''ifdef : IFDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN optional_semi
              | IFNDEF OPAREN TICK IDENTIFIER SQUOTE COMMA TICK interface_stmts SQUOTE CPAREN optional_semi
@@ -446,6 +469,7 @@
               | optional_policy
               | tunable_policy
               | ifdef
+              | ifelse
               | conditional
     '''
     p[0] = p[1]
@@ -844,8 +868,11 @@
 
 def p_error(tok):
     global error
-    error = "Syntax error on line %d %s [type=%s]" % (tok.lineno, tok.value, tok.type)
+    global parse_file
+    global success
+    error = "%s: Syntax error on line %d %s [type=%s]" % (parse_file, tok.lineno, tok.value, tok.type)
     print error
+    success = False
 
 def prep_spt(spt):
     if not spt:
@@ -941,12 +968,14 @@
             output.write(msg)
 
     def parse_file(f, module, spt=None):
+        global parse_file
         if debug:
             o("parsing file %s\n" % f)
         try:
             fd = open(f)
             txt = fd.read()
             fd.close()
+            parse_file = f
             parse(txt, module, spt, debug)
         except IOError, e:
             return
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 |