# include_paths

Definition: | sequence s = include_paths(integer convert=0)
Description: | Returns a list of include paths, which are typically searched last-first. The convert parameter is unused and present solely for compatibility with Euphoria.
pwa/p2js: | Not supported apart from include_file().
Comments: | The list returned is in reverse order of searching, potentially with inactive relative directory handling towards the end. For example if an application contains ‘include ..\..\demo\arwen\arwen.ew’ the appropriate fully resolved path to arwen.ew is added to the end of the include paths table so that any include statements within that file are searched for within that path first, and that path is marked inactive once arwen.ew has been fully processed. Several such events may have occurred during compilation; the table returned is the complete table as at the end of compilation, but without any indication of which, if any, directories are no longer 'active' (by the time it actually runs, in practice, almost all of them will have been marked inactive). As shown below, every entry of the result ends with a path separator, so there should be no need to check for that. If EUDIR and/or EUINC are defined, they appear at the start of the list, and therefore would be searched last.
Auxillary Functions | string s = include_path(sequence d="builtins") The include_path() function (without an s) caters for the common case of wanting just one entry from the with-an-s set, ending as specified. If d is "" (or {}) it retrieves the top-level directory where the main file resides, in practice that is include_paths()[include_files()[1][1]]. Multiple trailing directories can be specified as either eg `builtins\VM` or {"builtins","VM"}. Obviously, when faced with unexpected compile-time type errors on the parameter, double check that s, ie include_path() vs include_paths(). sequence f = include_files() The include_files() function returns a complete set of included files, with directories as indexes to the include_paths() result, see example. The result is fully expected to be significantly longer when compiled that when interpreted, since the latter re-uses some parts of the phix executable, whereas the former must incorporate its own copies of pDiagN.e, pHeap.e, pStack.e, pprntfN.e, etc. See technicalia below. integer fdx = include_file(integer depth=1) The include_file() function (without an s) returns an index into the include_files() result. An fdx of 1 denotes the main top-level file. It uses the call stack to determine the calling routine_id, and then the symtab to get the index of the file in which that was defined. You should get the same result from top-level as (deeply) nested routine calls, as long as both calls are in the same source code file. The depth parameter allows you to determine what file contained the call to the routine that is calling include_file(), to arbitrary depth. (depth is similar to the nFrames parameter of crash() with insufficient frames leading to undefined behaviour.) Note that in p2js.js include_file() is a dummy routine that always returns 1, and pwa/p2js replaces calls to include_file() not in the main file with incl0de_file() which is a dummy routine that always returns 0, and the depth parameter is completely ignored. Very specifically this just about covers "include_file()=1" and "include_file()!=1", but not much else, and it does not perform any rigorous checking that it is being used in a sensible/supported fashion. Note that to my knowledge there are no equivalents in Euphoria for any of these auxillary routines, not that I expect that they would be excessively difficult to add or work around, that is starting from the basic include_paths(), which I believe is supported.
Examples: |
    sequence p = include_paths()
    -- p might contain
    --  {`C:\Program Files (x86)\Phix\builtins\`,
    --   `C:\Program Files (x86)\Phix\builtins\VM\`,
    --   `C:\Program Files (x86)\Phix\`}

    string s = include_path()
    -- s will (given the above, and the default for d) contain
    --   `C:\Program Files (x86)\Phix\builtins\`

    sequence f = include_files()
    -- f might contain      -- ie assuming the above:
    --  {{3,`test.exw`},    -- ie C:\Program Files (x86)\Phix\test.exw
    --   {1,`pincpathN.e`}, -- ie C:\Program Files (x86)\Phix\builtins\pincpathN.e
    --   {2,`pprntfN.e`}}   -- ie C:\Program Files (x86)\Phix\builtins\VM\pprntfN.e

    integer fdx = include_file()
    -- An fdx of 1 matches that {3,`test.exw`}, meaning that is where the above is.
Implementation: | See builtins\pincpathN.e (an autoinclude) for details of the actual implementation. See also ptok.e, addPath/initFilePathSet/Finc/includeFile, for details of how the compiler builds and uses it.
Technicalia | The results are not thread safe (apart from fdx), and may corrupt internal reference counts when freed, should that occur in multiple threads. Ideally these routines should only ever be called from the main/gui thread, and perhaps kept for the entire duration of an application. That will avoid any need to lock when freeing reference counts, and/or >=2 AGI stalls that occur within every include_file() call. The "builtins" default for include_path() is used by several libraries for dll-loading purposes, but could fairly easily be changed if needed. Somewhat similar and perhaps more detailed and/or more deeply nested results can also be obtained via throw/catch. The directory paths are accurate during interpretation but may be misleading should pre-compiled applications be installed in a different directory, which can be especially significant when the builtins directory is located elsewhere on the target machine.