epp(3erl)
π NAME π
epp β bestie, it's an Erlang code preprocessor β¨
πΈ DESCRIPTION πΈ
Okay so real talk: the Erlang code preprocessor is a whole little icon π. It's got a bunch of functions that the compile module literally uses to preprocess macros and include files before the actual parsing happens. Like, it does the backstage prep work so the parser can walk on stage looking flawless π
.
π Encoding vibes (yes, your source file has a vibe) π
Your Erlang source file gets its encoding picked by a comment sitting in one of the first two lines of the file. The first string that matches this regular expression here is the one that wins:
coding\s*[:=]\s*([-a-zA-Z0-9])+
That matching string selects the encoding, periodt. But β important β if the matching string isn't a valid encoding, it is ignored (rude, but okay π).
The valid encodings are Latin-1 and UTF-8, and ngl the case of the characters can be chosen freely, so go off with your capitalization, it's giving freedom π.
π¦ Examples π¦
%% coding: utf-8
%% For this file we have chosen encoding = Latin-1
%% -*- coding: latin-1 -*-
Three different fits, all valid, all slay π β¨
π DATA TYPES π
macros()=
[atom() | {atom(), term()} | {atom(), term(), redefine}]
epp_handle()=pid()
Handle to the epp server π«Ά. Like, this is your little connection to the epp server, keep it close bestie.
source_encoding()=latin1 | utf8
The encoding type, lowkey straightforward, no notes π
warning_info()={erl_anno:location(), module(), term()}
The info bundle for warnings β location, module, and a term, all wrapped up cute in a tuple π
β¨ EXPORTS β¨
okay so this is the part where epp actually hands you the goods π
every function, every flag, every {ok, ...} β we're keeping it all, no cap.
close(Epp) -> ok
Types:
Epp = epp_handle()
Closes the preprocessing of a file. That's it, bestie β hang up the call, wrap the session, done π«Ά
default_encoding() -> source_encoding()
Returns the default encoding of Erlang source files. the standard vibe, if you will β¨
encoding_to_string(Encoding) -> string()
Types:
Encoding = source_encoding()
Returns a string representation of an encoding. That string is recognized by read_encoding/1,2, read_encoding_from_binary/1,2, and set_encoding/1,2 as a valid encoding. so it's a whole little encoding passport that everyone accepts ππ
format_error(ErrorDescriptor) -> io_lib:chars()
Types:
ErrorDescriptor = term()
Takes an ErrorDescriptor and returns a string that describes the error or warning. This function is usually called implicitly when processing an ErrorInfo structure (see section Error Information). it's giving βI explain the problem so you don't have toβ energy π
open(Options) -> {ok, Epp} | {ok, Epp, Extra} | {error, ErrorDescriptor}
Types:
Options =
[{default_encoding, DefEncoding :: source_encoding()} |
{includes, IncludePath :: [DirectoryName :: file:name()]}
|
{source_name, SourceName :: file:name()} |
{deterministic, Enabled :: boolean()} |
{macros, PredefMacros :: macros()} |
{name, FileName :: file:name()} |
{location, StartLocation :: erl_anno:location()} |
{fd, FileDescriptor :: file:io_device()} |
extra]
Epp = epp_handle()
Extra = [{encoding, source_encoding() | none}]
ErrorDescriptor = term()
Opens a file for preprocessing. main character moment: the file is now in the preprocessor's hands π
If you want to change the file name of the implicit -file() attributes inserted during preprocessing, you can do that with {source_name, SourceName}. If unset, it defaults to the name of the opened file.
Setting {deterministic, Enabled} will additionally reduce the file name of the implicit -file() attributes inserted during preprocessing to only the basename of the path. basename only, because we're being deterministic and cute about it β¨
If extra is specified in Options, the return value is {ok, Epp, Extra} instead of {ok, Epp}.
The option location is forwarded to the Erlang token scanner, see erl_scan:tokens/3,4.
open(FileName, IncludePath) -> {ok, Epp} | {error, ErrorDescriptor}
Types:
FileName = file:name()
IncludePath = [DirectoryName :: file:name()]
Epp = epp_handle()
ErrorDescriptor = term()
Equivalent to epp:open([{name, FileName}, {includes, IncludePath}]). same tea, shorter order π«Ά
open(FileName, IncludePath, PredefMacros) -> {ok, Epp} | {error, ErrorDescriptor}
Types:
FileName = file:name()
IncludePath = [DirectoryName :: file:name()]
PredefMacros = macros()
Epp = epp_handle()
ErrorDescriptor = term()
Equivalent to epp:open([{name, FileName}, {includes, IncludePath}, {macros, PredefMacros}]). now with macros, because we contain multitudes β¨
parse_erl_form(Epp) -> {ok, AbsForm} | {error, ErrorInfo} | {warning, WarningInfo} | {eof, Location}
Types:
Epp = epp_handle()
AbsForm = erl_parse:abstract_form()
Location = erl_anno:location()
ErrorInfo = erl_scan:error_info() | erl_parse:error_info()
WarningInfo = warning_info()
Returns the next Erlang form from the opened Erlang source file. Tuple {eof, Location} is returned at the end of the file. The first form corresponds to an implicit attribute -file(File,1)., where File is the file name. first form said βhi, I'm the file attributeβ and honestly? iconic π
parse_file(FileName, Options) -> {ok, [Form]} | {ok, [Form], Extra} | {error, OpenError}
Types:
FileName = file:name()
Options =
[{includes, IncludePath :: [DirectoryName :: file:name()]}
|
{source_name, SourceName :: file:name()} |
{macros, PredefMacros :: macros()} |
{default_encoding, DefEncoding :: source_encoding()} |
{location, StartLocation :: erl_anno:location()} |
{reserved_word_fun, Fun :: fun((atom()) -> boolean())} |
{features, [Feature :: atom()]} |
extra]
Form =
erl_parse:abstract_form() |
{error, ErrorInfo} |
{eof, Location}
Location = erl_anno:location()
ErrorInfo = erl_scan:error_info() | erl_parse:error_info()
Extra = [{encoding, source_encoding() | none}]
OpenError = file:posix() | badarg | system_limit
Preprocesses and parses an Erlang source file. Notice that tuple {eof, Location} returned at the end of the file is included as a "form". yes bestie, even the end-of-file moment gets to be a form. inclusivity! ππ
If you want to change the file name of the implicit -file() attributes inserted during preprocessing, you can do that with {source_name, SourceName}. If unset, it defaults to the name of the opened file.
If extra is specified in Options, the return value is {ok, [Form], Extra} instead of {ok, [Form]}.
The option location is forwarded to the Erlang token scanner, see erl_scan:tokens/3,4.
parse_file(FileName, IncludePath, PredefMacros) -> {ok, [Form]} | {error, OpenError}
Types:
FileName = file:name()
IncludePath = [DirectoryName :: file:name()]
Form =
erl_parse:abstract_form() |
{error, ErrorInfo} |
{eof, Location}
PredefMacros = macros()
Location = erl_anno:location()
ErrorInfo = erl_scan:error_info() | erl_parse:error_info()
OpenError = file:posix() | badarg | system_limit
Equivalent to epp:parse_file(FileName, [{includes, IncludePath}, {macros, PredefMacros}]). shortcut elegance, no notes π
read_encoding(FileName) -> source_encoding() | none
read_encoding(FileName, Options) -> source_encoding() | none
Types:
FileName = file:name()
Options = [Option]
Option = {in_comment_only, boolean()}
Reads the encoding from a file. Returns the read encoding, or none if no valid encoding is found. encoding detective behavior, but make it chic πβ¨
Option in_comment_only is true by default, which is correct for Erlang source files. If set to false, the encoding string does not necessarily have to occur in a comment. so like, it can be out in the wild β not just hiding in a comment π¦
read_encoding_from_binary(Binary) -> source_encoding() | none
read_encoding_from_binary(Binary, Options) -> source_encoding() | none
Types:
Binary = binary()
Options = [Option]
Option = {in_comment_only, boolean()}
Reads the encoding from a binary. Returns the read encoding, or none if no valid encoding is found. same encoding hunt, but binary edition π»π
Option in_comment_only is true by default, which is correct for Erlang source files. If set to false, the encoding string does not necessarily have to occur in a comment.
scan_erl_form(Epp) -> {ok, Tokens} | {error, ErrorInfo} | {warning, WarningInfo} | {eof, Line}
Types:
Epp = epp_handle()
Tokens = erl_scan:tokens()
Line = erl_anno:line()
ErrorInfo = erl_scan:error_info() | erl_parse:error_info()
WarningInfo = warning_info()
Returns the raw tokens of the next Erlang form from the opened Erlang source file. A tuple {eof, Line} is returned at the end of the file. The first form corresponds to an implicit attribute -file(File,1)., where File is the file name. raw tokens, no filter, no makeup β just the real thing π
scan_file(FileName, Options) -> {ok, [Form], Extra} | {error, OpenError}
Types:
FileName = file:name()
Options =
[{includes, IncludePath :: [DirectoryName :: file:name()]}
|
{source_name, SourceName :: file:name()} |
{macros, PredefMacros :: macros()} |
{default_encoding, DefEncoding :: source_encoding()}]
Form = erl_scan:tokens() | {error, ErrorInfo} | {eof, Loc}
Loc = erl_anno:location()
ErrorInfo = erl_scan:error_info()
Extra = [{encoding, source_encoding() | none}]
OpenError = file:posix() | badarg | system_limit
Preprocesses an Erlang source file returning a list of the lists of raw tokens of each form. Notice that the tuple {eof, Line} returned at the end of the file is included as a "form", and any failures to scan a form are included in the list as tuples {error, ErrorInfo}. errors get to be part of the list too, because we don't ghost failures ππ
set_encoding(File) -> source_encoding() | none
Types:
File = io:device()
Reads the encoding from an I/O device and sets the encoding of the device accordingly. The position of the I/O device referenced by File is not affected. If no valid encoding can be read from the I/O device, the encoding of the I/O device is set to the default encoding. it peeks at the encoding, updates the device, and does not disturb the position β respectful king behavior πβ¨
Returns the read encoding, or none if no valid encoding is found.
set_encoding(File, Default) -> source_encoding() | none
Types:
Default = source_encoding()
File = io:device()
Reads the encoding from an I/O device and sets the encoding of the device accordingly. The position of the I/O device referenced by File is not affected. If no valid encoding can be read from the I/O device, the encoding of the I/O device is set to the encoding specified by Default. same respectful position-preserving behavior, but now with your chosen fallback π
Returns the read encoding, or none if no valid encoding is found.
π ERROR INFORMATION π
ErrorInfo is the standard ErrorInfo structure that is returned from all I/O modules. The format is as follows:
{ErrorLine, Module, ErrorDescriptor}
A string describing the error is obtained with the following call:
Module:format_error(ErrorDescriptor)
so when something goes off, it's not just chaos β it's a whole structured little error package, and Module:format_error/1 turns it into words you can actually read π«Ά
π SEE ALSO π
erl_parse(3erl)β go read this too, bestie, it's giving related documentation energy β¨π
footer vibes: shoutout to Ericsson AB for making this happen, the version is stdlib 4.3.1.3, and the page is epp(3erl). There's no separate date in the footer, so we're not inventing one β periodt πππ¦
π¦ where this page comes from
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4 Β· Apache-2.0
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4.8 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms