message-view: bgo #727634 - Cannot copy build output
[anjuta.git] / plugins / am-project / ac-scanner.l
blob7a9e3f7df902185281af1a3b5aefaeb283eb430a
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"
24 #include "amp-source.h"
26 #include "libanjuta/anjuta-debug.h"
27 #include "libanjuta/anjuta-token-stream.h"
29 #include <stdlib.h>
30 #include <string.h>
32 #define YY_INPUT(buffer, result, max_size) result = anjuta_token_stream_read (yyextra->stream, buffer, max_size)
34 #define YY_EXTRA_TYPE  AmpAcScanner*
36 #define YY_DECL static int ac_yylex (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner)
38 //#define YY_USER_INIT {yy_flex_debug = 1;}
40 static gint amp_ac_scanner_parse_end (AmpAcScanner *scanner);
42 #define RETURN(tok) *yylval = anjuta_token_stream_tokenize (yyextra->stream, tok, yyleng); \
43                     return tok
45 struct _AmpAcScanner
47     yyscan_t scanner;
49     AnjutaTokenStream *stream;
51     AmpProject *project;
53     AnjutaToken *parsed;
55         gboolean eof;           /* TRUE to emit EOF at the end */
57         GHashTable *variables;
63 %option reentrant stack noyywrap yylineno
65 /* Remove some warnings */
66 %option nounput noinput noyy_pop_state noyy_top_state
68 %option prefix="amp_ac_yy"
70 /* Necessary because autotools wrapper always looks for a file named "lex.yy.c",
71  * not "lex.amp_ac_yy.c"
72 %option outfile="lex.yy.c"*/
74 %option bison-bridge bison-locations
76 %option never-interactive
78 %option batch
80 %option debug
82 WS          [ \t\r\v]+
83 NL          \n
84 WSNL        [ \t\v\r\n]+
85 COMMENT     #
86 OPENM4QUOTE   \[
87 CLOSEM4QUOTE  \]
88 SINGLEQUOTE   \'
89 DOUBLEQUOTE             \"
90 OPENPARG   \(
91 CLOSEPARG  \)
92 COMMA       ,
93 EQUAL       =
94 LOWER       <
95 GREATER     >
96 NAME        [A-Za-z_][A-Za-z0-9_]*
97 VARIABLE    $[A-Za-z_0-9]+
98 OTHER       [^ \t\r\v\n#\[\]\"\'\\(),=><$_A-Za-z_]+
100 %x SPACE_LIST
104 {WS}                    { RETURN (SPACE); }
106 \\\n                    { RETURN (SPACE); }
108 {NL}                    { RETURN (END_OF_LINE); }
110 {COMMENT}               { RETURN (HASH); }
112 {OPENM4QUOTE}             { RETURN (LEFT_BRACE); }
114 {CLOSEM4QUOTE}            { RETURN (RIGHT_BRACE); }
116 {OPENPARG}              { RETURN (LEFT_PAREN); }
118 {CLOSEPARG}             { RETURN (RIGHT_PAREN); }
120 {SINGLEQUOTE}                   { RETURN (SINGLE_QUOTE); }
122 {DOUBLEQUOTE}                   { RETURN (DOUBLE_QUOTE); }
124 {COMMA}                 { RETURN (COMMA); }
126 {EQUAL}                 { RETURN (EQUAL); }
128 {LOWER}                 { RETURN (LOWER); }
130 {GREATER}                 { RETURN (GREATER); }
132 dnl                     { RETURN (DNL); }
134 m4_include\(                    { RETURN (M4_INCLUDE); }
136 AC_ARG_ENABLE\(                 { RETURN (AC_ARG_ENABLE);}
138 AC_C_CONST                              { RETURN (AC_C_CONST);}
140 AC_CHECK_FUNCS\(                { RETURN (AC_CHECK_FUNCS);}
142 AC_CHECK_HEADERS\(              { RETURN (AC_CHECK_HEADERS);}
144 AC_CHECK_LIB\(                  { RETURN (AC_CHECK_LIB);}
146 AC_CHECK_PROG\(                 { RETURN (AC_CHECK_PROG);}
148 AC_CONFIG_FILES\(       { RETURN (AC_CONFIG_FILES); }
150 AC_CONFIG_HEADERS\(             { RETURN (AC_CONFIG_HEADERS); }
152 AC_CONFIG_MACRO_DIR\(   { RETURN (AC_CONFIG_MACRO_DIR); }
154 AC_CONFIG_SRCDIR\(              { RETURN (AC_CONFIG_SRCDIR); }
156 AC_EGREP_HEADER\(               { RETURN (AC_EGREP_HEADER); }
158 AC_EXEEXT                               { RETURN (AC_EXEEXT); }
160 AC_HEADER_STDC                  { RETURN (AC_HEADER_STDC); }
162 AC_INIT\(               { RETURN (AC_INIT); }
164 AC_OBJEXT                               { RETURN (AC_OBJEXT); }
166 AC_OUTPUT\(             { RETURN (OBSOLETE_AC_OUTPUT); }
168 AC_OUTPUT               { RETURN (AC_OUTPUT); }
170 AC_PREREQ\(                             { RETURN (AC_PREREQ); }
172 AC_PROG_CC                              { RETURN (AC_PROG_CC);}
174 AC_PROG_CPP                             { RETURN (AC_PROG_CPP);}
176 AC_PROG_CXX                             { RETURN (AC_PROG_CXX);}
178 IT_PROG_INTLTOOL\(              { RETURN (IT_PROG_INTLTOOL);}
180 AC_PROG_LEX                             { RETURN (AC_PROG_LEX);}
182 AC_PROG_LIBTOOL                 { RETURN (AC_PROG_LIBTOOL);}
184 AC_PROG_RANLIB                  { RETURN (AC_PROG_RANLIB);}
186 AC_PROG_YACC                    { RETURN (AC_PROG_YACC);}
188 AC_SUBST\(                              { RETURN (AC_SUBST);}
190 AC_TYPE_SIZE_T                  { RETURN (AC_TYPE_SIZE_T);}
192 AC_TYPE_OFF_T                   { RETURN (AC_TYPE_OFF_T);}
194 AM_INIT_AUTOMAKE\(              { RETURN (AM_INIT_AUTOMAKE);}
196 AM_GLIB_GNU_GETTEXT\(   { RETURN (AM_GLIB_GNU_GETTEXT);}
198 AM_MAINTAINER_MODE              { RETURN (AM_MAINTAINER_MODE);}
200 AM_PROG_LIBTOOL                 { RETURN (AM_PROG_LIBTOOL);}
202 LT_INIT\(                               { RETURN (LT_INIT);}
204 LT_INIT                                 { RETURN (DEFAULT_LT_INIT);}
206 LT_PREREQ\(                             { RETURN (LT_PREREQ);}
208 PKG_CHECK_MODULES\(     { RETURN (PKG_CHECK_MODULES); }
210 PKG_PROG_PKG_CONFIG\(   { RETURN (PKG_PROG_PKG_CONFIG);}
212 {NAME}                  { RETURN (NAME); }
214 {VARIABLE}              { RETURN (VARIABLE); }
216 {OTHER}|\$|\\           { RETURN (WORD); }
218 <<EOF>>                     { if (amp_ac_scanner_parse_end (yyextra) == YY_NULL) return YY_NULL; }
220 <SPACE_LIST>{
222 {WSNL}                    { RETURN (SPACE); }
224 \\\n                    { RETURN (SPACE); }
226 =|<|>|<=|>=             { RETURN (OPERATOR); }
228 {NAME}                    { RETURN (WORD); }
230 .                           {RETURN (WORD);}
235 /* Private functions
236  *---------------------------------------------------------------------------*/
239 static gint
240 amp_ac_scanner_parse_end (AmpAcScanner *scanner)
243         if (scanner->stream == NULL)
244         {
245                 yyterminate();
246         }
247         else
248         {
249                 if (scanner->eof)
250                 {
251                         scanner->eof = FALSE;
252                         return END_OF_FILE;
253                 }
255                 yypop_buffer_state(scanner->scanner);
256         scanner->stream = anjuta_token_stream_pop (scanner->stream);
258                 if (scanner->stream == NULL)
259                 {
260                         yyterminate();
261                 }
262                 else
263                 {
264                         scanner->eof = anjuta_token_stream_get_current_file (scanner->stream) != NULL;
266                         /* Continue parsing the parent file */
267                         return 1;
268                 }
269         }
272 /* Parser functions
273  *---------------------------------------------------------------------------*/
275 void
276 amp_ac_yyerror (YYLTYPE *loc, AmpAcScanner *scanner, char const *s)
278     AnjutaTokenFileLocation location;
280     if (amp_project_get_token_location (scanner->project, &location, *loc))
281     {
282         g_message ("%s:%d.%d %s\n", location.filename, location.line, location.column, s);
283         g_free (location.filename);
284     }
285     else
286     {
287         g_message ("%s \n", s);
288     }
291 void
292 amp_ac_scanner_load_module (AmpAcScanner *scanner, AnjutaToken *module)
294     amp_project_load_module (scanner->project, module);
297 void
298 amp_ac_scanner_load_config (AmpAcScanner *scanner, AnjutaToken *list)
300     amp_project_load_config (scanner->project, list);
303 void
304 amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaToken *macro, AnjutaToken *list)
306     amp_project_load_properties (scanner->project, macro, list);
309 void
310 amp_ac_scanner_include (AmpAcScanner *scanner, AnjutaToken *list)
312         GFile *file;
313         AnjutaTokenFile *include;
314         AnjutaToken *token;
315         AnjutaToken *name;
316         gchar *filename;
317         AnjutaProjectNode *source;
319         name = anjuta_token_first_item (list);          /* m4_include macro */
320         name = anjuta_token_next_item (name);           /* arguments list */
321         name = anjuta_token_first_item (name);          /* filename */
322         filename = g_strstrip (anjuta_token_evaluate (name));
323         //g_message ("read include =%s=", filename);
324         file = g_file_resolve_relative_path (anjuta_token_stream_get_current_directory (scanner->stream), filename);
325         g_free (filename);
326         source = amp_source_node_new (file, ANJUTA_PROJECT_PROJECT | ANJUTA_PROJECT_FRAME | ANJUTA_PROJECT_READ_ONLY);
327         anjuta_project_node_append (ANJUTA_PROJECT_NODE (scanner->project), source);
328         include = anjuta_token_file_new (file);
329         token = anjuta_token_file_load (include, NULL);
330         amp_ac_scanner_parse_token (scanner, list, token, 0, file, NULL);
331         g_object_unref (file);
334 void
335 amp_ac_scanner_update_variable (AmpAcScanner *scanner, AnjutaToken *variable)
337         AnjutaToken *arg;
338         char *name = NULL;
339         AnjutaToken *value = NULL;
341         arg = anjuta_token_first_word (variable);
342         name = g_strstrip (anjuta_token_evaluate (arg));
343         value = anjuta_token_nth_word (variable, 2);
345         g_hash_table_insert (scanner->variables, name, value);
348 void
349 amp_ac_scanner_subst_variable (AmpAcScanner *scanner, AnjutaToken *list)
351         AnjutaToken *arg;
352         char *name = NULL;
353         AnjutaToken *value = NULL;
355         arg = anjuta_token_first_word (list);
356         name = g_strstrip (anjuta_token_evaluate (arg));
357         value = anjuta_token_nth_word (list, 2);
358         if (value == NULL)
359         {
360                 value = g_hash_table_lookup (scanner->variables, name);
361         }
363         amp_project_add_subst_variable (scanner->project, name, value);
367 /* Public functions
368  *---------------------------------------------------------------------------*/
370 AnjutaToken *
371 amp_ac_scanner_parse_token (AmpAcScanner *scanner, AnjutaToken *root, AnjutaToken *content, gint start, GFile *filename, GError **error)
373     AnjutaToken *first;
374     AnjutaTokenStream *stream;
376     stream = anjuta_token_stream_push (scanner->stream, root, content, filename);
377     first = anjuta_token_stream_get_root (stream);
379         scanner->eof = filename != NULL;
381     if (scanner->stream != NULL)
382     {
383         /* Parse an included file or a expanded variable */
385         scanner->stream = stream;
386         yypush_buffer_state(yy_create_buffer(NULL, YY_BUF_SIZE, scanner->scanner), scanner->scanner);
387     }
388     else
389     {
390         amp_ac_yypstate *ps;
391         gint status;
392         YYSTYPE yylval_param;
393         YYLTYPE yylloc_param;
395         scanner->stream = stream;
396         ps = amp_ac_yypstate_new ();
398         yylval_param = NULL;
399         yylloc_param = NULL;
400         switch (start)
401         {
402         case AC_SPACE_LIST_STATE:
403             amp_ac_yypush_parse (ps, START_SPACE_LIST, &yylval_param, &yylloc_param, scanner);
404             yy_push_state (SPACE_LIST, scanner->scanner);
405             break;
406         default:
407             break;
408         }
410         do
411         {
412             gint yychar = ac_yylex (&yylval_param, &yylloc_param, scanner->scanner);
414             yylloc_param = yylval_param;
415             status = amp_ac_yypush_parse (ps, yychar, &yylval_param, &yylloc_param, scanner);
417         } while (status == YYPUSH_MORE);
418         amp_ac_yypstate_delete (ps);
419     }
421     return first;
424 /* Constructor & Destructor
425  *---------------------------------------------------------------------------*/
427 AmpAcScanner *
428 amp_ac_scanner_new (AmpProject *project)
430         AmpAcScanner *scanner;
432         scanner = g_new0 (AmpAcScanner, 1);
434     yylex_init(&scanner->scanner);
435     yyset_extra (scanner, scanner->scanner);
437     scanner->project = project;
439         scanner->variables = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
441         return scanner;
444 void
445 amp_ac_scanner_free (AmpAcScanner *scanner)
447         g_return_if_fail (scanner != NULL);
449         g_hash_table_remove_all (scanner->variables);
450     yylex_destroy(scanner->scanner);
452         g_free (scanner);