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"
24 #include "amp-source.h"
26 #include "libanjuta/anjuta-debug.h"
27 #include "libanjuta/anjuta-token-stream.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); \
49 AnjutaTokenStream *stream;
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
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_]+
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; }
222 {WSNL} { RETURN (SPACE); }
224 \\\n { RETURN (SPACE); }
226 =|<|>|<=|>= { RETURN (OPERATOR); }
228 {NAME} { RETURN (WORD); }
236 *---------------------------------------------------------------------------*/
240 amp_ac_scanner_parse_end (AmpAcScanner *scanner)
243 if (scanner->stream == NULL)
251 scanner->eof = FALSE;
255 yypop_buffer_state(scanner->scanner);
256 scanner->stream = anjuta_token_stream_pop (scanner->stream);
258 if (scanner->stream == NULL)
264 scanner->eof = anjuta_token_stream_get_current_file (scanner->stream) != NULL;
266 /* Continue parsing the parent file */
273 *---------------------------------------------------------------------------*/
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))
282 g_message ("%s:%d.%d %s\n", location.filename, location.line, location.column, s);
283 g_free (location.filename);
287 g_message ("%s \n", s);
292 amp_ac_scanner_load_module (AmpAcScanner *scanner, AnjutaToken *module)
294 amp_project_load_module (scanner->project, module);
298 amp_ac_scanner_load_config (AmpAcScanner *scanner, AnjutaToken *list)
300 amp_project_load_config (scanner->project, list);
304 amp_ac_scanner_load_properties (AmpAcScanner *scanner, AnjutaToken *macro, AnjutaToken *list)
306 amp_project_load_properties (scanner->project, macro, list);
310 amp_ac_scanner_include (AmpAcScanner *scanner, AnjutaToken *list)
313 AnjutaTokenFile *include;
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);
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);
335 amp_ac_scanner_update_variable (AmpAcScanner *scanner, AnjutaToken *variable)
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);
349 amp_ac_scanner_subst_variable (AmpAcScanner *scanner, AnjutaToken *list)
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);
360 value = g_hash_table_lookup (scanner->variables, name);
363 amp_project_add_subst_variable (scanner->project, name, value);
368 *---------------------------------------------------------------------------*/
371 amp_ac_scanner_parse_token (AmpAcScanner *scanner, AnjutaToken *root, AnjutaToken *content, gint start, GFile *filename, GError **error)
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)
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);
392 YYSTYPE yylval_param;
393 YYLTYPE yylloc_param;
395 scanner->stream = stream;
396 ps = amp_ac_yypstate_new ();
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);
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);
424 /* Constructor & Destructor
425 *---------------------------------------------------------------------------*/
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);
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);