/**
* reflect/files main-file
*
* Strategies for including and requiring files as in
* PHP. It adds the ATerms of the files to the environment.
*
* @author Eric Bouwers
*/
module php/reflect/inclusion/main
imports
php/reflect/inclusion/path
php/reflect/inclusion/currentdir
php/reflect/inclusion/workingdir
php/reflect/inclusion/inclusionid
strategies
//main strategy
include-and-require-files =
procedural-topdown(try(process-include-and-require-files(include-and-require-files)))
rules
/**
* Process and inclusion of files. This rule finds the statements
* that should be processed.
* Note that this is a simple strategy. It includes all files
* that are directly accessiable to the environment. For a more
* enhanced version see the analysis for constant propogation.
*/
process-include-and-require-files(s):
t@InternalFunction(Include(expr)) -> t'
where includeid := <process-include(s)> expr
; t' := <add-inclusion-id(|includeid)> t
process-include-and-require-files(s):
t@InternalFunction(Require(expr)) -> t'
where requireid := <process-include(s)> expr
; t' := <add-inclusion-id(|requireid)> t
process-include-and-require-files(s):
t@InternalFunction(IncludeOnce(expr)) -> t'
where includeid := <process-include(s)> expr
; t' := <add-inclusion-id(|includeid)> t
process-include-and-require-files(s):
t@InternalFunction(RequireOnce(expr)) -> t'
where requireid := <process-include(s)> expr
; t' := <add-inclusion-id(|requireid)> t
rules
/**
* Two special functions that we need to handle.
* - chdir: changes working directory
* - ini-set: sets the include path if first argument is 'include_path'
*/
process-include-and-require-files(s):
t@FunctionCall(name,params) -> t
where <php-handle-function-call> (name,<map(main-analyse-const-prop)> params)
rules
/**
* The real inclusion. The first two rules only work on direct single- or doublequoted
* strings with nothing fancy. Other rules can be added that take care of other
* scenario's.
*/
process-include(s):
ConstantEncapsedString(SingleQuoted([Literal(filename)])) -> includeid
where includeid := <process-inclusion(s)> filename
process-include(s):
ConstantEncapsedString(DoubleQuoted([Literal(filename)])) -> includeid
where includeid := <process-inclusion(s)> filename
strategies
/**
* Processes the inclusion of a filename. The strategy has
* the same semantics as within PHP. The file is looked-up within
* the current directory. When this fails and the filename is not relative
* the file is looked up within the current directory.
*
* The strategy 's' is applied to the newly parsed AST after which the
* new AST is added to the current environment.
*
* precondition: There must be an environment
*
* @param s: AST -> AST
* @type filename::String -> Inclusionid
*/
process-inclusion(s) = ?arg;
file := <find-php-file> arg
; where( file' := <get-current-php-file>
; <set-current-php-file> file
)
; <include-php-file(s)> file
; where(
<set-current-php-file> file'
)
/**
* Real inclusion of a filename and a strategy that must be applied to
* the included and parsed file.
*
* @param s: AST -> AST
* @type filename::String -> Inclusionid
*/
include-php-file(s) =
?file
; newcurdir := <?FILE(curdirpath); !curdirpath; dirname > file
; log(|Debug(), "Start including new file: ", curdirpath)
; includeid := <new-inclusion-id> curdirpath
; get-php-environment ; add-inclusion-filename(|curdirpath,includeid)
; set-php-current-directory(|newcurdir)
; ast := <parse-php> file
; ast' := <s> ast
; prev-php-current-directory
; get-php-environment ; add-inclusion-file(|ast',includeid)
; !includeid
; log(|Debug(), "Finish including new file: ", curdirpath)
/**
* Takes a filename and searches for this filename in the same way that
* PHP looks for the files to include.
*
* @type filename::String -> absolutepath::String
*/
find-php-file =
?filename
; ( file := <find-file-in-working-directory(|filename)>
<+ if <is-php-relative> filename
then fail
else file := <find-file-in-current-directory(|filename)>
end
)
; !file
/**
* Section to store current file being processed
*/
/**
* Returnes the name of the file currently being processed
*/
get-current-php-file =
<get-config> "current-php-file"
<+ get-input-path
/**
* Sets the name of the file currently being processed
*/
set-current-php-file =
<set-config> ("current-php-file", <id>)