1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Sébastien Granjoux 2009 <seb.sfo@free.fr>
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.
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.
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/>.
22 #include "ac-scanner.h"
23 #include "ac-parser.h"
25 #include "libanjuta/anjuta-debug.h"
26 #include "libanjuta/anjuta-token-stream.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); \
48 AnjutaTokenStream *stream;
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
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_]+
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; }
221 {WSNL} { RETURN (SPACE); }
223 \\\n { RETURN (SPACE); }
225 =|<|>|<=|>= { RETURN (OPERATOR); }
227 {NAME} { RETURN (WORD); }
235 *---------------------------------------------------------------------------*/
239 amp_ac_scanner_parse_end (AmpAcScanner *scanner)
242 if (scanner->stream == NULL)
250 scanner->eof = FALSE;
254 yypop_buffer_state(scanner->scanner);
255 scanner->stream = anjuta_token_stream_pop (scanner->stream);
257 if (scanner->stream == NULL)
263 scanner->eof = anjuta_token_stream_get_current_file (scanner->stream) != NULL;
265 /* Continue parsing the parent file */
272 *---------------------------------------------------------------------------*/
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))
281 g_message ("%s:%d.%d %s\n", location.filename, location.line, location.column, s);
282 g_free (location.filename);
286 g_message ("%s \n", s);
291 amp_ac_scanner_load_module (AmpAcScanner *scanner, AnjutaToken *module)
293 amp_project_load_module (scanner->project, module);
297 amp_ac_scanner_load_config (AmpAcScanner *scanner, AnjutaToken *list)
299 amp_project_load_config (scanner->project, list);
303 amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaToken *macro, AnjutaToken *list)
305 amp_project_load_properties (scanner->project, macro, list);
309 amp_ac_scanner_include (AmpAcScanner *scanner, AnjutaToken *list)
312 AnjutaTokenFile *include;
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);
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);
331 amp_ac_scanner_update_variable (AmpAcScanner *scanner, AnjutaToken *variable)
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);
345 amp_ac_scanner_subst_variable (AmpAcScanner *scanner, AnjutaToken *list)
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);
356 value = g_hash_table_lookup (scanner->variables, name);
359 amp_project_add_subst_variable (scanner->project, name, value);
364 *---------------------------------------------------------------------------*/
367 amp_ac_scanner_parse_token (AmpAcScanner *scanner, AnjutaToken *root, AnjutaToken *content, gint start, GFile *filename, GError **error)
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)
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);
388 YYSTYPE yylval_param;
389 YYLTYPE yylloc_param;
391 scanner->stream = stream;
392 ps = amp_ac_yypstate_new ();
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);
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);
420 /* Constructor & Destructor
421 *---------------------------------------------------------------------------*/
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);
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);