search: Use G_REGEX_MULTILINE for find in files.
[anjuta.git] / plugins / am-project / ac-scanner.l
blob9347f25ebd421a4dc25f8142991af51f0789adb3
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * ac-scanner.l
4  * Copyright (C) Sébastien Granjoux 2009 <seb.sfo@free.fr>
5  *
6  * main.c is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * main.c is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
22 #include "ac-scanner.h"
23 #include "ac-parser.h"
25 #include "libanjuta/anjuta-debug.h"
26 #include "libanjuta/anjuta-token-stream.h"
28 #include <stdlib.h>
29 #include <string.h>
31 #define YY_INPUT(buffer, result, max_size) result = anjuta_token_stream_read (yyextra->stream, buffer, max_size)
33 #define YY_EXTRA_TYPE  AmpAcScanner*
35 #define YY_DECL static int ac_yylex (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner)
37 //#define YY_USER_INIT {yy_flex_debug = 1;}
39 static gint amp_ac_scanner_parse_end (AmpAcScanner *scanner);
41 #define RETURN(tok) *yylval = anjuta_token_stream_tokenize (yyextra->stream, tok, yyleng); \
42                     return tok
44 struct _AmpAcScanner
46     yyscan_t scanner;
48     AnjutaTokenStream *stream;
50     AmpProject *project;
52     AnjutaToken *parsed;
54         gboolean eof;           /* TRUE to emit EOF at the end */
56         GHashTable *variables;
62 %option reentrant stack noyywrap yylineno
64 /* Remove some warnings */
65 %option nounput noinput noyy_pop_state noyy_top_state
67 %option prefix="amp_ac_yy"
69 /* Necessary because autotools wrapper always looks for a file named "lex.yy.c",
70  * not "lex.amp_ac_yy.c"
71 %option outfile="lex.yy.c"*/
73 %option bison-bridge bison-locations
75 %option never-interactive
77 %option batch
79 %option debug
81 WS          [ \t\r\v]+
82 NL          \n
83 WSNL        [ \t\v\r\n]+
84 COMMENT     #
85 OPENM4QUOTE   \[
86 CLOSEM4QUOTE  \]
87 SINGLEQUOTE   \'
88 DOUBLEQUOTE             \"
89 OPENPARG   \(
90 CLOSEPARG  \)
91 COMMA       ,
92 EQUAL       =
93 LOWER       <
94 GREATER     >
95 NAME        [A-Za-z_][A-Za-z0-9_]*
96 VARIABLE    $[A-Za-z_0-9]+
97 OTHER       [^ \t\r\v\n#\[\]\"\'\\(),=><$_A-Za-z_]+
99 %x SPACE_LIST
103 {WS}                    { RETURN (SPACE); }
105 \\\n                    { RETURN (SPACE); }
107 {NL}                    { RETURN (END_OF_LINE); }
109 {COMMENT}               { RETURN (HASH); }
111 {OPENM4QUOTE}             { RETURN (LEFT_BRACE); }
113 {CLOSEM4QUOTE}            { RETURN (RIGHT_BRACE); }
115 {OPENPARG}              { RETURN (LEFT_PAREN); }
117 {CLOSEPARG}             { RETURN (RIGHT_PAREN); }
119 {SINGLEQUOTE}                   { RETURN (SINGLE_QUOTE); }
121 {DOUBLEQUOTE}                   { RETURN (DOUBLE_QUOTE); }
123 {COMMA}                 { RETURN (COMMA); }
125 {EQUAL}                 { RETURN (EQUAL); }
127 {LOWER}                 { RETURN (LOWER); }
129 {GREATER}                 { RETURN (GREATER); }
131 dnl                     { RETURN (DNL); }
133 m4_include\(                    { RETURN (M4_INCLUDE); }
135 AC_ARG_ENABLE\(                 { RETURN (AC_ARG_ENABLE);}
137 AC_C_CONST                              { RETURN (AC_C_CONST);}
139 AC_CHECK_FUNCS\(                { RETURN (AC_CHECK_FUNCS);}
141 AC_CHECK_HEADERS\(              { RETURN (AC_CHECK_HEADERS);}
143 AC_CHECK_LIB\(                  { RETURN (AC_CHECK_LIB);}
145 AC_CHECK_PROG\(                 { RETURN (AC_CHECK_PROG);}
147 AC_CONFIG_FILES\(       { RETURN (AC_CONFIG_FILES); }
149 AC_CONFIG_HEADERS\(             { RETURN (AC_CONFIG_HEADERS); }
151 AC_CONFIG_MACRO_DIR\(   { RETURN (AC_CONFIG_MACRO_DIR); }
153 AC_CONFIG_SRCDIR\(              { RETURN (AC_CONFIG_SRCDIR); }
155 AC_EGREP_HEADER\(               { RETURN (AC_EGREP_HEADER); }
157 AC_EXEEXT                               { RETURN (AC_EXEEXT); }
159 AC_HEADER_STDC                  { RETURN (AC_HEADER_STDC); }
161 AC_INIT\(               { RETURN (AC_INIT); }
163 AC_OBJEXT                               { RETURN (AC_OBJEXT); }
165 AC_OUTPUT\(             { RETURN (OBSOLETE_AC_OUTPUT); }
167 AC_OUTPUT               { RETURN (AC_OUTPUT); }
169 AC_PREREQ\(                             { RETURN (AC_PREREQ); }
171 AC_PROG_CC                              { RETURN (AC_PROG_CC);}
173 AC_PROG_CPP                             { RETURN (AC_PROG_CPP);}
175 AC_PROG_CXX                             { RETURN (AC_PROG_CXX);}
177 IT_PROG_INTLTOOL\(              { RETURN (IT_PROG_INTLTOOL);}
179 AC_PROG_LEX                             { RETURN (AC_PROG_LEX);}
181 AC_PROG_LIBTOOL                 { RETURN (AC_PROG_LIBTOOL);}
183 AC_PROG_RANLIB                  { RETURN (AC_PROG_RANLIB);}
185 AC_PROG_YACC                    { RETURN (AC_PROG_YACC);}
187 AC_SUBST\(                              { RETURN (AC_SUBST);}
189 AC_TYPE_SIZE_T                  { RETURN (AC_TYPE_SIZE_T);}
191 AC_TYPE_OFF_T                   { RETURN (AC_TYPE_OFF_T);}
193 AM_INIT_AUTOMAKE\(              { RETURN (AM_INIT_AUTOMAKE);}
195 AM_GLIB_GNU_GETTEXT\(   { RETURN (AM_GLIB_GNU_GETTEXT);}
197 AM_MAINTAINER_MODE              { RETURN (AM_MAINTAINER_MODE);}
199 AM_PROG_LIBTOOL                 { RETURN (AM_PROG_LIBTOOL);}
201 LT_INIT\(                               { RETURN (LT_INIT);}
203 LT_INIT                                 { RETURN (DEFAULT_LT_INIT);}
205 LT_PREREQ\(                             { RETURN (LT_PREREQ);}
207 PKG_CHECK_MODULES\(     { RETURN (PKG_CHECK_MODULES); }
209 PKG_PROG_PKG_CONFIG\(   { RETURN (PKG_PROG_PKG_CONFIG);}
211 {NAME}                  { RETURN (NAME); }
213 {VARIABLE}              { RETURN (VARIABLE); }
215 {OTHER}|\$|\\           { RETURN (WORD); }
217 <<EOF>>                     { if (amp_ac_scanner_parse_end (yyextra) == YY_NULL) return YY_NULL; }
219 <SPACE_LIST>{
221 {WSNL}                    { RETURN (SPACE); }
223 \\\n                    { RETURN (SPACE); }
225 =|<|>|<=|>=             { RETURN (OPERATOR); }
227 {NAME}                    { RETURN (WORD); }
229 .                           {RETURN (WORD);}
234 /* Private functions
235  *---------------------------------------------------------------------------*/
238 static gint
239 amp_ac_scanner_parse_end (AmpAcScanner *scanner)
242         if (scanner->stream == NULL)
243         {
244                 yyterminate();
245         }
246         else
247         {
248                 if (scanner->eof)
249                 {
250                         scanner->eof = FALSE;
251                         return END_OF_FILE;
252                 }
254                 yypop_buffer_state(scanner->scanner);
255         scanner->stream = anjuta_token_stream_pop (scanner->stream);
257                 if (scanner->stream == NULL)
258                 {
259                         yyterminate();
260                 }
261                 else
262                 {
263                         scanner->eof = anjuta_token_stream_get_current_file (scanner->stream) != NULL;
265                         /* Continue parsing the parent file */
266                         return 1;
267                 }
268         }
271 /* Parser functions
272  *---------------------------------------------------------------------------*/
274 void
275 amp_ac_yyerror (YYLTYPE *loc, AmpAcScanner *scanner, char const *s)
277     AnjutaTokenFileLocation location;
279     if (amp_project_get_token_location (scanner->project, &location, *loc))
280     {
281         g_message ("%s:%d.%d %s\n", location.filename, location.line, location.column, s);
282         g_free (location.filename);
283     }
284     else
285     {
286         g_message ("%s \n", s);
287     }
290 void
291 amp_ac_scanner_load_module (AmpAcScanner *scanner, AnjutaToken *module)
293     amp_project_load_module (scanner->project, module);
296 void
297 amp_ac_scanner_load_config (AmpAcScanner *scanner, AnjutaToken *list)
299     amp_project_load_config (scanner->project, list);
302 void
303 amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaToken *macro, AnjutaToken *list)
305     amp_project_load_properties (scanner->project, macro, list);
308 void
309 amp_ac_scanner_include (AmpAcScanner *scanner, AnjutaToken *list)
311         GFile *file;
312         AnjutaTokenFile *include;
313         AnjutaToken *token;
314         AnjutaToken *name;
315         gchar *filename;
317         name = anjuta_token_first_item (list);          /* m4_include macro */
318         name = anjuta_token_next_item (name);           /* arguments list */
319         name = anjuta_token_first_item (name);          /* filename */
320         filename = g_strstrip (anjuta_token_evaluate (name));
321         //g_message ("read include =%s=", filename);
322         file = g_file_resolve_relative_path (anjuta_token_stream_get_current_directory (scanner->stream), filename);
323         g_free (filename);
324         include = anjuta_token_file_new (file);
325         token = anjuta_token_file_load (include, NULL);
326         amp_ac_scanner_parse_token (scanner, list, token, 0, file, NULL);
327         g_object_unref (file);
330 void
331 amp_ac_scanner_update_variable (AmpAcScanner *scanner, AnjutaToken *variable)
333         AnjutaToken *arg;
334         char *name = NULL;
335         AnjutaToken *value = NULL;
337         arg = anjuta_token_first_word (variable);
338         name = g_strstrip (anjuta_token_evaluate (arg));
339         value = anjuta_token_nth_word (variable, 2);
341         g_hash_table_insert (scanner->variables, name, value);
344 void
345 amp_ac_scanner_subst_variable (AmpAcScanner *scanner, AnjutaToken *list)
347         AnjutaToken *arg;
348         char *name = NULL;
349         AnjutaToken *value = NULL;
351         arg = anjuta_token_first_word (list);
352         name = g_strstrip (anjuta_token_evaluate (arg));
353         value = anjuta_token_nth_word (list, 2);
354         if (value == NULL)
355         {
356                 value = g_hash_table_lookup (scanner->variables, name);
357         }
359         amp_project_add_subst_variable (scanner->project, name, value);
363 /* Public functions
364  *---------------------------------------------------------------------------*/
366 AnjutaToken *
367 amp_ac_scanner_parse_token (AmpAcScanner *scanner, AnjutaToken *root, AnjutaToken *content, gint start, GFile *filename, GError **error)
369     AnjutaToken *first;
370     AnjutaTokenStream *stream;
372     stream = anjuta_token_stream_push (scanner->stream, root, content, filename);
373     first = anjuta_token_stream_get_root (stream);
375         scanner->eof = filename != NULL;
377     if (scanner->stream != NULL)
378     {
379         /* Parse an included file or a expanded variable */
381         scanner->stream = stream;
382         yypush_buffer_state(yy_create_buffer(NULL, YY_BUF_SIZE, scanner->scanner), scanner->scanner);
383     }
384     else
385     {
386         amp_ac_yypstate *ps;
387         gint status;
388         YYSTYPE yylval_param;
389         YYLTYPE yylloc_param;
391         scanner->stream = stream;
392         ps = amp_ac_yypstate_new ();
394         yylval_param = NULL;
395         yylloc_param = NULL;
396         switch (start)
397         {
398         case AC_SPACE_LIST_STATE:
399             amp_ac_yypush_parse (ps, START_SPACE_LIST, &yylval_param, &yylloc_param, scanner);
400             yy_push_state (SPACE_LIST, scanner->scanner);
401             break;
402         default:
403             break;
404         }
406         do
407         {
408             gint yychar = ac_yylex (&yylval_param, &yylloc_param, scanner->scanner);
410             yylloc_param = yylval_param;
411             status = amp_ac_yypush_parse (ps, yychar, &yylval_param, &yylloc_param, scanner);
413         } while (status == YYPUSH_MORE);
414         amp_ac_yypstate_delete (ps);
415     }
417     return first;
420 /* Constructor & Destructor
421  *---------------------------------------------------------------------------*/
423 AmpAcScanner *
424 amp_ac_scanner_new (AmpProject *project)
426         AmpAcScanner *scanner;
428         scanner = g_new0 (AmpAcScanner, 1);
430     yylex_init(&scanner->scanner);
431     yyset_extra (scanner, scanner->scanner);
433     scanner->project = project;
435         scanner->variables = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
437         return scanner;
440 void
441 amp_ac_scanner_free (AmpAcScanner *scanner)
443         g_return_if_fail (scanner != NULL);
445         g_hash_table_remove_all (scanner->variables);
446     yylex_destroy(scanner->scanner);
448         g_free (scanner);