Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

version 0.8.5

  • Loading branch information...
commit 497b7740bcfa815fee186dc193d363e869196bba 1 parent 7b68ed5
@ahmednawras ahmednawras authored
View
16 API.txt
@@ -3,7 +3,12 @@ NOTE:
Please be informed that the API below as of now is not stable and any of the functions/parameters below
may be changed without prior notice.
-Furthermore, you can find the appenders
+Furthermore, you can find appenders and their configurations in 'Appenders_API.txt' file included in release.
+
+**> log4erl:conf(File) -> ok | {error, E}
+ File :: string()
+
+ File is the name of the configuration file. Please check CONFIGURATION.txt for the format of this file.
**> log4erl:add_logger(Name) -> ok | {error, E}
Name :: atom() name of the logger
@@ -49,10 +54,10 @@ Furthermore, you can find the appenders
This will change the output format to the specified Format. Format is a pattern string similar to
PatternLayout in Log4j. patterns is an arbitrary string with specifiers (proceeded by '%').
Possible specifiers are below:
- d - output date (1-2-2008)
- j - output date (01-02-2008)
+ d - output date (2008-3-7)
+ j - output date (2008-03-07)
t - time (2:13:9)
- T - time (02:28:01,811637)
+ T - time (02:28:01.811637)
y - year in YY format (08)
Y - year in YYYY format (2008)
M - month (2)
@@ -64,6 +69,9 @@ Furthermore, you can find the appenders
s - second
i - milli-seconds
l - the actual log message
+ I - ISO format with universal GMT time (equivilant to "%jT%TZ").
+ S - ISO format with local time and time zone offset
+ Z - timezone (+04:00)
L - log level
n - new line
% - the percentage sign (%)
View
41 Appenders_API.txt
@@ -8,7 +8,8 @@
{LogDir, LogFileName, {size, Size}, NumOfRotations, Suffix, LogLevel}
or
{LogDir, LogFileName, {size, Size}, NumOfRotations, Suffix, LogLevel, Format}
- This tuple defines the appender's attributes.
+ This tuple defines the appender's attributes.
+ If Format is not specified, the default format is "[%L] %l%n".
Example:
log4erl:add_file_appender(chat_room1, {"../logs", "room1", {size, 100000}, 4, "txt", warn}).
@@ -87,3 +88,41 @@
<warn - 01-03-2009 12:21:09,818534
test smtp appender>
+**> log4erl:add_syslog_appender(Appender, Spec) -> ok
+ log4erl:add_syslog_appender(Logger, Appender, Spec) -> ok
+ Logger :: atom()
+ Appender :: atom()
+ Spec :: tuple() | list()
+
+ @since version 0.8.5
+
+ This will create a new syslog appender to either Logger of default logger and initialize it to spec in Spec or
+ file named Spec if Spec is a list. Spec is in the below form. MsgFormat is the format of the message and it
+ has the same meaning as the format of Format in add_file_logger/2,3.
+
+ Note: In for syslog_appender to work, you need to enable syslogd to accept network messages. In linux, you
+ need to use '-r' switch when running syslogd.
+
+ Spec =
+ {Level, Fac} |
+ {Level, Fac, Host} |
+ {Level, Fac, Host, Format} |
+ {Level, Fac, Host, Port, Format}
+ where:
+ Level = atom()
+ Fac = atom()
+ Host = string() | tuple()
+ Port = integer()
+ Format = string()
+
+ Example:
+ log4erl:add_syslog_appender(appender1, {warn, user, "syslog_srvr", "(%L) - %S %l%n"}}).
+
+ This will create a syslog_appender called appender1 with level 'warn' and uses 'user' facility.
+ The appender will connect to host "syslog_srvr" with default port (514). The messages will be
+ formatted according to the format "%L - %j %T %n %l%n".
+
+ Default host is "localhost".
+ Default port is 514.
+ Default Format is the same as default format of file_appender
+
View
7 CHANGELOG.txt
@@ -1,3 +1,10 @@
+log4erl 0.8.5:
+==============
+* Added new file configuration (log4erl:conf(File)).
+* Added syslog_appender.
+* Added support for ISO standard format to appenders (%I, %S & %Z specifiers).
+* Changed %d & %j to output the date in YYYY-MM-DD format according to ISO standard format
+
log4erl 0.8.4:
==============
* Added smtp_appender (new functions add_smtp_appender/2,3)
View
99 CONFIGURATION.txt
@@ -0,0 +1,99 @@
+ Configuration Guide:
+ ====================
+
+TOC:
+====
+* Introduction
+* Loggers
+ - Example
+* Appenders
+ - common properties
+ - file_appender
+ - console_appender
+ - smtp_appender
+ - syslog_appender
+
+Introduction:
+=============
+This document explains the format of log4erl configuarion file. The configuration file is simple
+and easy to write. At any place in the file, any thing you type after '%' is a comment.
+You can find a sample configuration in the file 'log4erl.conf' under 'priv' directory.
+
+* Loggers:
+==========
+ It contains a list of logs with the format below, where
+<name> is any name you'd like to call it. <name> can later on be used with any of the log messages
+in log4erl API (e.g. log4erl:info/2,3,4). If no value for <name> exists or value of "default" suplied,
+then the elements inside '{' and '}' will be applied to the default logger.
+
+logger [<name>] {
+ ...
+}
+
+Example:
+--------
+logger application_logger{
+ ...
+}
+
+%% default logger
+logger {
+ ...
+}
+
+* Appenders:
+============
+Inside each logger, there can be 1 or more appenders. These appenders can be
+added inside loggers according to the format below.
+
+<appender_type> <name> {
+ ...
+}
+
+Example:
+--------
+file_appender file1{
+ ...
+}
+
+insider appenders' block, you can add properties for that appender in the format 'property=value'.
+Multiple properties are seperated by a comman ','Each appender type has different sets of properties,
+which are detailed below.
+
+common properties:
+------------------
+level = <Level> => level of log (e.g. warn)
+format = <F> => format of the output (look at 'Appenders.txt')
+
+file_appender:
+--------------
+dir = <Dir> => directory of output (e.g. /var/log/my_app)
+file = <File> => name of the log file (e.g. my_app_log)
+type = <Type> => either size or time. Only size is implemented currently
+max = <Max> => Maximum size of each rotation
+suffix = <Suf> => Suffix of the log file (e.g. log)
+rotation = <R> => number of rotations before over-writing log files
+
+console_appender:
+-----------------
+Nothing more than common properties.
+
+smtp_appender:
+--------------
+ip = <IP> => ip of the SMTP server
+port = <Port> => SMTP prot [Optional]
+no_auth = true|false => if specified, no authentication is performed even if
+ username or password below is provided
+username = <U> => SMTP username
+password = <P> => SMTP password
+from = <From> => value of the From field [Optional]
+to = <To> => email to send to
+title = <T> => title of email [Optional]
+msg = <Format> => format of the email message [Optional]
+
+syslog_appender:
+----------------
+facility = <F> => Facility to be used (e.g. ftp)
+host = <H> => Host to send syslog messages to [Optional]
+port = <P> => syslog port [Optioanl]
+
View
30 README.txt
@@ -7,9 +7,10 @@ TOC:
2. Installation
3. Usage
4. API
-5. Known issues
-6. Future development
-7. License
+5. Configuration
+6. Known issues
+7. Future development
+8. License
1. FEATURES:
============
@@ -55,13 +56,18 @@ $> erl -pz /path/to/log4erl ...
you need to run:
> application:start(log4erl).
-3- Create loggers & add appenders to them as appropriate. You can do this as per the API below.
+3- Create a configuration file and load it using log4erl:conf(File)
+> log4erl:conf("priv/log4erl.conf").
+
+4- Alternatevly, you can create loggers & add appenders to them programmatically as appropriate.
+You can do this as per the API below.
> log4erl:add_logger(messages_log).
-> log4erl:add_file_appender(messages_log, file_logs, Conf).
- where Conf is the configuration file or erlang term describing how the log is to be handled
+> log4erl:add_console_appender(messages_log, cmd_logs, {warn, "[%L] %l%n"}).
+ where Conf is the erlang term describing how the log is to be handled
You can also add more types of appenders, which is explained in API.txt and Appneders_API.txt.
-4- Now, you can log whatever messages you like as per logging functions described in API.
+5- Now, you can log whatever messages you like as per logging functions described in API.
+> log4erl:info("Information message").
Precedance of log levels are:
all = debug < info < warn < error < fatal < none
@@ -72,14 +78,18 @@ User defined levels are always written except when none level is specified in th
=======
Please look at API.txt file for more information about the API.
-5. KNOWN ISSUES:
+5. CONFIGURATION:
+=================
+Please look at CONFIGURATION.txt for more information about how to configure log4erl.
+
+6. KNOWN ISSUES:
================
- Name of both loggers & appenders should be unique and not registered since log4erl will try and register
their names. If the name is already registered, nothing will happen. This will be fixed soon.
- If you run change_log_format/1,2 and appender crashed, a restart from the supervisor will not record the latest
format used. It will only use either the default format or the format used in the argument is supplied.
-6. FUTURE DEVELOPMENT:
+7. FUTURE DEVELOPMENT:
======================
- Add support for extensive file-based configuration
- Add support for different log persistance methods (e.g files, XML, console, DB, SNMP, syslog...etc)
@@ -89,7 +99,7 @@ Please look at API.txt file for more information about the API.
Please send your suggestion to ahmed.nawras <at @ at> gmail <dot . dot> com
-7. LICENSE:
+8. LICENSE:
===========
This software is subject to "Mozilla Public License 1.1". You can find the license terms
in the file 'LICENSE.txt' shipping along with the source code. You may also get a copy
View
6 TODO.txt
@@ -7,12 +7,12 @@ default formatting patters [DONE]
* Update manual [DONE (latest for log4erl 0.8.2)]
* Add performance benchmarks
* Add support for file-based configuration to log4erl instead of only
-programmable-only configuration that is working now
+programmable-only configuration that is working now [DONE]
* Add support for SNMP appender
* Add support for DB appender (MySQL, Postgres?, Mnesia,...etc)
-* Add support for SMTP appender
+* Add support for SMTP appender [DONE]
* Add support for NT event appender
-* Add support for syslog appender
+* Add support for syslog appender [DONE]
* Add support for NDC/MDC
* Add support for time-based log rotation (file_appender)
View
2  ebin/log4erl.app
@@ -2,7 +2,7 @@
%% application.
{application, log4erl,
[{description, "Logger for erlang in the spirit of Log4J"},
- {vsn, "0.8.4"},
+ {vsn, "0.8.5"},
{modules, [log4erl]},
{registered,[log4erl]},
{applications, [kernel,stdlib]},
View
10 include/log4erl.hrl
@@ -36,16 +36,18 @@
%% The filename of a log is file_name ++ "_" ++ counter ++ "." ++ suffix
%% e.g. log_1.txt
%% tokens = format tokens generated from log_formatter:parse/1
--record(file_appender, {dir, file_name, fd, counter, log_type, rotation, suffix, level, format}).
+-record(file_appender, {dir, file_name, fd, counter, log_type, rotation, suffix, level, format=?DEFAULT_FORMAT}).
--record(console_appender, {level, format}).
+-record(console_appender, {level=?DEFAULT_LEVEL, format=?DEFAULT_FORMAT}).
-record(rotation_state, {state, timer}).
--record(smtp_appender, {level, srvr_opts, auth_opts, msg_opts}).
+-record(smtp_appender, {level=?DEFAULT_LEVEL, srvr_opts, auth_opts, msg_opts}).
-record(srvr_opts, {ip, port}).
-record(auth_opts, {username, password}).
--record(msg_opts, {from, to, title, msg}).
+-record(msg_opts, {from, to, title, msg=?DEFAULT_FORMAT}).
+
+-record(syslog_appender, {level=?DEFAULT_LEVEL, facility=user,host,port=415, socket, format=?DEFAULT_FORMAT}).
%% log record
-record(log, {level, msg, data, time, millis}).
View
4 src/Makefile
@@ -10,8 +10,8 @@ BEAMS=$(ERLS:.erl=.beam)
.erl.beam:
$(ERLC) -W $<
-.yrl.erl:
- $(ERLC)-W $<
+#.yrl.erl:
+# $(ERLC)-W $<
# Here's a list of the erlang modules you want compiling
View
16 src/console_appender.erl
@@ -7,6 +7,22 @@
-export([init/1, handle_event/2, handle_call/2,
handle_info/2, terminate/2, code_change/3]).
+init({conf, Conf}) when is_list(Conf) ->
+ CL = lists:foldl(fun(X, List) ->
+ [proplists:get_value(X,Conf)|List]
+ end,
+ [],
+ [level, format]),
+
+ %% in case format doesn't exist
+ Res = case hd(CL) of
+ undefined ->
+ [_|CL2] = CL,
+ lists:reverse(CL2);
+ _ ->
+ lists:reverse(CL)
+ end,
+ init(list_to_tuple(Res));
init({Level}) ->
init({Level, ?DEFAULT_FORMAT});
init({Level, Format} = _Args) ->
View
26 src/file_appender.erl
@@ -8,6 +8,8 @@
-include("../include/log4erl.hrl").
-include_lib("kernel/include/file.hrl").
+-import(log4erl_utils, [to_list/1, to_atom/1, to_int/1]).
+
%% gen_event callbacks
-export([init/1, handle_event/2, handle_call/2,
handle_info/2, terminate/2, code_change/3]).
@@ -15,12 +17,28 @@
%%======================================
%% gen_event callback functions
%%======================================
+init({conf, Conf}) when is_list(Conf) ->
+ CL = lists:foldl(fun(X, List) ->
+ [proplists:get_value(X,Conf)|List]
+ end,
+ [],
+ [dir, file, type, max, rotation, suffix, level, format]),
+
+ %% in case format doesn't exist
+ Res = case hd(CL) of
+ undefined ->
+ [_|CL2] = CL,
+ lists:reverse(CL2);
+ _ ->
+ lists:reverse(CL)
+ end,
+ init(list_to_tuple(Res));
init({Dir, Fname, {Type, Max}, Rot, Suf, Level})->
?LOG("file_appender:init() - with default format~n"),
init({Dir, Fname, {Type, Max}, Rot, Suf, Level, ?DEFAULT_FORMAT});
%% This one with custom format
init({Dir, Fname, {Type, Max}, Rot, Suf, Level, Pattern} = _Conf) ->
- ?LOG("file_appender:init() - 1~n"),
+ ?LOG2("file_appender:init() - 1 ~p~n",[_Conf]),
File = Dir ++ "/" ++ Fname ++ "." ++ Suf,
{ok, Fd} = file:open(File, ?FILE_OPTIONS),
Ltype = #log_type{type = Type, max = Max},
@@ -39,6 +57,12 @@ init({Dir, Fname, {Type, Max}, Rot, Suf, Level, Pattern} = _Conf) ->
level=Level, format=Format},
?LOG2("file_appender:init() with conf ~p~n",[State]),
{ok, State};
+% These 2 are for result of reading conf file
+init({Dir, Fname, Type, Max, Rot, Suf, Level}) ->
+ init({to_list(Dir), to_list(Fname), {to_atom(Type), to_int(Max)}, to_int(Rot), to_list(Suf), to_atom(Level)});
+init({Dir, Fname, Type, Max, Rot, Suf, Level, Format}) ->
+ init({to_list(Dir), to_list(Fname), {to_atom(Type), to_int(Max)}, to_int(Rot), to_list(Suf), to_atom(Level), to_list(Format)});
+% This is for reading from a config file only for one appender
init(Conf) when is_list(Conf) ->
?LOG2("file_appender:init() ~p~n",[Conf]),
case file:consult(Conf) of
View
24 src/log4erl.erl
@@ -13,11 +13,12 @@
-export([change_log_level/1, change_log_level/2]).
-export([change_level/2, change_level/3]).
--export([add_logger/1]).
+-export([add_logger/1, conf/1]).
-export([add_appender/2, add_appender/3]).
-export([add_file_appender/2, add_file_appender/3]).
-export([add_console_appender/2, add_console_appender/3]).
-export([add_smtp_appender/2, add_smtp_appender/3]).
+-export([add_syslog_appender/2, add_syslog_appender/3]).
-export([add_dummy_appender/2, add_dummy_appender/3]).
-export([get_appenders/0, get_appenders/1]).
-export([change_format/2, change_format/3]).
@@ -51,12 +52,6 @@ add_appender(Appender, Conf) ->
%% Appender = {Appender, Name}
add_appender(Logger, Appender, Conf) ->
try_msg({add_appender, Logger, Appender, Conf}).
-
-add_smtp_appender(Name, Conf) ->
- add_appender({smtp_appender, Name}, Conf).
-
-add_smtp_appender(Logger, Name, Conf) ->
- add_appender(Logger, {smtp_appender, Name}, Conf).
add_console_appender(AName, Conf) ->
add_appender({console_appender, AName}, Conf).
@@ -70,6 +65,18 @@ add_file_appender(AName, Conf) ->
add_file_appender(Logger, AName, Conf) ->
add_appender(Logger, {file_appender, AName}, Conf).
+add_smtp_appender(Name, Conf) ->
+ add_appender({smtp_appender, Name}, Conf).
+
+add_smtp_appender(Logger, Name, Conf) ->
+ add_appender(Logger, {smtp_appender, Name}, Conf).
+
+add_syslog_appender(Name, Conf) ->
+ add_appender({syslog_appender, Name}, Conf).
+
+add_syslog_appender(Logger, Name, Conf) ->
+ add_appender(Logger, {syslog_appender, Name}, Conf).
+
add_dummy_appender(AName, Conf) ->
add_appender({dummy_appender, AName}, Conf).
@@ -82,6 +89,9 @@ get_appenders() ->
get_appenders(Logger) ->
try_msg({get_appenders, Logger}).
+conf(File) ->
+ log4erl_conf:conf(File).
+
change_format(Appender, Format) ->
try_msg({change_format, Appender, Format}).
change_format(Logger, Appender, Format) ->
View
59 src/log4erl_conf.erl
@@ -0,0 +1,59 @@
+-module(log4erl_conf).
+
+-export([conf/1]).
+
+leex(File) ->
+ {ok, Bin} = file:read_file(File),
+ F = binary_to_list(Bin),
+ R = log4erl_lex:string(F),
+ case R of
+ {ok, Tokens, _} ->
+ Tokens;
+ _ ->
+ io:format("Error ~p~n",[R])
+ end.
+
+parse(Tokens) ->
+ R = log4erl_parser:parse(Tokens),
+ case R of
+ {ok, T} ->
+ T;
+ {error, {Line, _, EMsg}} ->
+ io:format("Error in line ~p with message: ~p~n",[Line, lists:flatten(EMsg)]),
+ throw({parser_error, Line, EMsg})
+ end.
+
+conf(File) ->
+ Tree = parse(leex(File)),
+ traverse(Tree).
+
+traverse([]) ->
+ ok;
+traverse([H|Tree]) ->
+ logger(H),
+ traverse(Tree).
+
+logger({default_logger, Appenders}) ->
+ appenders(Appenders);
+logger({logger, Logger, Appenders}) ->
+ log4erl:add_logger(Logger),
+ appenders(Logger, Appenders).
+
+appenders([]) ->
+ ok;
+appenders([H|Apps]) ->
+ appender(H),
+ appenders(Apps).
+
+appenders(_, []) ->
+ ok;
+appenders(Logger, [H|Apps]) ->
+ appender(Logger, H),
+ appenders(Logger, Apps).
+
+appender({appender, App, Name, Conf}) ->
+ log4erl:add_appender({App, Name}, {conf, Conf}).
+
+appender(Logger, {appender, App, Name, Conf}) ->
+ log4erl:add_appender(Logger, {App, Name}, {conf, Conf}).
+
View
676 src/log4erl_lex.erl
@@ -0,0 +1,676 @@
+%% The source of this file is part of leex distribution, as such it
+%% has the same Copyright as the other files in the leex
+%% distribution. The Copyright is defined in the accompanying file
+%% COPYRIGHT. However, the resultant scanner generated by leex is the
+%% property of the creator of the scanner and is not covered by that
+%% Copyright.
+
+-module(log4erl_lex).
+
+-export([string/1,string/2,token/2,token/3,tokens/2,tokens/3]).
+-export([format_error/1]).
+
+%% User code. This is placed here to allow extra attributes.
+
+strip(TokenChars,TokenLen) ->
+ lists:sublist(TokenChars, 2, TokenLen - 2).
+
+format_error({illegal,S}) -> ["illegal characters ",io_lib:write_string(S)];
+format_error({user,S}) -> S.
+
+string(String) -> string(String, 1).
+
+string(String, Line) -> string(String, Line, String, []).
+
+%% string(InChars, Line, TokenChars, Tokens) ->
+%% {ok,Tokens,Line} | {error,ErrorInfo,Line}.
+%% Note the line number going into yystate, L0, is line of token
+%% start while line number returned is line of token end. We want line
+%% of token start.
+
+string([], L, [], Ts) -> %No partial tokens!
+ {ok,yyrev(Ts),L};
+string(Ics0, L0, Tcs, Ts) ->
+ case yystate(yystate(), Ics0, L0, 0, reject, 0) of
+ {A,Alen,Ics1,L1} -> %Accepting end state
+ string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L0), Ts);
+ {A,Alen,Ics1,L1,_S1} -> %Accepting transistion state
+ string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L0), Ts);
+ {reject,_Alen,Tlen,_Ics1,L1,_S1} -> %After a non-accepting state
+ {error,{L0,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1};
+ {A,Alen,_Tlen,_Ics1,L1,_S1} ->
+ string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L0), Ts)
+ end.
+
+%% string_cont(RestChars, Line, Token, Tokens)
+%% Test for and remove the end token wrapper. Push back characters
+%% are prepended to RestChars.
+
+string_cont(Rest, Line, {token,T}, Ts) ->
+ string(Rest, Line, Rest, [T|Ts]);
+string_cont(Rest, Line, {token,T,Push}, Ts) ->
+ NewRest = Push ++ Rest,
+ string(NewRest, Line, NewRest, [T|Ts]);
+string_cont(Rest, Line, {end_token,T}, Ts) ->
+ string(Rest, Line, Rest, [T|Ts]);
+string_cont(Rest, Line, {end_token,T,Push}, Ts) ->
+ NewRest = Push ++ Rest,
+ string(NewRest, Line, NewRest, [T|Ts]);
+string_cont(Rest, Line, skip_token, Ts) ->
+ string(Rest, Line, Rest, Ts);
+string_cont(Rest, Line, {skip_token,Push}, Ts) ->
+ NewRest = Push ++ Rest,
+ string(NewRest, Line, NewRest, Ts);
+string_cont(_Rest, Line, {error,S}, _Ts) ->
+ {error,{Line,?MODULE,{user,S}},Line}.
+
+%% token(Continuation, Chars) ->
+%% token(Continuation, Chars, Line) ->
+%% {more,Continuation} | {done,ReturnVal,RestChars}.
+%% Must be careful when re-entering to append the latest characters to the
+%% after characters in an accept. The continuation is:
+%% {token,State,CurrLine,TokenChars,TokenLen,TokenLine,AccAction,AccLen}
+
+token(Cont, Chars) -> token(Cont, Chars, 1).
+
+token([], Chars, Line) ->
+ token(yystate(), Chars, Line, Chars, 0, Line, reject, 0);
+token({token,State,Line,Tcs,Tlen,Tline,Action,Alen}, Chars, _) ->
+ token(State, Chars, Line, Tcs ++ Chars, Tlen, Tline, Action, Alen).
+
+%% token(State, InChars, Line, TokenChars, TokenLen, TokenLine,
+%% AcceptAction, AcceptLen) ->
+%% {more,Continuation} | {done,ReturnVal,RestChars}.
+%% The argument order is chosen to be more efficient.
+
+token(S0, Ics0, L0, Tcs, Tlen0, Tline, A0, Alen0) ->
+ case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
+ %% Accepting end state, we have a token.
+ {A1,Alen1,Ics1,L1} ->
+ token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline));
+ %% Accepting transition state, can take more chars.
+ {A1,Alen1,[],L1,S1} -> %Need more chars to check
+ {more,{token,S1,Tcs,L1,Alen1,Tline,A1,Alen1}};
+ {A1,Alen1,Ics1,L1,_S1} -> %Take what we got
+ token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline));
+ %% After a non-accepting state, maybe reach accept state later.
+ {A1,Alen1,Tlen1,[],L1,S1} -> %Need more chars to check
+ {more,{token,S1,Tcs,L1,Tlen1,Tline,A1,Alen1}};
+ {reject,_Alen1,Tlen1,eof,L1,_S1} -> %No token match
+ %% Check for partial token which is error.
+ Ret = if Tlen1 > 0 -> {error,{Tline,?MODULE,
+ %% Skip eof tail in Tcs.
+ {illegal,yypre(Tcs, Tlen1)}},L1};
+ true -> {eof,L1}
+ end,
+ {done,Ret,eof};
+ {reject,_Alen1,Tlen1,Ics1,L1,_S1} -> %No token match
+ Error = {Tline,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},
+ {done,{error,Error,L1},Ics1};
+ {A1,Alen1,_Tlen1,_Ics1,L1,_S1} -> %Use last accept match
+ token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, Tline))
+ end.
+
+%% tokens_cont(RestChars, Line, Token)
+%% If we have a token or error then return done, else if we have a
+%% skip_token then continue.
+
+token_cont(Rest, Line, {token,T}) ->
+ {done,{ok,T,Line},Rest};
+token_cont(Rest, Line, {token,T,Push}) ->
+ NewRest = Push ++ Rest,
+ {done,{ok,T,Line},NewRest};
+token_cont(Rest, Line, {end_token,T}) ->
+ {done,{ok,T,Line},Rest};
+token_cont(Rest, Line, {end_token,T,Push}) ->
+ NewRest = Push ++ Rest,
+ {done,{ok,T,Line},NewRest};
+token_cont(Rest, Line, skip_token) ->
+ token(yystate(), Rest, Line, Rest, 0, Line, reject, 0);
+token_cont(Rest, Line, {skip_token,Push}) ->
+ NewRest = Push ++ Rest,
+ token(yystate(), NewRest, Line, NewRest, 0, Line, reject, 0);
+token_cont(Rest, Line, {error,S}) ->
+ {done,{error,{Line,?MODULE,{user,S}},Line},Rest}.
+
+%% tokens(Continuation, Chars, Line) ->
+%% {more,Continuation} | {done,ReturnVal,RestChars}.
+%% Must be careful when re-entering to append the latest characters to the
+%% after characters in an accept. The continuation is:
+%% {tokens,State,CurrLine,TokenChars,TokenLen,TokenLine,Tokens,AccAction,AccLen}
+%% {skip_tokens,State,CurrLine,TokenChars,TokenLen,TokenLine,Error,AccAction,AccLen}
+
+tokens(Cont, Chars) -> tokens(Cont, Chars, 1).
+
+tokens([], Chars, Line) ->
+ tokens(yystate(), Chars, Line, Chars, 0, Line, [], reject, 0);
+tokens({tokens,State,Line,Tcs,Tlen,Tline,Ts,Action,Alen}, Chars, _) ->
+ tokens(State, Chars, Line, Tcs ++ Chars, Tlen, Tline, Ts, Action, Alen);
+tokens({skip_tokens,State,Line,Tcs,Tlen,Tline,Error,Action,Alen}, Chars, _) ->
+ skip_tokens(State, Chars, Line, Tcs ++ Chars, Tlen, Tline, Error, Action, Alen).
+
+%% tokens(State, InChars, Line, TokenChars, TokenLen, TokenLine, Tokens,
+%% AcceptAction, AcceptLen) ->
+%% {more,Continuation} | {done,ReturnVal,RestChars}.
+
+tokens(S0, Ics0, L0, Tcs, Tlen0, Tline, Ts, A0, Alen0) ->
+ case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
+ %% Accepting end state, we have a token.
+ {A1,Alen1,Ics1,L1} ->
+ tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Ts);
+ %% Accepting transition state, can take more chars.
+ {A1,Alen1,[],L1,S1} -> %Need more chars to check
+ {more,{tokens,S1,L1,Tcs,Alen1,Tline,Ts,A1,Alen1}};
+ {A1,Alen1,Ics1,L1,_S1} -> %Take what we got
+ tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Ts);
+ %% After a non-accepting state, maybe reach accept state later.
+ {A1,Alen1,Tlen1,[],L1,S1} -> %Need more chars to check
+ {more,{tokens,S1,L1,Tcs,Tlen1,Tline,Ts,A1,Alen1}};
+ {reject,_Alen1,Tlen1,eof,L1,_S1} -> %No token match
+ %% Check for partial token which is error, no need to skip here.
+ Ret = if Tlen1 > 0 -> {error,{Tline,?MODULE,
+ %% Skip eof tail in Tcs.
+ {illegal,yypre(Tcs, Tlen1)}},L1};
+ Ts == [] -> {eof,L1};
+ true -> {ok,yyrev(Ts),L1}
+ end,
+ {done,Ret,eof};
+ {reject,_Alen1,Tlen1,_Ics1,L1,_S1} ->
+ %% Skip rest of tokens.
+ Error = {L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},
+ skip_tokens(yysuf(Tcs, Tlen1+1), L1, Error);
+ {A1,Alen1,_Tlen1,_Ics1,L1,_S1} ->
+ Token = yyaction(A1, Alen1, Tcs, Tline),
+ tokens_cont(yysuf(Tcs, Alen1), L1, Token, Ts)
+ end.
+
+%% tokens_cont(RestChars, Line, Token, Tokens)
+%% If we have a end_token or error then return done, else if we have
+%% a token then save it and continue, else if we have a skip_token
+%% just continue.
+
+tokens_cont(Rest, Line, {token,T}, Ts) ->
+ tokens(yystate(), Rest, Line, Rest, 0, Line, [T|Ts], reject, 0);
+tokens_cont(Rest, Line, {token,T,Push}, Ts) ->
+ NewRest = Push ++ Rest,
+ tokens(yystate(), NewRest, Line, NewRest, 0, Line, [T|Ts], reject, 0);
+tokens_cont(Rest, Line, {end_token,T}, Ts) ->
+ {done,{ok,yyrev(Ts, [T]),Line},Rest};
+tokens_cont(Rest, Line, {end_token,T,Push}, Ts) ->
+ NewRest = Push ++ Rest,
+ {done,{ok,yyrev(Ts, [T]),Line},NewRest};
+tokens_cont(Rest, Line, skip_token, Ts) ->
+ tokens(yystate(), Rest, Line, Rest, 0, Line, Ts, reject, 0);
+tokens_cont(Rest, Line, {skip_token,Push}, Ts) ->
+ NewRest = Push ++ Rest,
+ tokens(yystate(), NewRest, Line, NewRest, 0, Line, Ts, reject, 0);
+tokens_cont(Rest, Line, {error,S}, _Ts) ->
+ skip_tokens(Rest, Line, {Line,?MODULE,{user,S}}).
+
+%%skip_tokens(InChars, Line, Error) -> {done,{error,Error,Line},Ics}.
+%% Skip tokens until an end token, junk everything and return the error.
+
+skip_tokens(Ics, Line, Error) ->
+ skip_tokens(yystate(), Ics, Line, Ics, 0, Line, Error, reject, 0).
+
+%% skip_tokens(State, InChars, Line, TokenChars, TokenLen, TokenLine, Tokens,
+%% AcceptAction, AcceptLen) ->
+%% {more,Continuation} | {done,ReturnVal,RestChars}.
+
+skip_tokens(S0, Ics0, L0, Tcs, Tlen0, Tline, Error, A0, Alen0) ->
+ case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
+ {A1,Alen1,Ics1,L1} -> %Accepting end state
+ skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Error);
+ {A1,Alen1,[],L1,S1} -> %After an accepting state
+ {more,{skip_tokens,S1,L1,Tcs,Alen1,Tline,Error,A1,Alen1}};
+ {A1,Alen1,Ics1,L1,_S1} ->
+ skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Error);
+ {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state
+ {more,{skip_tokens,S1,L1,Tcs,Tlen1,Tline,Error,A1,Alen1}};
+ {reject,_Alen1,_Tlen1,eof,L1,_S1} ->
+ {done,{error,Error,L1},eof};
+ {reject,_Alen1,Tlen1,_Ics1,L1,_S1} ->
+ skip_tokens(yysuf(Tcs, Tlen1+1), L1, Error);
+ {A1,Alen1,_Tlen1,_Ics1,L1,_S1} ->
+ Token = yyaction(A1, Alen1, Tcs, Tline),
+ skip_cont(yysuf(Tcs, Alen1), L1, Token, Error)
+ end.
+
+%% skip_cont(RestChars, Line, Token, Error)
+%% Skip tokens until we have an end_token or error then return done
+%% with the original rror.
+
+skip_cont(Rest, Line, {token,_T}, Error) ->
+ skip_tokens(yystate(), Rest, Line, Rest, 0, Line, Error, reject, 0);
+skip_cont(Rest, Line, {token,_T,Push}, Error) ->
+ NewRest = Push ++ Rest,
+ skip_tokens(yystate(), NewRest, Line, NewRest, 0, Line, Error, reject, 0);
+skip_cont(Rest, Line, {end_token,_T}, Error) ->
+ {done,{error,Error,Line},Rest};
+skip_cont(Rest, Line, {end_token,_T,Push}, Error) ->
+ NewRest = Push ++ Rest,
+ {done,{error,Error,Line},NewRest};
+skip_cont(Rest, Line, skip_token, Error) ->
+ skip_tokens(yystate(), Rest, Line, Rest, 0, Line, Error, reject, 0);
+skip_cont(Rest, Line, {skip_token,Push}, Error) ->
+ NewRest = Push ++ Rest,
+ skip_tokens(yystate(), NewRest, Line, NewRest, 0, Line, Error, reject, 0);
+skip_cont(Rest, Line, {error,_S}, Error) ->
+ skip_tokens(yystate(), Rest, Line, Rest, 0, Line, Error, reject, 0).
+
+yyrev(List) -> lists:reverse(List).
+yyrev(List, Tail) -> lists:reverse(List, Tail).
+yypre(List, N) -> lists:sublist(List, N).
+yysuf(List, N) -> lists:nthtail(N, List).
+
+%% yystate() -> InitialState.
+%% yystate(State, InChars, Line, CurrTokLen, AcceptAction, AcceptLen) ->
+%% {Action, AcceptLen, RestChars, Line} |
+%% {Action, AcceptLen, RestChars, Line, State} |
+%% {reject, AcceptLen, CurrTokLen, RestChars, Line, State} |
+%% {Action, AcceptLen, CurrTokLen, RestChars, Line, State}.
+%% Generated state transition functions. The non-accepting end state
+%% return signal either an unrecognised character or end of current
+%% input.
+
+yystate() -> 21.
+
+yystate(24, [116|Ics], Line, Tlen, _, _) ->
+ yystate(20, Ics, Line, Tlen+1, 3, Tlen);
+yystate(24, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(24, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(24, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(24, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 115 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(24, [C|Ics], Line, Tlen, _, _) when C >= 117, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(24, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,24};
+yystate(23, [37|Ics], Line, Tlen, _, _) ->
+ yystate(7, Ics, Line, Tlen+1, 7, Tlen);
+yystate(23, [10|Ics], Line, Tlen, _, _) ->
+ yystate(23, Ics, Line+1, Tlen+1, 7, Tlen);
+yystate(23, [C|Ics], Line, Tlen, _, _) when C >= 0, C =< 9 ->
+ yystate(23, Ics, Line, Tlen+1, 7, Tlen);
+yystate(23, [C|Ics], Line, Tlen, _, _) when C >= 11, C =< 32 ->
+ yystate(23, Ics, Line, Tlen+1, 7, Tlen);
+yystate(23, Ics, Line, Tlen, _, _) ->
+ {7,Tlen,Ics,Line,23};
+yystate(22, [108|Ics], Line, Tlen, _, _) ->
+ yystate(24, Ics, Line, Tlen+1, 3, Tlen);
+yystate(22, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(22, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(22, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(22, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 107 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(22, [C|Ics], Line, Tlen, _, _) when C >= 109, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(22, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,22};
+yystate(21, [125|Ics], Line, Tlen, Action, Alen) ->
+ yystate(8, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [123|Ics], Line, Tlen, Action, Alen) ->
+ yystate(8, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [108|Ics], Line, Tlen, Action, Alen) ->
+ yystate(17, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [100|Ics], Line, Tlen, Action, Alen) ->
+ yystate(6, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [95|Ics], Line, Tlen, Action, Alen) ->
+ yystate(16, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [61|Ics], Line, Tlen, Action, Alen) ->
+ yystate(8, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [44|Ics], Line, Tlen, Action, Alen) ->
+ yystate(8, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [39|Ics], Line, Tlen, Action, Alen) ->
+ yystate(4, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [37|Ics], Line, Tlen, Action, Alen) ->
+ yystate(7, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [34|Ics], Line, Tlen, Action, Alen) ->
+ yystate(11, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [10|Ics], Line, Tlen, Action, Alen) ->
+ yystate(23, Ics, Line+1, Tlen+1, Action, Alen);
+yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= 0, C =< 9 ->
+ yystate(23, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= 11, C =< 32 ->
+ yystate(23, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= 48, C =< 57 ->
+ yystate(12, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= 97, C =< 99 ->
+ yystate(16, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= 101, C =< 107 ->
+ yystate(16, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, [C|Ics], Line, Tlen, Action, Alen) when C >= 109, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, Action, Alen);
+yystate(21, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,21};
+yystate(20, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 1, Tlen);
+yystate(20, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 1, Tlen);
+yystate(20, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 1, Tlen);
+yystate(20, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 1, Tlen);
+yystate(20, Ics, Line, Tlen, _, _) ->
+ {1,Tlen,Ics,Line,20};
+yystate(19, Ics, Line, Tlen, _, _) ->
+ {5,Tlen,Ics,Line};
+yystate(18, [117|Ics], Line, Tlen, _, _) ->
+ yystate(22, Ics, Line, Tlen+1, 3, Tlen);
+yystate(18, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(18, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(18, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(18, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 116 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(18, [C|Ics], Line, Tlen, _, _) when C >= 118, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(18, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,18};
+yystate(17, [111|Ics], Line, Tlen, _, _) ->
+ yystate(13, Ics, Line, Tlen+1, 3, Tlen);
+yystate(17, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(17, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(17, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(17, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 110 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(17, [C|Ics], Line, Tlen, _, _) when C >= 112, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(17, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,17};
+yystate(16, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(16, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(16, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(16, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(16, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,16};
+yystate(15, [95|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [93|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [62|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [60|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [45|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [46|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [34|Ics], Line, Tlen, Action, Alen) ->
+ yystate(19, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [32|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= 35, C =< 37 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= 40, C =< 42 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= 48, C =< 58 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= 64, C =< 91 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, [C|Ics], Line, Tlen, Action, Alen) when C >= 97, C =< 122 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(15, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,15};
+yystate(14, [97|Ics], Line, Tlen, _, _) ->
+ yystate(18, Ics, Line, Tlen+1, 3, Tlen);
+yystate(14, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(14, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(14, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(14, [C|Ics], Line, Tlen, _, _) when C >= 98, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(14, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,14};
+yystate(13, [103|Ics], Line, Tlen, _, _) ->
+ yystate(9, Ics, Line, Tlen+1, 3, Tlen);
+yystate(13, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(13, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(13, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(13, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 102 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(13, [C|Ics], Line, Tlen, _, _) when C >= 104, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(13, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,13};
+yystate(12, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 2, Tlen);
+yystate(12, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(12, Ics, Line, Tlen+1, 2, Tlen);
+yystate(12, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 2, Tlen);
+yystate(12, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 2, Tlen);
+yystate(12, Ics, Line, Tlen, _, _) ->
+ {2,Tlen,Ics,Line,12};
+yystate(11, [95|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [93|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [62|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [60|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [45|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [46|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [32|Ics], Line, Tlen, Action, Alen) ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [C|Ics], Line, Tlen, Action, Alen) when C >= 35, C =< 37 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [C|Ics], Line, Tlen, Action, Alen) when C >= 40, C =< 42 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [C|Ics], Line, Tlen, Action, Alen) when C >= 48, C =< 58 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [C|Ics], Line, Tlen, Action, Alen) when C >= 64, C =< 91 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, [C|Ics], Line, Tlen, Action, Alen) when C >= 97, C =< 122 ->
+ yystate(15, Ics, Line, Tlen+1, Action, Alen);
+yystate(11, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,11};
+yystate(10, [102|Ics], Line, Tlen, _, _) ->
+ yystate(14, Ics, Line, Tlen+1, 3, Tlen);
+yystate(10, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(10, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(10, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(10, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 101 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(10, [C|Ics], Line, Tlen, _, _) when C >= 103, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(10, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,10};
+yystate(9, [103|Ics], Line, Tlen, _, _) ->
+ yystate(5, Ics, Line, Tlen+1, 3, Tlen);
+yystate(9, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(9, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(9, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(9, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 102 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(9, [C|Ics], Line, Tlen, _, _) when C >= 104, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(9, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,9};
+yystate(8, Ics, Line, Tlen, _, _) ->
+ {6,Tlen,Ics,Line};
+yystate(7, [37|Ics], Line, Tlen, _, _) ->
+ yystate(7, Ics, Line, Tlen+1, 7, Tlen);
+yystate(7, [10|Ics], Line, Tlen, _, _) ->
+ yystate(23, Ics, Line+1, Tlen+1, 7, Tlen);
+yystate(7, [C|Ics], Line, Tlen, _, _) when C >= 0, C =< 9 ->
+ yystate(7, Ics, Line, Tlen+1, 7, Tlen);
+yystate(7, [C|Ics], Line, Tlen, _, _) when C >= 11, C =< 32 ->
+ yystate(7, Ics, Line, Tlen+1, 7, Tlen);
+yystate(7, [C|Ics], Line, Tlen, _, _) when C >= 33, C =< 36 ->
+ yystate(7, Ics, Line, Tlen+1, 7, Tlen);
+yystate(7, [C|Ics], Line, Tlen, _, _) when C >= 38 ->
+ yystate(7, Ics, Line, Tlen+1, 7, Tlen);
+yystate(7, Ics, Line, Tlen, _, _) ->
+ {7,Tlen,Ics,Line,7};
+yystate(6, [101|Ics], Line, Tlen, _, _) ->
+ yystate(10, Ics, Line, Tlen+1, 3, Tlen);
+yystate(6, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(6, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(6, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(6, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 100 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(6, [C|Ics], Line, Tlen, _, _) when C >= 102, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(6, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,6};
+yystate(5, [101|Ics], Line, Tlen, _, _) ->
+ yystate(1, Ics, Line, Tlen+1, 3, Tlen);
+yystate(5, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(5, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(5, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(5, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 100 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(5, [C|Ics], Line, Tlen, _, _) when C >= 102, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(5, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,5};
+yystate(4, [95|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [93|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [62|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [60|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [45|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [46|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [32|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= 35, C =< 37 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= 40, C =< 42 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= 48, C =< 58 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= 64, C =< 91 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, [C|Ics], Line, Tlen, Action, Alen) when C >= 97, C =< 122 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(4, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,4};
+yystate(3, Ics, Line, Tlen, _, _) ->
+ {4,Tlen,Ics,Line};
+yystate(2, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 0, Tlen);
+yystate(2, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 0, Tlen);
+yystate(2, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 0, Tlen);
+yystate(2, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 0, Tlen);
+yystate(2, Ics, Line, Tlen, _, _) ->
+ {0,Tlen,Ics,Line,2};
+yystate(1, [114|Ics], Line, Tlen, _, _) ->
+ yystate(2, Ics, Line, Tlen+1, 3, Tlen);
+yystate(1, [95|Ics], Line, Tlen, _, _) ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(1, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(1, [C|Ics], Line, Tlen, _, _) when C >= 65, C =< 90 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(1, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 113 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(1, [C|Ics], Line, Tlen, _, _) when C >= 115, C =< 122 ->
+ yystate(16, Ics, Line, Tlen+1, 3, Tlen);
+yystate(1, Ics, Line, Tlen, _, _) ->
+ {3,Tlen,Ics,Line,1};
+yystate(0, [95|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [93|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [62|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [60|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [45|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [46|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [39|Ics], Line, Tlen, Action, Alen) ->
+ yystate(3, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [32|Ics], Line, Tlen, Action, Alen) ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= 35, C =< 37 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= 40, C =< 42 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= 48, C =< 58 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= 64, C =< 91 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, [C|Ics], Line, Tlen, Action, Alen) when C >= 97, C =< 122 ->
+ yystate(0, Ics, Line, Tlen+1, Action, Alen);
+yystate(0, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,0};
+yystate(S, Ics, Line, Tlen, Action, Alen) ->
+ {Action,Alen,Tlen,Ics,Line,S}.
+
+%% yyaction(Action, TokenLength, TokenChars, TokenLine) ->
+%% {token,Token} | {end_token, Token} | skip_token | {error,String}.
+%% Generated action function.
+
+yyaction(0, TokenLen, YYtcs, TokenLine) ->
+ TokenChars = yypre(YYtcs, TokenLen),
+ {token,{loger,TokenLine,list_to_atom(TokenChars)}};
+yyaction(1, TokenLen, YYtcs, TokenLine) ->
+ TokenChars = yypre(YYtcs, TokenLen),
+ {token,{default,TokenLine,list_to_atom(TokenChars)}};
+yyaction(2, TokenLen, YYtcs, TokenLine) ->
+ TokenChars = yypre(YYtcs, TokenLen),
+ {token,{integer,TokenLine,list_to_integer(TokenChars)}};
+yyaction(3, TokenLen, YYtcs, TokenLine) ->
+ TokenChars = yypre(YYtcs, TokenLen),
+ {token,{atom,TokenLine,list_to_atom(TokenChars)}};
+yyaction(4, TokenLen, YYtcs, TokenLine) ->
+ TokenChars = yypre(YYtcs, TokenLen),
+ {token,{val,TokenLine,strip(TokenChars, TokenLen)}};
+yyaction(5, TokenLen, YYtcs, TokenLine) ->
+ TokenChars = yypre(YYtcs, TokenLen),
+ {token,{val,TokenLine,strip(TokenChars, TokenLen)}};
+yyaction(6, TokenLen, YYtcs, TokenLine) ->
+ TokenChars = yypre(YYtcs, TokenLen),
+ {token,{list_to_atom(TokenChars),TokenLine}};
+yyaction(7, _, _, _) ->
+ skip_token;
+yyaction(_, _, _, _) -> error.
View
23 src/log4erl_lex.xrl
@@ -0,0 +1,23 @@
+Definitions.
+
+D = [0-9]
+L = [A-Z0-9a-z_]
+LS = [\[\]A-Z0-9a-z_\s\%\*\$\#\@\(\)\.\-\>\<\:]
+WS = ([\000-\s]|%.*)
+
+Rules.
+
+logger : {token,{loger,TokenLine, list_to_atom(TokenChars)}}.
+default : {token,{default,TokenLine, list_to_atom(TokenChars)}}.
+{D}+ : {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
+%%{L}+_appender : {token,{apender,TokenLine,list_to_atom(TokenChars)}}.
+{L}+ : {token,{atom,TokenLine,list_to_atom(TokenChars)}}.
+'{LS}+' : {token,{val,TokenLine,strip(TokenChars,TokenLen)}}.
+"{LS}+" : {token,{val,TokenLine,strip(TokenChars,TokenLen)}}.
+[{},=] : {token,{list_to_atom(TokenChars),TokenLine}}.
+{WS}+ : skip_token.
+
+Erlang code.
+
+strip(TokenChars,TokenLen) ->
+ lists:sublist(TokenChars, 2, TokenLen - 2).
View
527 src/log4erl_parser.erl
@@ -0,0 +1,527 @@
+-module(log4erl_parser).
+-export([parse/1, parse_and_scan/1, format_error/1]).
+-file("log4erl_parser.yrl", 30).
+
+unwrap({_,_,V}) -> V.
+
+-file("/opt/erlang/lib/erlang/lib/parsetools-1.4.5/include/yeccpre.hrl", 0).
+%% ``The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
+%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
+%% AB. All Rights Reserved.''
+%%
+%% $Id $
+%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% The parser generator will insert appropriate declarations before this line.%
+
+-type(yecc_ret() :: {'error', _} | {'ok', _}).
+
+-spec(parse/1 :: (_) -> yecc_ret()).
+parse(Tokens) ->
+ yeccpars0(Tokens, false).
+
+-spec(parse_and_scan/1 ::
+ ({function() | {atom(), atom()}, [_]} | {atom(), atom(), [_]}) ->
+ yecc_ret()).
+parse_and_scan({F, A}) -> % Fun or {M, F}
+ yeccpars0([], {F, A});
+parse_and_scan({M, F, A}) ->
+ yeccpars0([], {{M, F}, A}).
+
+-spec(format_error/1 :: (any()) -> [char() | list()]).
+format_error(Message) ->
+ case io_lib:deep_char_list(Message) of
+ true ->
+ Message;
+ _ ->
+ io_lib:write(Message)
+ end.
+
+% To be used in grammar files to throw an error message to the parser
+% toplevel. Doesn't have to be exported!
+-compile({nowarn_unused_function,{return_error,2}}).
+-spec(return_error/2 :: (integer(), any()) -> no_return()).
+return_error(Line, Message) ->
+ throw({error, {Line, ?MODULE, Message}}).
+
+-define(CODE_VERSION, "1.2").
+
+yeccpars0(Tokens, MFA) ->
+ try yeccpars1(Tokens, MFA, 0, [], [])
+ catch
+ error: Error ->
+ Stacktrace = erlang:get_stacktrace(),
+ try yecc_error_type(Error, Stacktrace) of
+ {syntax_error, Token} ->
+ yeccerror(Token);
+ {missing_in_goto_table=Tag, State} ->
+ Desc = {State, Tag},
+ erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
+ Stacktrace);
+ {missing_in_goto_table=Tag, Symbol, State} ->
+ Desc = {Symbol, State, Tag},
+ erlang:raise(error, {yecc_bug, ?CODE_VERSION, Desc},
+ Stacktrace)
+ catch _:_ -> erlang:raise(error, Error, Stacktrace)
+ end;
+ throw: {error, {_Line, ?MODULE, _M}} = Error ->
+ Error % probably from return_error/2
+ end.
+
+yecc_error_type(function_clause, [{?MODULE,F,[_,_,_,_,Token,_,_]} | _]) ->
+ "yeccpars2" ++ _ = atom_to_list(F),
+ {syntax_error, Token};
+yecc_error_type({case_clause,{State}}, [{?MODULE,yeccpars2,_}|_]) ->
+ %% Inlined goto-function
+ {missing_in_goto_table, State};
+yecc_error_type(function_clause, [{?MODULE,F,[State]}|_]) ->
+ "yeccgoto_" ++ SymbolL = atom_to_list(F),
+ {ok,[{atom,_,Symbol}]} = erl_scan:string(SymbolL),
+ {missing_in_goto_table, Symbol, State}.
+
+yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
+ yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
+ Tokenizer);
+yeccpars1([], {F, A}, State, States, Vstack) ->
+ case apply(F, A) of
+ {ok, Tokens, _Endline} ->
+ yeccpars1(Tokens, {F, A}, State, States, Vstack);
+ {eof, _Endline} ->
+ yeccpars1([], false, State, States, Vstack);
+ {error, Descriptor, _Endline} ->
+ {error, Descriptor}
+ end;
+yeccpars1([], false, State, States, Vstack) ->
+ yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
+
+%% yeccpars1/7 is called from generated code.
+%%
+%% When using the {includefile, Includefile} option, make sure that
+%% yeccpars1/7 can be found by parsing the file without following
+%% include directives. yecc will otherwise assume that an old
+%% yeccpre.hrl is included (one which defines yeccpars1/5).
+yeccpars1(State1, State, States, Vstack, Stack1, [Token | Tokens],
+ Tokenizer) ->
+ yeccpars2(State, element(1, Token), [State1 | States],
+ [Stack1 | Vstack], Token, Tokens, Tokenizer);
+yeccpars1(State1, State, States, Vstack, Stack1, [], {F, A}) ->
+ case apply(F, A) of
+ {ok, Tokens, _Endline} ->
+ yeccpars1(State1, State, States, Vstack, Stack1, Tokens, {F, A});
+ {eof, _Endline} ->
+ yeccpars1(State1, State, States, Vstack, Stack1, [], false);
+ {error, Descriptor, _Endline} ->
+ {error, Descriptor}
+ end;
+yeccpars1(State1, State, States, Vstack, Stack1, [], false) ->
+ yeccpars2(State, '$end', [State1 | States], [Stack1 | Vstack],
+ {'$end', 999999}, [], false).
+
+% For internal use only.
+yeccerror(Token) ->
+ {error,
+ {element(2, Token), ?MODULE,
+ ["syntax error before: ", yecctoken2string(Token)]}}.
+
+yecctoken2string({atom, _, A}) -> io_lib:write(A);
+yecctoken2string({integer,_,N}) -> io_lib:write(N);
+yecctoken2string({float,_,F}) -> io_lib:write(F);
+yecctoken2string({char,_,C}) -> io_lib:write_char(C);
+yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
+yecctoken2string({string,_,S}) -> io_lib:write_string(S);
+yecctoken2string({reserved_symbol, _, A}) -> io_lib:format("~w", [A]);
+yecctoken2string({_Cat, _, Val}) -> io_lib:format("~w", [Val]);
+yecctoken2string({dot, _}) -> "'.'";
+yecctoken2string({'$end', _}) ->
+ [];
+yecctoken2string({Other, _}) when is_atom(Other) ->
+ io_lib:format("~w", [Other]);
+yecctoken2string(Other) ->
+ io_lib:write(Other).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+-file("log4erl_parser.erl", 158).
+
+yeccpars2(0=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_0(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(1=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_1(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(2=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_2(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(3=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_3(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(4=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_4(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(5=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_5(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(6=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_6(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(7=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_7(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(8=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_8(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(9=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(10=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(11=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_11(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(12=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_12(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(13=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_13(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(14=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_14(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(15=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_15(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(16=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(17=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_17(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(18=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_18(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(19=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_19(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(20=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(21=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_21(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(22=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_22(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(23=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(24=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_24(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(25=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(26=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_26(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(27=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_27(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(28=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(29=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_29(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(30=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_30(S, Cat, Ss, Stack, T, Ts, Tzr);
+%% yeccpars2(31=S, Cat, Ss, Stack, T, Ts, Tzr) ->
+%% yeccpars2_31(S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccpars2(Other, _, _, _, _, _, _) ->
+ erlang:error({yecc_bug,"1.3",{missing_state_in_action_table, Other}}).
+
+yeccpars2_0(S, loger, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 3, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_1(_S, '$end', _Ss, Stack, _T, _Ts, _Tzr) ->
+ {ok, hd(Stack)}.
+
+yeccpars2_2(S, loger, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 3, Ss, Stack, T, Ts, Tzr);
+yeccpars2_2(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_2_(Stack),
+ yeccgoto_loggers(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+
+yeccpars2_3(S, default, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 6, Ss, Stack, T, Ts, Tzr);
+yeccpars2_3(S, '{', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 9, Ss, Stack, T, Ts, Tzr);
+yeccpars2_3(S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(S, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_4(S, '{', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 28, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_5(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_5_(Stack),
+ yeccgoto_value(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+
+yeccpars2_6(S, '{', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 25, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_7(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_7_(Stack),
+ yeccgoto_value(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+
+yeccpars2_8(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_8_(Stack),
+ yeccgoto_value(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+
+yeccpars2_9(S, atom, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr);
+yeccpars2_9(S, integer, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 7, Ss, Stack, T, Ts, Tzr);
+yeccpars2_9(S, val, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 8, Ss, Stack, T, Ts, Tzr).
+
+%% yeccpars2_10: see yeccpars2_9
+
+yeccpars2_11(S, '}', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 14, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_12(S, atom, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 5, Ss, Stack, T, Ts, Tzr);
+yeccpars2_12(S, integer, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 7, Ss, Stack, T, Ts, Tzr);
+yeccpars2_12(S, val, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 8, Ss, Stack, T, Ts, Tzr);
+yeccpars2_12(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_12_(Stack),
+ yeccgoto_appenders(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+
+yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_|Nss] = Ss,
+ NewStack = yeccpars2_13_(Stack),
+ yeccgoto_appenders(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+yeccpars2_14(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_,_|Nss] = Ss,
+ NewStack = yeccpars2_14_(Stack),
+ yeccgoto_logger(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+yeccpars2_15(S, '{', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 16, Ss, Stack, T, Ts, Tzr).
+
+%% yeccpars2_16: see yeccpars2_9
+
+yeccpars2_17(S, '=', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 23, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_18(S, '}', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 22, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_19(S, ',', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 20, Ss, Stack, T, Ts, Tzr);
+yeccpars2_19(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ NewStack = yeccpars2_19_(Stack),
+ yeccgoto_props(hd(Ss), Cat, Ss, NewStack, T, Ts, Tzr).
+
+%% yeccpars2_20: see yeccpars2_9
+
+yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_|Nss] = Ss,
+ NewStack = yeccpars2_21_(Stack),
+ yeccgoto_props(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+yeccpars2_22(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_,_,_|Nss] = Ss,
+ NewStack = yeccpars2_22_(Stack),
+ yeccgoto_appender(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+%% yeccpars2_23: see yeccpars2_9
+
+yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_|Nss] = Ss,
+ NewStack = yeccpars2_24_(Stack),
+ yeccgoto_prop(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+%% yeccpars2_25: see yeccpars2_9
+
+yeccpars2_26(S, '}', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 27, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_27(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_,_,_|Nss] = Ss,
+ NewStack = yeccpars2_27_(Stack),
+ yeccgoto_logger(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+%% yeccpars2_28: see yeccpars2_9
+
+yeccpars2_29(S, '}', Ss, Stack, T, Ts, Tzr) ->
+ yeccpars1(S, 30, Ss, Stack, T, Ts, Tzr).
+
+yeccpars2_30(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_,_,_,_|Nss] = Ss,
+ NewStack = yeccpars2_30_(Stack),
+ yeccgoto_logger(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ [_|Nss] = Ss,
+ NewStack = yeccpars2_31_(Stack),
+ yeccgoto_loggers(hd(Nss), Cat, Nss, NewStack, T, Ts, Tzr).
+
+yeccgoto_appender(9, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_12(12, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_appender(12, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_12(12, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_appender(25, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_12(12, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_appender(28, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_12(12, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccgoto_appenders(9, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_11(11, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_appenders(12=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_13(_S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_appenders(25, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_26(26, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_appenders(28, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_29(29, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccgoto_logger(0, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_2(2, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_logger(2, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_2(2, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccgoto_loggers(0, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_1(1, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_loggers(2=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_31(_S, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccgoto_prop(16, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_19(19, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_prop(20, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_19(19, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccgoto_props(16, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_18(18, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_props(20=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_21(_S, Cat, Ss, Stack, T, Ts, Tzr).
+
+yeccgoto_value(3, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_4(4, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(9, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(10, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(10, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_15(15, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(12, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(10, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(16, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(20, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_17(17, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(23=_S, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_24(_S, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(25, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(10, Cat, Ss, Stack, T, Ts, Tzr);
+yeccgoto_value(28, Cat, Ss, Stack, T, Ts, Tzr) ->
+ yeccpars2_9(10, Cat, Ss, Stack, T, Ts, Tzr).
+
+-compile({inline,{yeccpars2_2_,1}}).
+-file("log4erl_parser.yrl", 5).
+yeccpars2_2_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
+ [ __1 ]
+ end | __Stack].
+
+-compile({inline,{yeccpars2_5_,1}}).
+-file("log4erl_parser.yrl", 24).
+yeccpars2_5_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
+ unwrap ( __1 )
+ end | __Stack].
+
+-compile({inline,{yeccpars2_7_,1}}).
+-file("log4erl_parser.yrl", 23).
+yeccpars2_7_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
+ unwrap ( __1 )
+ end | __Stack].
+
+-compile({inline,{yeccpars2_8_,1}}).
+-file("log4erl_parser.yrl", 22).
+yeccpars2_8_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
+ unwrap ( __1 )
+ end | __Stack].
+
+-compile({inline,{yeccpars2_12_,1}}).
+-file("log4erl_parser.yrl", 12).
+yeccpars2_12_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
+ [ __1 ]
+ end | __Stack].
+
+-compile({inline,{yeccpars2_13_,1}}).
+-file("log4erl_parser.yrl", 13).
+yeccpars2_13_(__Stack0) ->
+ [__2,__1 | __Stack] = __Stack0,
+ [begin
+ [ __1 ] ++ __2
+ end | __Stack].
+
+-compile({inline,{yeccpars2_14_,1}}).
+-file("log4erl_parser.yrl", 9).
+yeccpars2_14_(__Stack0) ->
+ [__4,__3,__2,__1 | __Stack] = __Stack0,
+ [begin
+ { default_logger , __3 }
+ end | __Stack].
+
+-compile({inline,{yeccpars2_19_,1}}).
+-file("log4erl_parser.yrl", 17).
+yeccpars2_19_(__Stack0) ->
+ [__1 | __Stack] = __Stack0,
+ [begin
+ [ __1 ]
+ end | __Stack].
+
+-compile({inline,{yeccpars2_21_,1}}).
+-file("log4erl_parser.yrl", 18).
+yeccpars2_21_(__Stack0) ->
+ [__3,__2,__1 | __Stack] = __Stack0,
+ [begin
+ [ __1 ] ++ __3
+ end | __Stack].
+
+-compile({inline,{yeccpars2_22_,1}}).
+-file("log4erl_parser.yrl", 15).
+yeccpars2_22_(__Stack0) ->
+ [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
+ [begin
+ { appender , __1 , __2 , __4 }
+ end | __Stack].
+
+-compile({inline,{yeccpars2_24_,1}}).
+-file("log4erl_parser.yrl", 20).
+yeccpars2_24_(__Stack0) ->
+ [__3,__2,__1 | __Stack] = __Stack0,
+ [begin
+ { __1 , __3 }
+ end | __Stack].
+
+-compile({inline,{yeccpars2_27_,1}}).
+-file("log4erl_parser.yrl", 10).
+yeccpars2_27_(__Stack0) ->
+ [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
+ [begin
+ { default_logger , __4 }
+ end | __Stack].
+
+-compile({inline,{yeccpars2_30_,1}}).
+-file("log4erl_parser.yrl", 8).
+yeccpars2_30_(__Stack0) ->
+ [__5,__4,__3,__2,__1 | __Stack] = __Stack0,
+ [begin
+ { logger , __2 , __4 }
+ end | __Stack].
+
+-compile({inline,{yeccpars2_31_,1}}).
+-file("log4erl_parser.yrl", 6).
+yeccpars2_31_(__Stack0) ->
+ [__2,__1 | __Stack] = __Stack0,
+ [begin
+ [ __1 ] ++ __2
+ end | __Stack].
+
+
+-file("log4erl_parser.yrl", 33).
View
32 src/log4erl_parser.yrl
@@ -0,0 +1,32 @@
+Nonterminals loggers logger appenders appender props prop value.
+
+% 'loger' is missing 'e' not to be confused with Nonterminals
+% check 'log4erl_conf.xrl'
+Terminals '{' '}' ',' '=' 'loger' 'default' 'integer' 'val' 'atom'.
+
+Rootsymbol loggers.
+
+loggers -> logger : ['$1'].
+loggers -> logger loggers : ['$1'] ++ '$2'.
+
+logger -> loger value '{' appenders '}' : {logger, '$2', '$4'}.
+logger -> loger '{' appenders '}' : {default_logger, '$3'}.
+logger -> loger default '{' appenders '}' : {default_logger, '$4'}.
+
+appenders -> appender : ['$1'].
+appenders -> appender appenders : ['$1'] ++ '$2'.
+
+appender -> value value '{' props '}' : {appender, '$1', '$2', '$4'}.
+
+props -> prop : ['$1'].
+props -> prop ',' props : ['$1'] ++ '$3'.
+
+prop -> value '=' value : {'$1', '$3'}.
+
+value -> val : unwrap('$1').
+value -> integer : unwrap('$1').
+value -> atom : unwrap('$1').
+
+Erlang code.
+
+unwrap({_,_,V}) -> V.
View
24 src/log4erl_utils.erl
@@ -2,6 +2,7 @@
-export([gen_log_txt/1,return_2columns/1, get_current_time/1, to_log/2]).
-export([get_id/0, get_month_name/1, get_month_long_name/1]).
+-export([to_atom/1, to_list/1, to_int/1]).
% a function to make the log level text look pretty
gen_log_txt(L) when is_list(L) ->
@@ -20,7 +21,7 @@ gen_log_txt(L) when is_list(L) ->
% a function to format date/time properly (e.g. 09 instead of 9)
return_2columns(X) ->
- case length(X) of
+ case string:len(X) of
1 ->
"0" ++ X;
_ ->
@@ -120,3 +121,24 @@ get_month_long_name(Month) ->
12 ->
"December"
end.
+
+to_list(A) when is_atom(A) ->
+ atom_to_list(A);
+to_list(A) when is_integer(A) ->
+ integer_to_list(A);
+to_list(A) when is_binary(A) ->
+ binary_to_list(A);
+to_list(A) when is_list(A) ->
+ A.
+
+to_atom(A) when is_list(A) ->
+ list_to_atom(A);
+to_atom(A) when is_binary(A) ->
+ list_to_atom(binary_to_list(A));
+to_atom(A) when is_atom(A) ->
+ A.
+
+to_int(A) when is_list(A) ->
+ list_to_integer(A);
+to_int(A) when is_integer(A) ->
+ A.
View
79 src/log_formatter.erl
@@ -64,15 +64,16 @@ get_token_value(date, Log) ->
get_token_value(date2, Log) ->
D = Log#log.time,
{{Y, M, Dd},_} = D,
- [C,B,A] = lists:map(
+ [A,B,C] = lists:map(
fun(X) ->
X2 = integer_to_list(X),
- case string:len(X2) > 1 of
- false ->
- "0" ++ X2;
- _ ->
- X2
- end
+ log4erl_utils:return_2columns(X2)
+%% case string:len(X2) > 1 of
+%% false ->
+%% "0" ++ X2;
+%% _ ->
+%% X2
+%% end
end,
[Y,M,Dd]),
Res = A ++ "-" ++ B ++ "-" ++ C,
@@ -94,15 +95,16 @@ get_token_value(time2, Log) ->
[A,B,C,E] = lists:map(
fun(X) ->
X2 = integer_to_list(X),
- case string:len(X2) > 1 of
- false ->
- "0" ++ X2;
- _ ->
- X2
- end
+ log4erl_utils:return_2columns(X2)
+%% case string:len(X2) > 1 of
+%% false ->
+%% "0" ++ X2;
+%% _ ->
+%% X2
+%% end
end,
[H,M,S, Ms]),
- Res = A ++ ":" ++ B ++ ":" ++ C ++ "," ++ E,
+ Res = A ++ ":" ++ B ++ ":" ++ C ++ "." ++ E,
Res;
get_token_value(year4, Log) ->
D = Log#log.time,
@@ -149,6 +151,48 @@ get_token_value(level, Log) ->
atom_to_list(Log#log.level);
get_token_value(new_line, _Log) ->
"\n";
+% GMT TZ
+get_token_value(iso_format, Log) ->
+ [Date] = calendar:local_time_to_universal_time_dst(Log#log.time),
+ get_token_value(date2, Log) ++ "T" ++ get_token_value(time2, Log#log{time=Date}) ++ "Z";
+% With TZ
+get_token_value(iso_format2, Log) ->
+ D = Log#log.time,
+ [UD] = calendar:local_time_to_universal_time_dst(D),
+ Ds = calendar:datetime_to_gregorian_seconds(D),
+ UDs = calendar:datetime_to_gregorian_seconds(UD),
+ TZ = case Ds-UDs > 0 of
+ true ->
+ {_,{A,B,_}} = calendar:gregorian_seconds_to_datetime(Ds-UDs),
+ A2 = log4erl_utils:return_2columns(integer_to_list(A)),
+ B2 = log4erl_utils:return_2columns(integer_to_list(B)),
+ "+" ++ A2 ++ ":" ++ B2;
+ _ ->
+ {_,{C,D,_}} = calendar:gregorian_seconds_to_datetime(UDs-Ds),
+ C2 = log4erl_utils:return_2columns(integer_to_list(C)),
+ D2 = log4erl_utils:return_2columns(integer_to_list(D)),
+ "-" ++ C2 ++ ":" ++ D2
+ end,
+ get_token_value(date2, Log) ++ "T" ++ get_token_value(time2, Log) ++ TZ;
+% TZ only
+get_token_value(time_zone, Log) ->
+ D = Log#log.time,
+ [UD] = calendar:local_time_to_universal_time_dst(D),
+ Ds = calendar:datetime_to_gregorian_seconds(D),
+ UDs = calendar:datetime_to_gregorian_seconds(UD),
+ TZ = case Ds-UDs > 0 of
+ true ->
+ {_,{A,B,_}} = calendar:gregorian_seconds_to_datetime(Ds-UDs),
+ A2 = log4erl_utils:return_2columns(integer_to_list(A)),
+ B2 = log4erl_utils:return_2columns(integer_to_list(B)),
+ "+" ++ A2 ++ ":" ++ B2;
+ _ ->
+ {_,{C,D,_}} = calendar:gregorian_seconds_to_datetime(UDs-Ds),
+ C2 = log4erl_utils:return_2columns(integer_to_list(C)),
+ D2 = log4erl_utils:return_2columns(integer_to_list(D)),
+ "-" ++ C2 ++ ":" ++ D2
+ end,
+ TZ;
get_token_value(A, _Log) ->
A.
@@ -212,5 +256,12 @@ parse_char($n) ->
new_line;
parse_char($i) ->
millis;
+parse_char($I) ->
+ iso_format;