Skip to content

Commit

Permalink
[daap/smartpl] Add new bison/flex parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
ejurgensen committed Jan 29, 2022
1 parent 3a93dc5 commit efe5df5
Show file tree
Hide file tree
Showing 14 changed files with 1,560 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ missing
stamp-h1
autotools-stamp
build-stamp
ylwrap
owntone.spec
owntone.conf
owntone.service
Expand Down
9 changes: 9 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ If you modify any .gperf files, you will need to install it.]])],
[AC_MSG_ERROR([[GNU gperf required, please install it.]])])
])

AX_PROG_FLEX([AC_DEFINE([LEX], [flex], [flex found])],
[AS_IF([test ! -f "$srcdir/src/smartpl_lexer.c"],
[AC_MSG_ERROR([flex required, please install it])])
])
AX_PROG_BISON([AC_DEFINE([YACC], [bison], [GNU bison found])],
[AS_IF([test ! -f "$srcdir/src/smartpl_parser.c"],
[AC_MSG_ERROR([GNU bison required, please install it])])
])

dnl Enable all warnings by default.
AM_CPPFLAGS="-Wall"
AC_SUBST([AM_CPPFLAGS])
Expand Down
65 changes: 65 additions & 0 deletions m4/ax_prog_bison.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_prog_bison.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_BISON(ACTION-IF-TRUE,ACTION-IF-FALSE)
#
# DESCRIPTION
#
# Check whether bison is the parser generator. Run ACTION-IF-TRUE if
# successful, ACTION-IF-FALSE otherwise
#
# LICENSE
#
# Copyright (c) 2009 Francesco Salvestrini <salvestrini@users.sourceforge.net>
# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.

#serial 10

AC_DEFUN([AX_PROG_BISON], [
AC_REQUIRE([AC_PROG_YACC])
AC_REQUIRE([AC_PROG_EGREP])
AC_CACHE_CHECK([if bison is the parser generator],[ax_cv_prog_bison],[
AS_IF([$YACC --version 2>/dev/null | $EGREP -q '^bison '],
[ax_cv_prog_bison=yes], [ax_cv_prog_bison=no])
])
AS_IF([test "$ax_cv_prog_bison" = "yes"], [
dnl replace the yacc-compatible compiler with the real bison, as
dnl otherwise autoconf limits us to the POSIX yacc.
dnl We also change the generated filename to the old one, so that
dnl automake's ylwrap can deal with it.
YACC="${YACC% -y} -o y.tab.c"
] m4_ifnblank([$1], [[$1]]),
m4_ifnblank([$2], [[$2]])
)
])

60 changes: 60 additions & 0 deletions m4/ax_prog_flex.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_prog_flex.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_FLEX(ACTION-IF-TRUE,ACTION-IF-FALSE)
#
# DESCRIPTION
#
# Check whether flex is the scanner generator. Run ACTION-IF-TRUE if
# successful, ACTION-IF-FALSE otherwise
#
# LICENSE
#
# Copyright (c) 2009 Francesco Salvestrini <salvestrini@users.sourceforge.net>
# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.

#serial 13

AC_DEFUN([AX_PROG_FLEX], [
AC_REQUIRE([AM_PROG_LEX])
AC_REQUIRE([AC_PROG_EGREP])
AC_CACHE_CHECK([if flex is the lexer generator],[ax_cv_prog_flex],[
AS_IF([$LEX --version 2>/dev/null | $EGREP -qw '^g?flex'],
[ax_cv_prog_flex=yes], [ax_cv_prog_flex=no])
])
AS_IF([test "$ax_cv_prog_flex" = "yes"],
m4_ifnblank([$1], [[$1]]),
m4_ifnblank([$2], [[$2]])
)
])

3 changes: 3 additions & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
owntone

*_lexer.[ch]
*_parser.[ch]

daap_query_hash.h
rsp_query_hash.h
dacp_prop_hash.h
Expand Down
34 changes: 30 additions & 4 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ GPERF_FILES = \

GPERF_SRC = $(GPERF_FILES:.gperf=_hash.h)

LEXER_SRC = daap_lexer.l smartpl_lexer.l
PARSER_SRC = daap_parser.y smartpl_parser.y

# This flag is given to flex and tells it to produce headers. automake's ylwrap
# doesn't seem to rename the header like it does with the .c flex output, so
# here we give it the final name. The "$(@:.c=.h)" uses substitution reference
# and means 'change .c to .h in $@' (the target name, e.g. calc_lexer.c).
AM_LFLAGS = --header-file=$(@:.c=.h)

# This flag is given to Bison and tells it to produce headers. Note that
# automake recognizes this flag too, and has special logic around it, so don't
# change it to compound arguments (so for instance no "-dv"). I'm also not sure
# --defines will work instead of -d.
AM_YFLAGS = -d

AM_CPPFLAGS += \
$(OWNTONE_CPPFLAGS) \
$(OWNTONE_OPTS_CPPFLAGS) \
Expand Down Expand Up @@ -130,16 +145,27 @@ owntone_SOURCES = main.c \
mxml-compat.h \
outputs/plist_wrap.h \
$(LIBWEBSOCKETS_SRC) \
$(GPERF_SRC)
$(GPERF_SRC) \
$(LEXER_SRC) $(PARSER_SRC)

# built by maintainers, and distributed. Clean with maintainer-clean
# This should ensure the headers are built first. automake knows how to make
# parser headers, but doesn't know how to do that for flex. So instead we set
# the C files as target, as the AM_LFLAGS will make sure headers are produced.
BUILT_SOURCES = \
$(GPERF_SRC)
$(GPERF_SRC) \
$(LEXER_SRC:.l=.c) $(PARSER_SRC:.y=.h)

# automake doesn't know how to make lexer headers, nor does it automatically
# include them, so need to specify them as EXTRA_DIST.
EXTRA_DIST = \
$(GPERF_FILES)
$(GPERF_FILES) \
$(LEXER_SRC:.l=.h)

# gperf construction rules
%_hash.h: %.gperf
$(AM_V_GEN)$(GPERF) --output-file=$@ $<

# Anything built by make should be cleaned by make clean, but when it comes to
# flex/bison automake's support leaves something to be desired
clean-local:
rm -f $(LEXER_SRC:.l=.[ch]) $(PARSER_SRC:.y=.[ch])
74 changes: 74 additions & 0 deletions src/daap_lexer.l
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (C) 2021-2022 Espen Jürgensen <espenjurgensen@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

/* =========================== BOILERPLATE SECTION ===========================*/

/* This is to avoid compiler warnings about unused functions. More options are
noyyalloc noyyrealloc noyyfree. */
%option noyywrap nounput noinput

/* Thread safe scanner */
%option reentrant

/* To avoid symbol name conflicts with multiple lexers */
%option prefix="daap_"

/* Automake's ylwrap expexts the output to have this name */
%option outfile="lex.yy.c"

/* Makes a Bison-compatible yylex */
%option bison-bridge

%{
#include <stdio.h>
#include "daap_parser.h"

/* Unknown why this is required despite using prefix */
#define YYSTYPE DAAP_STYPE

%}

/* ========================= NON-BOILERPLATE SECTION =========================*/

re_quote '
re_key [[:alnum:]\.\-]+
re_value (\\.|[^'])+
re_operator (!?[:@])

%x IN_CRITERIA IN_CRITERIA_VALUE

%%

{re_quote} { BEGIN IN_CRITERIA; return DAAP_T_QUOTE; }

<IN_CRITERIA>{re_key}/{re_operator} { yylval->str = strdup(yytext); return DAAP_T_KEY; }
<IN_CRITERIA>{re_operator} { BEGIN IN_CRITERIA_VALUE; return (*yytext == '!' ? DAAP_T_NOT : DAAP_T_EQUAL); }
<IN_CRITERIA>. { return *yytext; }

<IN_CRITERIA_VALUE>\*{re_value}\*/{re_quote} { yylval->str = strdup(yytext); return DAAP_T_WILDCARD; }
<IN_CRITERIA_VALUE>{re_value}/{re_quote} { yylval->str = strdup(yytext); return DAAP_T_VALUE; }
<IN_CRITERIA_VALUE>{re_quote} { BEGIN INITIAL; return DAAP_T_QUOTE; }
<IN_CRITERIA_VALUE>. { return *yytext; }

"+"|" " { return DAAP_T_AND; }
"," { return DAAP_T_OR; }
"\r"?"\n" { return DAAP_T_NEWLINE; }
. { return *yytext; }

%%

Loading

0 comments on commit efe5df5

Please sign in to comment.