glib/libglib/src/gscanner.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* GLIB - Library of useful routines for C programming
       
     2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
       
     3  *
       
     4  * GScanner: Flexible lexical scanner for general purpose.
       
     5  * Copyright (C) 1997, 1998 Tim Janik
       
     6  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Lesser General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
       
    16  * Lesser General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Lesser General Public
       
    19  * License along with this library; if not, write to the
       
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  */
       
    23 
       
    24 /*
       
    25  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    26  * file for a list of people on the GLib Team.  See the ChangeLog
       
    27  * files for a list of changes.  These files are distributed with
       
    28  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    29  */
       
    30 
       
    31 /* 
       
    32  * MT safe
       
    33  */
       
    34 
       
    35 #include "config.h"
       
    36 
       
    37 #include	<errno.h>
       
    38 #include	<stdlib.h>
       
    39 #include	<stdarg.h>
       
    40 #include	<string.h>
       
    41 #include	<stdio.h>
       
    42 #ifdef HAVE_UNISTD_H
       
    43 #include	<unistd.h>
       
    44 #endif
       
    45 
       
    46 #include	"glib.h"
       
    47 #include	"gprintfint.h"
       
    48 #include        "galias.h"
       
    49 
       
    50 #ifdef __SYMBIAN32__
       
    51 #include <glib_wsd.h>
       
    52 #endif
       
    53 
       
    54 #ifdef G_OS_WIN32
       
    55 #include	<io.h>		/* For _read() */
       
    56 #endif
       
    57 
       
    58 /* --- defines --- */
       
    59 #define	to_lower(c)				( \
       
    60 	(guchar) (							\
       
    61 	  ( (((guchar)(c))>='A' && ((guchar)(c))<='Z') * ('a'-'A') ) |	\
       
    62 	  ( (((guchar)(c))>=192 && ((guchar)(c))<=214) * (224-192) ) |	\
       
    63 	  ( (((guchar)(c))>=216 && ((guchar)(c))<=222) * (248-216) ) |	\
       
    64 	  ((guchar)(c))							\
       
    65 	)								\
       
    66 )
       
    67 #define	READ_BUFFER_SIZE	(4000)
       
    68 
       
    69 
       
    70 /* --- typedefs --- */
       
    71 typedef	struct	_GScannerKey	GScannerKey;
       
    72 
       
    73 struct	_GScannerKey
       
    74 {
       
    75   guint		 scope_id;
       
    76   gchar		*symbol;
       
    77   gpointer	 value;
       
    78 };
       
    79 
       
    80 
       
    81 /* --- variables --- */
       
    82 #if EMULATOR
       
    83 
       
    84 PLS(g_scanner_config_template ,gscanner,GScannerConfig)
       
    85 
       
    86 #define g_scanner_config_template  (*FUNCTION_NAME(g_scanner_config_template ,gscanner)())
       
    87 
       
    88 #else
       
    89 
       
    90 static GScannerConfig g_scanner_config_template =
       
    91 {
       
    92   (
       
    93    " \t\r\n"
       
    94    )			/* cset_skip_characters */,
       
    95   (
       
    96    G_CSET_a_2_z
       
    97    "_"
       
    98    G_CSET_A_2_Z
       
    99    )			/* cset_identifier_first */,
       
   100   (
       
   101    G_CSET_a_2_z
       
   102    "_"
       
   103    G_CSET_A_2_Z
       
   104    G_CSET_DIGITS
       
   105    G_CSET_LATINS
       
   106    G_CSET_LATINC
       
   107    )			/* cset_identifier_nth */,
       
   108   ( "#\n" )		/* cpair_comment_single */,
       
   109   
       
   110   FALSE			/* case_sensitive */,
       
   111   
       
   112   TRUE			/* skip_comment_multi */,
       
   113   TRUE			/* skip_comment_single */,
       
   114   TRUE			/* scan_comment_multi */,
       
   115   TRUE			/* scan_identifier */,
       
   116   FALSE			/* scan_identifier_1char */,
       
   117   FALSE			/* scan_identifier_NULL */,
       
   118   TRUE			/* scan_symbols */,
       
   119   FALSE			/* scan_binary */,
       
   120   TRUE			/* scan_octal */,
       
   121   TRUE			/* scan_float */,
       
   122   TRUE			/* scan_hex */,
       
   123   FALSE			/* scan_hex_dollar */,
       
   124   TRUE			/* scan_string_sq */,
       
   125   TRUE			/* scan_string_dq */,
       
   126   TRUE			/* numbers_2_int */,
       
   127   FALSE			/* int_2_float */,
       
   128   FALSE			/* identifier_2_string */,
       
   129   TRUE			/* char_2_token */,
       
   130   FALSE			/* symbol_2_token */,
       
   131   FALSE			/* scope_0_fallback */,
       
   132   FALSE			/* store_int64 */,
       
   133 };
       
   134 
       
   135 #endif /* EMULATOR */
       
   136 
       
   137 
       
   138 /* --- prototypes --- */
       
   139 static inline
       
   140 GScannerKey*	g_scanner_lookup_internal (GScanner	*scanner,
       
   141 					   guint	 scope_id,
       
   142 					   const gchar	*symbol);
       
   143 static gboolean	g_scanner_key_equal	  (gconstpointer v1,
       
   144 					   gconstpointer v2);
       
   145 static guint	g_scanner_key_hash	  (gconstpointer v);
       
   146 static void	g_scanner_get_token_ll	  (GScanner	*scanner,
       
   147 					   GTokenType	*token_p,
       
   148 					   GTokenValue	*value_p,
       
   149 					   guint	*line_p,
       
   150 					   guint	*position_p);
       
   151 static void	g_scanner_get_token_i	  (GScanner	*scanner,
       
   152 					   GTokenType	*token_p,
       
   153 					   GTokenValue	*value_p,
       
   154 					   guint	*line_p,
       
   155 					   guint	*position_p);
       
   156 
       
   157 static guchar	g_scanner_peek_next_char  (GScanner	*scanner);
       
   158 static guchar	g_scanner_get_char	  (GScanner	*scanner,
       
   159 					   guint	*line_p,
       
   160 					   guint	*position_p);
       
   161 static void	g_scanner_msg_handler	  (GScanner	*scanner,
       
   162 					   gchar	*message,
       
   163 					   gboolean	 is_error);
       
   164 
       
   165 
       
   166 /* --- functions --- */
       
   167 static inline gint
       
   168 g_scanner_char_2_num (guchar	c,
       
   169 		      guchar	base)
       
   170 {
       
   171   if (c >= '0' && c <= '9')
       
   172     c -= '0';
       
   173   else if (c >= 'A' && c <= 'Z')
       
   174     c -= 'A' - 10;
       
   175   else if (c >= 'a' && c <= 'z')
       
   176     c -= 'a' - 10;
       
   177   else
       
   178     return -1;
       
   179   
       
   180   if (c < base)
       
   181     return c;
       
   182   
       
   183   return -1;
       
   184 }
       
   185 
       
   186 EXPORT_C GScanner*
       
   187 g_scanner_new (const GScannerConfig *config_templ)
       
   188 {
       
   189   GScanner *scanner;
       
   190   
       
   191   if (!config_templ)
       
   192     config_templ = &g_scanner_config_template;
       
   193   scanner = g_new0 (GScanner, 1);
       
   194   
       
   195   scanner->user_data = NULL;
       
   196   scanner->max_parse_errors = 1;
       
   197   scanner->parse_errors	= 0;
       
   198   scanner->input_name = NULL;
       
   199   g_datalist_init (&scanner->qdata);
       
   200   scanner->config = g_new0 (GScannerConfig, 1);
       
   201   
       
   202   scanner->config->case_sensitive	 = config_templ->case_sensitive;
       
   203   scanner->config->cset_skip_characters	 = config_templ->cset_skip_characters;
       
   204   if (!scanner->config->cset_skip_characters)
       
   205     scanner->config->cset_skip_characters = "";
       
   206   scanner->config->cset_identifier_first = config_templ->cset_identifier_first;
       
   207   scanner->config->cset_identifier_nth	 = config_templ->cset_identifier_nth;
       
   208   scanner->config->cpair_comment_single	 = config_templ->cpair_comment_single;
       
   209   scanner->config->skip_comment_multi	 = config_templ->skip_comment_multi;
       
   210   scanner->config->skip_comment_single	 = config_templ->skip_comment_single;
       
   211   scanner->config->scan_comment_multi	 = config_templ->scan_comment_multi;
       
   212   scanner->config->scan_identifier	 = config_templ->scan_identifier;
       
   213   scanner->config->scan_identifier_1char = config_templ->scan_identifier_1char;
       
   214   scanner->config->scan_identifier_NULL	 = config_templ->scan_identifier_NULL;
       
   215   scanner->config->scan_symbols		 = config_templ->scan_symbols;
       
   216   scanner->config->scan_binary		 = config_templ->scan_binary;
       
   217   scanner->config->scan_octal		 = config_templ->scan_octal;
       
   218   scanner->config->scan_float		 = config_templ->scan_float;
       
   219   scanner->config->scan_hex		 = config_templ->scan_hex;
       
   220   scanner->config->scan_hex_dollar	 = config_templ->scan_hex_dollar;
       
   221   scanner->config->scan_string_sq	 = config_templ->scan_string_sq;
       
   222   scanner->config->scan_string_dq	 = config_templ->scan_string_dq;
       
   223   scanner->config->numbers_2_int	 = config_templ->numbers_2_int;
       
   224   scanner->config->int_2_float		 = config_templ->int_2_float;
       
   225   scanner->config->identifier_2_string	 = config_templ->identifier_2_string;
       
   226   scanner->config->char_2_token		 = config_templ->char_2_token;
       
   227   scanner->config->symbol_2_token	 = config_templ->symbol_2_token;
       
   228   scanner->config->scope_0_fallback	 = config_templ->scope_0_fallback;
       
   229   scanner->config->store_int64		 = config_templ->store_int64;
       
   230   
       
   231   scanner->token = G_TOKEN_NONE;
       
   232   scanner->value.v_int64 = 0;
       
   233   scanner->line = 1;
       
   234   scanner->position = 0;
       
   235   
       
   236   scanner->next_token = G_TOKEN_NONE;
       
   237   scanner->next_value.v_int64 = 0;
       
   238   scanner->next_line = 1;
       
   239   scanner->next_position = 0;
       
   240   
       
   241   scanner->symbol_table = g_hash_table_new (g_scanner_key_hash, g_scanner_key_equal);
       
   242   scanner->input_fd = -1;
       
   243   scanner->text = NULL;
       
   244   scanner->text_end = NULL;
       
   245   scanner->buffer = NULL;
       
   246   scanner->scope_id = 0;
       
   247   
       
   248   scanner->msg_handler = g_scanner_msg_handler;
       
   249   
       
   250   return scanner;
       
   251 }
       
   252 
       
   253 static inline void
       
   254 g_scanner_free_value (GTokenType     *token_p,
       
   255 		      GTokenValue     *value_p)
       
   256 {
       
   257   switch (*token_p)
       
   258     {
       
   259     case G_TOKEN_STRING:
       
   260     case G_TOKEN_IDENTIFIER:
       
   261     case G_TOKEN_IDENTIFIER_NULL:
       
   262     case G_TOKEN_COMMENT_SINGLE:
       
   263     case G_TOKEN_COMMENT_MULTI:
       
   264       g_free (value_p->v_string);
       
   265       break;
       
   266       
       
   267     default:
       
   268       break;
       
   269     }
       
   270   
       
   271   *token_p = G_TOKEN_NONE;
       
   272 }
       
   273 
       
   274 static void
       
   275 g_scanner_destroy_symbol_table_entry (gpointer _key,
       
   276 				      gpointer _value,
       
   277 				      gpointer _data)
       
   278 {
       
   279   GScannerKey *key = _key;
       
   280   
       
   281   g_free (key->symbol);
       
   282   g_free (key);
       
   283 }
       
   284 
       
   285 EXPORT_C void
       
   286 g_scanner_destroy (GScanner	*scanner)
       
   287 {
       
   288   g_return_if_fail (scanner != NULL);
       
   289   
       
   290   g_datalist_clear (&scanner->qdata);
       
   291   g_hash_table_foreach (scanner->symbol_table, 
       
   292 			g_scanner_destroy_symbol_table_entry, NULL);
       
   293   g_hash_table_destroy (scanner->symbol_table);
       
   294   g_scanner_free_value (&scanner->token, &scanner->value);
       
   295   g_scanner_free_value (&scanner->next_token, &scanner->next_value);
       
   296   g_free (scanner->config);
       
   297   g_free (scanner->buffer);
       
   298   g_free (scanner);
       
   299 }
       
   300 
       
   301 static void
       
   302 g_scanner_msg_handler (GScanner		*scanner,
       
   303 		       gchar		*message,
       
   304 		       gboolean		is_error)
       
   305 {
       
   306   g_return_if_fail (scanner != NULL);
       
   307   
       
   308   _g_fprintf (stderr, "%s:%d: ",
       
   309 	      scanner->input_name ? scanner->input_name : "<memory>",
       
   310 	      scanner->line);
       
   311   if (is_error)
       
   312     _g_fprintf (stderr, "error: ");
       
   313   _g_fprintf (stderr, "%s\n", message);
       
   314 }
       
   315 
       
   316 EXPORT_C void
       
   317 g_scanner_error (GScanner	*scanner,
       
   318 		 const gchar	*format,
       
   319 		 ...)
       
   320 {
       
   321   g_return_if_fail (scanner != NULL);
       
   322   g_return_if_fail (format != NULL);
       
   323   
       
   324   scanner->parse_errors++;
       
   325   
       
   326   if (scanner->msg_handler)
       
   327     {
       
   328       va_list args;
       
   329       gchar *string;
       
   330       
       
   331       va_start (args, format);
       
   332       string = g_strdup_vprintf (format, args);
       
   333       va_end (args);
       
   334       
       
   335       scanner->msg_handler (scanner, string, TRUE);
       
   336       
       
   337       g_free (string);
       
   338     }
       
   339 }
       
   340 
       
   341 EXPORT_C void
       
   342 g_scanner_warn (GScanner       *scanner,
       
   343 		const gchar    *format,
       
   344 		...)
       
   345 {
       
   346   g_return_if_fail (scanner != NULL);
       
   347   g_return_if_fail (format != NULL);
       
   348   
       
   349   if (scanner->msg_handler)
       
   350     {
       
   351       va_list args;
       
   352       gchar *string;
       
   353       
       
   354       va_start (args, format);
       
   355       string = g_strdup_vprintf (format, args);
       
   356       va_end (args);
       
   357       
       
   358       scanner->msg_handler (scanner, string, FALSE);
       
   359       
       
   360       g_free (string);
       
   361     }
       
   362 }
       
   363 
       
   364 static gboolean
       
   365 g_scanner_key_equal (gconstpointer v1,
       
   366 		     gconstpointer v2)
       
   367 {
       
   368   const GScannerKey *key1 = v1;
       
   369   const GScannerKey *key2 = v2;
       
   370   
       
   371   return (key1->scope_id == key2->scope_id) && (strcmp (key1->symbol, key2->symbol) == 0);
       
   372 }
       
   373 
       
   374 static guint
       
   375 g_scanner_key_hash (gconstpointer v)
       
   376 {
       
   377   const GScannerKey *key = v;
       
   378   gchar *c;
       
   379   guint h;
       
   380   
       
   381   h = key->scope_id;
       
   382   for (c = key->symbol; *c; c++)
       
   383     h = (h << 5) - h + *c;
       
   384   
       
   385   return h;
       
   386 }
       
   387 
       
   388 static inline GScannerKey*
       
   389 g_scanner_lookup_internal (GScanner	*scanner,
       
   390 			   guint	 scope_id,
       
   391 			   const gchar	*symbol)
       
   392 {
       
   393   GScannerKey	*key_p;
       
   394   GScannerKey key;
       
   395   
       
   396   key.scope_id = scope_id;
       
   397   
       
   398   if (!scanner->config->case_sensitive)
       
   399     {
       
   400       gchar *d;
       
   401       const gchar *c;
       
   402       key.symbol = g_new (gchar, strlen (symbol) + 1);
       
   403       for (d = key.symbol, c = symbol; *c; c++, d++)
       
   404 	*d = to_lower (*c);
       
   405       *d = 0;
       
   406       key_p = g_hash_table_lookup (scanner->symbol_table, &key);
       
   407       g_free (key.symbol);
       
   408     }
       
   409   else
       
   410     {
       
   411       key.symbol = (gchar*) symbol;
       
   412       key_p = g_hash_table_lookup (scanner->symbol_table, &key);
       
   413     }
       
   414   
       
   415   return key_p;
       
   416 }
       
   417 
       
   418 EXPORT_C void
       
   419 g_scanner_scope_add_symbol (GScanner	*scanner,
       
   420 			    guint	 scope_id,
       
   421 			    const gchar	*symbol,
       
   422 			    gpointer	 value)
       
   423 {
       
   424   GScannerKey	*key;
       
   425   
       
   426   g_return_if_fail (scanner != NULL);
       
   427   g_return_if_fail (symbol != NULL);
       
   428   
       
   429   key = g_scanner_lookup_internal (scanner, scope_id, symbol);
       
   430   
       
   431   if (!key)
       
   432     {
       
   433       key = g_new (GScannerKey, 1);
       
   434       key->scope_id = scope_id;
       
   435       key->symbol = g_strdup (symbol);
       
   436       key->value = value;
       
   437       if (!scanner->config->case_sensitive)
       
   438 	{
       
   439 	  gchar *c;
       
   440 	  
       
   441 	  c = key->symbol;
       
   442 	  while (*c != 0)
       
   443 	    {
       
   444 	      *c = to_lower (*c);
       
   445 	      c++;
       
   446 	    }
       
   447 	}
       
   448       g_hash_table_insert (scanner->symbol_table, key, key);
       
   449     }
       
   450   else
       
   451     key->value = value;
       
   452 }
       
   453 
       
   454 EXPORT_C void
       
   455 g_scanner_scope_remove_symbol (GScanner	   *scanner,
       
   456 			       guint	    scope_id,
       
   457 			       const gchar *symbol)
       
   458 {
       
   459   GScannerKey	*key;
       
   460   
       
   461   g_return_if_fail (scanner != NULL);
       
   462   g_return_if_fail (symbol != NULL);
       
   463   
       
   464   key = g_scanner_lookup_internal (scanner, scope_id, symbol);
       
   465   
       
   466   if (key)
       
   467     {
       
   468       g_hash_table_remove (scanner->symbol_table, key);
       
   469       g_free (key->symbol);
       
   470       g_free (key);
       
   471     }
       
   472 }
       
   473 
       
   474 EXPORT_C gpointer
       
   475 g_scanner_lookup_symbol (GScanner	*scanner,
       
   476 			 const gchar	*symbol)
       
   477 {
       
   478   GScannerKey	*key;
       
   479   guint scope_id;
       
   480   
       
   481   g_return_val_if_fail (scanner != NULL, NULL);
       
   482   
       
   483   if (!symbol)
       
   484     return NULL;
       
   485   
       
   486   scope_id = scanner->scope_id;
       
   487   key = g_scanner_lookup_internal (scanner, scope_id, symbol);
       
   488   if (!key && scope_id && scanner->config->scope_0_fallback)
       
   489     key = g_scanner_lookup_internal (scanner, 0, symbol);
       
   490   
       
   491   if (key)
       
   492     return key->value;
       
   493   else
       
   494     return NULL;
       
   495 }
       
   496 
       
   497 EXPORT_C gpointer
       
   498 g_scanner_scope_lookup_symbol (GScanner	      *scanner,
       
   499 			       guint	       scope_id,
       
   500 			       const gchar    *symbol)
       
   501 {
       
   502   GScannerKey	*key;
       
   503   
       
   504   g_return_val_if_fail (scanner != NULL, NULL);
       
   505   
       
   506   if (!symbol)
       
   507     return NULL;
       
   508   
       
   509   key = g_scanner_lookup_internal (scanner, scope_id, symbol);
       
   510   
       
   511   if (key)
       
   512     return key->value;
       
   513   else
       
   514     return NULL;
       
   515 }
       
   516 
       
   517 EXPORT_C guint
       
   518 g_scanner_set_scope (GScanner	    *scanner,
       
   519 		     guint	     scope_id)
       
   520 {
       
   521   guint old_scope_id;
       
   522   
       
   523   g_return_val_if_fail (scanner != NULL, 0);
       
   524   
       
   525   old_scope_id = scanner->scope_id;
       
   526   scanner->scope_id = scope_id;
       
   527   
       
   528   return old_scope_id;
       
   529 }
       
   530 
       
   531 static void
       
   532 g_scanner_foreach_internal (gpointer  _key,
       
   533 			    gpointer  _value,
       
   534 			    gpointer  _user_data)
       
   535 {
       
   536   GScannerKey *key;
       
   537   gpointer *d;
       
   538   GHFunc func;
       
   539   gpointer user_data;
       
   540   guint *scope_id;
       
   541   
       
   542   d = _user_data;
       
   543   func = (GHFunc) d[0];
       
   544   user_data = d[1];
       
   545   scope_id = d[2];
       
   546   key = _value;
       
   547   
       
   548   if (key->scope_id == *scope_id)
       
   549     func (key->symbol, key->value, user_data);
       
   550 }
       
   551 
       
   552 EXPORT_C void
       
   553 g_scanner_scope_foreach_symbol (GScanner       *scanner,
       
   554 				guint		scope_id,
       
   555 				GHFunc		func,
       
   556 				gpointer	user_data)
       
   557 {
       
   558   gpointer d[3];
       
   559   
       
   560   g_return_if_fail (scanner != NULL);
       
   561   
       
   562   d[0] = (gpointer) func;
       
   563   d[1] = user_data;
       
   564   d[2] = &scope_id;
       
   565   
       
   566   g_hash_table_foreach (scanner->symbol_table, g_scanner_foreach_internal, d);
       
   567 }
       
   568 
       
   569 EXPORT_C GTokenType
       
   570 g_scanner_peek_next_token (GScanner	*scanner)
       
   571 {
       
   572   g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
       
   573   
       
   574   if (scanner->next_token == G_TOKEN_NONE)
       
   575     {
       
   576       scanner->next_line = scanner->line;
       
   577       scanner->next_position = scanner->position;
       
   578       g_scanner_get_token_i (scanner,
       
   579 			     &scanner->next_token,
       
   580 			     &scanner->next_value,
       
   581 			     &scanner->next_line,
       
   582 			     &scanner->next_position);
       
   583     }
       
   584   
       
   585   return scanner->next_token;
       
   586 }
       
   587 
       
   588 EXPORT_C GTokenType
       
   589 g_scanner_get_next_token (GScanner	*scanner)
       
   590 {
       
   591   g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
       
   592   
       
   593   if (scanner->next_token != G_TOKEN_NONE)
       
   594     {
       
   595       g_scanner_free_value (&scanner->token, &scanner->value);
       
   596       
       
   597       scanner->token = scanner->next_token;
       
   598       scanner->value = scanner->next_value;
       
   599       scanner->line = scanner->next_line;
       
   600       scanner->position = scanner->next_position;
       
   601       scanner->next_token = G_TOKEN_NONE;
       
   602     }
       
   603   else
       
   604     g_scanner_get_token_i (scanner,
       
   605 			   &scanner->token,
       
   606 			   &scanner->value,
       
   607 			   &scanner->line,
       
   608 			   &scanner->position);
       
   609   
       
   610   return scanner->token;
       
   611 }
       
   612 
       
   613 EXPORT_C GTokenType
       
   614 g_scanner_cur_token (GScanner *scanner)
       
   615 {
       
   616   g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
       
   617   
       
   618   return scanner->token;
       
   619 }
       
   620 
       
   621 EXPORT_C GTokenValue
       
   622 g_scanner_cur_value (GScanner *scanner)
       
   623 {
       
   624   GTokenValue v;
       
   625   
       
   626   v.v_int64 = 0;
       
   627   
       
   628   g_return_val_if_fail (scanner != NULL, v);
       
   629 
       
   630   /* MSC isn't capable of handling return scanner->value; ? */
       
   631 
       
   632   v = scanner->value;
       
   633 
       
   634   return v;
       
   635 }
       
   636 
       
   637 EXPORT_C guint
       
   638 g_scanner_cur_line (GScanner *scanner)
       
   639 {
       
   640   g_return_val_if_fail (scanner != NULL, 0);
       
   641   
       
   642   return scanner->line;
       
   643 }
       
   644 
       
   645 EXPORT_C guint
       
   646 g_scanner_cur_position (GScanner *scanner)
       
   647 {
       
   648   g_return_val_if_fail (scanner != NULL, 0);
       
   649   
       
   650   return scanner->position;
       
   651 }
       
   652 
       
   653 EXPORT_C gboolean
       
   654 g_scanner_eof (GScanner	*scanner)
       
   655 {
       
   656   g_return_val_if_fail (scanner != NULL, TRUE);
       
   657   
       
   658   return scanner->token == G_TOKEN_EOF || scanner->token == G_TOKEN_ERROR;
       
   659 }
       
   660 
       
   661 EXPORT_C void
       
   662 g_scanner_input_file (GScanner *scanner,
       
   663 		      gint	input_fd)
       
   664 {
       
   665   g_return_if_fail (scanner != NULL);
       
   666   g_return_if_fail (input_fd >= 0);
       
   667 
       
   668   if (scanner->input_fd >= 0)
       
   669     g_scanner_sync_file_offset (scanner);
       
   670 
       
   671   scanner->token = G_TOKEN_NONE;
       
   672   scanner->value.v_int64 = 0;
       
   673   scanner->line = 1;
       
   674   scanner->position = 0;
       
   675   scanner->next_token = G_TOKEN_NONE;
       
   676 
       
   677   scanner->input_fd = input_fd;
       
   678   scanner->text = NULL;
       
   679   scanner->text_end = NULL;
       
   680 
       
   681   if (!scanner->buffer)
       
   682     scanner->buffer = g_new (gchar, READ_BUFFER_SIZE + 1);
       
   683 }
       
   684 
       
   685 EXPORT_C void
       
   686 g_scanner_input_text (GScanner	  *scanner,
       
   687 		      const gchar *text,
       
   688 		      guint	   text_len)
       
   689 {
       
   690   g_return_if_fail (scanner != NULL);
       
   691   if (text_len)
       
   692     g_return_if_fail (text != NULL);
       
   693   else
       
   694     text = NULL;
       
   695 
       
   696   if (scanner->input_fd >= 0)
       
   697     g_scanner_sync_file_offset (scanner);
       
   698 
       
   699   scanner->token = G_TOKEN_NONE;
       
   700   scanner->value.v_int64 = 0;
       
   701   scanner->line = 1;
       
   702   scanner->position = 0;
       
   703   scanner->next_token = G_TOKEN_NONE;
       
   704 
       
   705   scanner->input_fd = -1;
       
   706   scanner->text = text;
       
   707   scanner->text_end = text + text_len;
       
   708 
       
   709   if (scanner->buffer)
       
   710     {
       
   711       g_free (scanner->buffer);
       
   712       scanner->buffer = NULL;
       
   713     }
       
   714 }
       
   715 
       
   716 static guchar
       
   717 g_scanner_peek_next_char (GScanner *scanner)
       
   718 {
       
   719   if (scanner->text < scanner->text_end)
       
   720     {
       
   721       return *scanner->text;
       
   722     }
       
   723   else if (scanner->input_fd >= 0)
       
   724     {
       
   725       gint count;
       
   726       gchar *buffer;
       
   727 
       
   728       buffer = scanner->buffer;
       
   729       do
       
   730 	{
       
   731 	  count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
       
   732 	}
       
   733       while (count == -1 && (errno == EINTR || errno == EAGAIN));
       
   734 
       
   735       if (count < 1)
       
   736 	{
       
   737 	  scanner->input_fd = -1;
       
   738 
       
   739 	  return 0;
       
   740 	}
       
   741       else
       
   742 	{
       
   743 	  scanner->text = buffer;
       
   744 	  scanner->text_end = buffer + count;
       
   745 
       
   746 	  return *buffer;
       
   747 	}
       
   748     }
       
   749   else
       
   750     return 0;
       
   751 }
       
   752 
       
   753 EXPORT_C void
       
   754 g_scanner_sync_file_offset (GScanner *scanner)
       
   755 {
       
   756   g_return_if_fail (scanner != NULL);
       
   757 
       
   758   /* for file input, rewind the filedescriptor to the current
       
   759    * buffer position and blow the file read ahead buffer. usefull for
       
   760    * third party uses of our filedescriptor, which hooks onto the current
       
   761    * scanning position.
       
   762    */
       
   763 
       
   764   if (scanner->input_fd >= 0 && scanner->text_end > scanner->text)
       
   765     {
       
   766       gint buffered;
       
   767 
       
   768       buffered = scanner->text_end - scanner->text;
       
   769       if (lseek (scanner->input_fd, - buffered, SEEK_CUR) >= 0)
       
   770 	{
       
   771 	  /* we succeeded, blow our buffer's contents now */
       
   772 	  scanner->text = NULL;
       
   773 	  scanner->text_end = NULL;
       
   774 	}
       
   775       else
       
   776 	errno = 0;
       
   777     }
       
   778 }
       
   779 
       
   780 static guchar
       
   781 g_scanner_get_char (GScanner	*scanner,
       
   782 		    guint	*line_p,
       
   783 		    guint	*position_p)
       
   784 {
       
   785   guchar fchar;
       
   786 
       
   787   if (scanner->text < scanner->text_end)
       
   788     fchar = *(scanner->text++);
       
   789   else if (scanner->input_fd >= 0)
       
   790     {
       
   791       gint count;
       
   792       gchar *buffer;
       
   793 
       
   794       buffer = scanner->buffer;
       
   795       do
       
   796 	{
       
   797 	  count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
       
   798 	}
       
   799       while (count == -1 && (errno == EINTR || errno == EAGAIN));
       
   800 
       
   801       if (count < 1)
       
   802 	{
       
   803 	  scanner->input_fd = -1;
       
   804 	  fchar = 0;
       
   805 	}
       
   806       else
       
   807 	{
       
   808 	  scanner->text = buffer + 1;
       
   809 	  scanner->text_end = buffer + count;
       
   810 	  fchar = *buffer;
       
   811 	  if (!fchar)
       
   812 	    {
       
   813 	      g_scanner_sync_file_offset (scanner);
       
   814 	      scanner->text_end = scanner->text;
       
   815 	      scanner->input_fd = -1;
       
   816 	    }
       
   817 	}
       
   818     }
       
   819   else
       
   820     fchar = 0;
       
   821   
       
   822   if (fchar == '\n')
       
   823     {
       
   824       (*position_p) = 0;
       
   825       (*line_p)++;
       
   826     }
       
   827   else if (fchar)
       
   828     {
       
   829       (*position_p)++;
       
   830     }
       
   831   
       
   832   return fchar;
       
   833 }
       
   834 
       
   835 EXPORT_C void
       
   836 g_scanner_unexp_token (GScanner		*scanner,
       
   837 		       GTokenType	 expected_token,
       
   838 		       const gchar	*identifier_spec,
       
   839 		       const gchar	*symbol_spec,
       
   840 		       const gchar	*symbol_name,
       
   841 		       const gchar	*message,
       
   842 		       gint		 is_error)
       
   843 {
       
   844   gchar	*token_string;
       
   845   guint	token_string_len;
       
   846   gchar	*expected_string;
       
   847   guint	expected_string_len;
       
   848   gchar	*message_prefix;
       
   849   gboolean print_unexp;
       
   850   void (*msg_handler)	(GScanner*, const gchar*, ...);
       
   851   
       
   852   g_return_if_fail (scanner != NULL);
       
   853   
       
   854   if (is_error)
       
   855     msg_handler = g_scanner_error;
       
   856   else
       
   857     msg_handler = g_scanner_warn;
       
   858   
       
   859   if (!identifier_spec)
       
   860     identifier_spec = "identifier";
       
   861   if (!symbol_spec)
       
   862     symbol_spec = "symbol";
       
   863   
       
   864   token_string_len = 56;
       
   865   token_string = g_new (gchar, token_string_len + 1);
       
   866   expected_string_len = 64;
       
   867   expected_string = g_new (gchar, expected_string_len + 1);
       
   868   print_unexp = TRUE;
       
   869   
       
   870   switch (scanner->token)
       
   871     {
       
   872     case G_TOKEN_EOF:
       
   873       _g_snprintf (token_string, token_string_len, "end of file");
       
   874       break;
       
   875       
       
   876     default:
       
   877       if (scanner->token >= 1 && scanner->token <= 255)
       
   878 	{
       
   879 	  if ((scanner->token >= ' ' && scanner->token <= '~') ||
       
   880 	      strchr (scanner->config->cset_identifier_first, scanner->token) ||
       
   881 	      strchr (scanner->config->cset_identifier_nth, scanner->token))
       
   882 	    _g_snprintf (token_string, token_string_len, "character `%c'", scanner->token);
       
   883 	  else
       
   884 	    _g_snprintf (token_string, token_string_len, "character `\\%o'", scanner->token);
       
   885 	  break;
       
   886 	}
       
   887       else if (!scanner->config->symbol_2_token)
       
   888 	{
       
   889 	  _g_snprintf (token_string, token_string_len, "(unknown) token <%d>", scanner->token);
       
   890 	  break;
       
   891 	}
       
   892       /* fall through */
       
   893     case G_TOKEN_SYMBOL:
       
   894       if (expected_token == G_TOKEN_SYMBOL ||
       
   895 	  (scanner->config->symbol_2_token &&
       
   896 	   expected_token > G_TOKEN_LAST))
       
   897 	print_unexp = FALSE;
       
   898       if (symbol_name)
       
   899 	_g_snprintf (token_string,
       
   900 		     token_string_len,
       
   901 		     "%s%s `%s'",
       
   902 		     print_unexp ? "" : "invalid ",
       
   903 		     symbol_spec,
       
   904 		     symbol_name);
       
   905       else
       
   906 	_g_snprintf (token_string,
       
   907 		     token_string_len,
       
   908 		     "%s%s",
       
   909 		     print_unexp ? "" : "invalid ",
       
   910 		     symbol_spec);
       
   911       break;
       
   912       
       
   913     case G_TOKEN_ERROR:
       
   914       print_unexp = FALSE;
       
   915       expected_token = G_TOKEN_NONE;
       
   916       switch (scanner->value.v_error)
       
   917 	{
       
   918 	case G_ERR_UNEXP_EOF:
       
   919 	  _g_snprintf (token_string, token_string_len, "scanner: unexpected end of file");
       
   920 	  break;
       
   921 	  
       
   922 	case G_ERR_UNEXP_EOF_IN_STRING:
       
   923 	  _g_snprintf (token_string, token_string_len, "scanner: unterminated string constant");
       
   924 	  break;
       
   925 	  
       
   926 	case G_ERR_UNEXP_EOF_IN_COMMENT:
       
   927 	  _g_snprintf (token_string, token_string_len, "scanner: unterminated comment");
       
   928 	  break;
       
   929 	  
       
   930 	case G_ERR_NON_DIGIT_IN_CONST:
       
   931 	  _g_snprintf (token_string, token_string_len, "scanner: non digit in constant");
       
   932 	  break;
       
   933 	  
       
   934 	case G_ERR_FLOAT_RADIX:
       
   935 	  _g_snprintf (token_string, token_string_len, "scanner: invalid radix for floating constant");
       
   936 	  break;
       
   937 	  
       
   938 	case G_ERR_FLOAT_MALFORMED:
       
   939 	  _g_snprintf (token_string, token_string_len, "scanner: malformed floating constant");
       
   940 	  break;
       
   941 	  
       
   942 	case G_ERR_DIGIT_RADIX:
       
   943 	  _g_snprintf (token_string, token_string_len, "scanner: digit is beyond radix");
       
   944 	  break;
       
   945 	  
       
   946 	case G_ERR_UNKNOWN:
       
   947 	default:
       
   948 	  _g_snprintf (token_string, token_string_len, "scanner: unknown error");
       
   949 	  break;
       
   950 	}
       
   951       break;
       
   952       
       
   953     case G_TOKEN_CHAR:
       
   954       _g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char);
       
   955       break;
       
   956       
       
   957     case G_TOKEN_IDENTIFIER:
       
   958     case G_TOKEN_IDENTIFIER_NULL:
       
   959       if (expected_token == G_TOKEN_IDENTIFIER ||
       
   960 	  expected_token == G_TOKEN_IDENTIFIER_NULL)
       
   961 	print_unexp = FALSE;
       
   962       _g_snprintf (token_string,
       
   963 		  token_string_len,
       
   964 		  "%s%s `%s'",
       
   965 		  print_unexp ? "" : "invalid ",
       
   966 		  identifier_spec,
       
   967 		  scanner->token == G_TOKEN_IDENTIFIER ? scanner->value.v_string : "null");
       
   968       break;
       
   969       
       
   970     case G_TOKEN_BINARY:
       
   971     case G_TOKEN_OCTAL:
       
   972     case G_TOKEN_INT:
       
   973     case G_TOKEN_HEX:
       
   974       if (scanner->config->store_int64)
       
   975 	_g_snprintf (token_string, token_string_len, "number `%" G_GUINT64_FORMAT "'", scanner->value.v_int64);
       
   976       else
       
   977 	_g_snprintf (token_string, token_string_len, "number `%lu'", scanner->value.v_int);
       
   978       break;
       
   979       
       
   980     case G_TOKEN_FLOAT:
       
   981       _g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float);
       
   982       break;
       
   983       
       
   984     case G_TOKEN_STRING:
       
   985       if (expected_token == G_TOKEN_STRING)
       
   986 	print_unexp = FALSE;
       
   987       _g_snprintf (token_string,
       
   988 		   token_string_len,
       
   989 		   "%s%sstring constant \"%s\"",
       
   990 		   print_unexp ? "" : "invalid ",
       
   991 		   scanner->value.v_string[0] == 0 ? "empty " : "",
       
   992 		   scanner->value.v_string);
       
   993       token_string[token_string_len - 2] = '"';
       
   994       token_string[token_string_len - 1] = 0;
       
   995       break;
       
   996       
       
   997     case G_TOKEN_COMMENT_SINGLE:
       
   998     case G_TOKEN_COMMENT_MULTI:
       
   999       _g_snprintf (token_string, token_string_len, "comment");
       
  1000       break;
       
  1001       
       
  1002     case G_TOKEN_NONE:
       
  1003       /* somehow the user's parsing code is screwed, there isn't much
       
  1004        * we can do about it.
       
  1005        * Note, a common case to trigger this is
       
  1006        * g_scanner_peek_next_token(); g_scanner_unexp_token();
       
  1007        * without an intermediate g_scanner_get_next_token().
       
  1008        */
       
  1009       g_assert_not_reached ();
       
  1010       break;
       
  1011     }
       
  1012   
       
  1013   
       
  1014   switch (expected_token)
       
  1015     {
       
  1016       gboolean need_valid;
       
  1017       gchar *tstring;
       
  1018     case G_TOKEN_EOF:
       
  1019       _g_snprintf (expected_string, expected_string_len, "end of file");
       
  1020       break;
       
  1021     default:
       
  1022       if (expected_token >= 1 && expected_token <= 255)
       
  1023 	{
       
  1024 	  if ((expected_token >= ' ' && expected_token <= '~') ||
       
  1025 	      strchr (scanner->config->cset_identifier_first, expected_token) ||
       
  1026 	      strchr (scanner->config->cset_identifier_nth, expected_token))
       
  1027 	    _g_snprintf (expected_string, expected_string_len, "character `%c'", expected_token);
       
  1028 	  else
       
  1029 	    _g_snprintf (expected_string, expected_string_len, "character `\\%o'", expected_token);
       
  1030 	  break;
       
  1031 	}
       
  1032       else if (!scanner->config->symbol_2_token)
       
  1033 	{
       
  1034 	  _g_snprintf (expected_string, expected_string_len, "(unknown) token <%d>", expected_token);
       
  1035 	  break;
       
  1036 	}
       
  1037       /* fall through */
       
  1038     case G_TOKEN_SYMBOL:
       
  1039       need_valid = (scanner->token == G_TOKEN_SYMBOL ||
       
  1040 		    (scanner->config->symbol_2_token &&
       
  1041 		     scanner->token > G_TOKEN_LAST));
       
  1042       _g_snprintf (expected_string,
       
  1043 		   expected_string_len,
       
  1044 		   "%s%s",
       
  1045 		   need_valid ? "valid " : "",
       
  1046 		   symbol_spec);
       
  1047       /* FIXME: should we attempt to lookup the symbol_name for symbol_2_token? */
       
  1048       break;
       
  1049     case G_TOKEN_CHAR:
       
  1050       _g_snprintf (expected_string, expected_string_len, "%scharacter",
       
  1051 		   scanner->token == G_TOKEN_CHAR ? "valid " : "");
       
  1052       break;
       
  1053     case G_TOKEN_BINARY:
       
  1054       tstring = "binary";
       
  1055       _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
       
  1056 		   scanner->token == expected_token ? "valid " : "", tstring);
       
  1057       break;
       
  1058     case G_TOKEN_OCTAL:
       
  1059       tstring = "octal";
       
  1060       _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
       
  1061 		   scanner->token == expected_token ? "valid " : "", tstring);
       
  1062       break;
       
  1063     case G_TOKEN_INT:
       
  1064       tstring = "integer";
       
  1065       _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
       
  1066 		   scanner->token == expected_token ? "valid " : "", tstring);
       
  1067       break;
       
  1068     case G_TOKEN_HEX:
       
  1069       tstring = "hexadecimal";
       
  1070       _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
       
  1071 		   scanner->token == expected_token ? "valid " : "", tstring);
       
  1072       break;
       
  1073     case G_TOKEN_FLOAT:
       
  1074       tstring = "float";
       
  1075       _g_snprintf (expected_string, expected_string_len, "%snumber (%s)",
       
  1076 		   scanner->token == expected_token ? "valid " : "", tstring);
       
  1077       break;
       
  1078     case G_TOKEN_STRING:
       
  1079       _g_snprintf (expected_string,
       
  1080 		   expected_string_len,
       
  1081 		   "%sstring constant",
       
  1082 		   scanner->token == G_TOKEN_STRING ? "valid " : "");
       
  1083       break;
       
  1084     case G_TOKEN_IDENTIFIER:
       
  1085     case G_TOKEN_IDENTIFIER_NULL:
       
  1086       need_valid = (scanner->token == G_TOKEN_IDENTIFIER_NULL ||
       
  1087 		    scanner->token == G_TOKEN_IDENTIFIER);
       
  1088       _g_snprintf (expected_string,
       
  1089 		   expected_string_len,
       
  1090 		   "%s%s",
       
  1091 		   need_valid ? "valid " : "",
       
  1092 		   identifier_spec);
       
  1093       break;
       
  1094     case G_TOKEN_COMMENT_SINGLE:
       
  1095       tstring = "single-line";
       
  1096       _g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
       
  1097 		   scanner->token == expected_token ? "valid " : "", tstring);
       
  1098       break;
       
  1099     case G_TOKEN_COMMENT_MULTI:
       
  1100       tstring = "multi-line";
       
  1101       _g_snprintf (expected_string, expected_string_len, "%scomment (%s)",
       
  1102 		   scanner->token == expected_token ? "valid " : "", tstring);
       
  1103       break;
       
  1104     case G_TOKEN_NONE:
       
  1105     case G_TOKEN_ERROR:
       
  1106       /* this is handled upon printout */
       
  1107       break;
       
  1108     }
       
  1109   
       
  1110   if (message && message[0] != 0)
       
  1111     message_prefix = " - ";
       
  1112   else
       
  1113     {
       
  1114       message_prefix = "";
       
  1115       message = "";
       
  1116     }
       
  1117   if (expected_token == G_TOKEN_ERROR)
       
  1118     {
       
  1119       msg_handler (scanner,
       
  1120 		   "failure around %s%s%s",
       
  1121 		   token_string,
       
  1122 		   message_prefix,
       
  1123 		   message);
       
  1124     }
       
  1125   else if (expected_token == G_TOKEN_NONE)
       
  1126     {
       
  1127       if (print_unexp)
       
  1128 	msg_handler (scanner,
       
  1129 		     "unexpected %s%s%s",
       
  1130 		     token_string,
       
  1131 		     message_prefix,
       
  1132 		     message);
       
  1133       else
       
  1134 	msg_handler (scanner,
       
  1135 		     "%s%s%s",
       
  1136 		     token_string,
       
  1137 		     message_prefix,
       
  1138 		     message);
       
  1139     }
       
  1140   else
       
  1141     {
       
  1142       if (print_unexp)
       
  1143 	msg_handler (scanner,
       
  1144 		     "unexpected %s, expected %s%s%s",
       
  1145 		     token_string,
       
  1146 		     expected_string,
       
  1147 		     message_prefix,
       
  1148 		     message);
       
  1149       else
       
  1150 	msg_handler (scanner,
       
  1151 		     "%s, expected %s%s%s",
       
  1152 		     token_string,
       
  1153 		     expected_string,
       
  1154 		     message_prefix,
       
  1155 		     message);
       
  1156     }
       
  1157   
       
  1158   g_free (token_string);
       
  1159   g_free (expected_string);
       
  1160 }
       
  1161 
       
  1162 static void
       
  1163 g_scanner_get_token_i (GScanner	*scanner,
       
  1164 		       GTokenType	*token_p,
       
  1165 		       GTokenValue	*value_p,
       
  1166 		       guint		*line_p,
       
  1167 		       guint		*position_p)
       
  1168 {
       
  1169   do
       
  1170     {
       
  1171       g_scanner_free_value (token_p, value_p);
       
  1172       g_scanner_get_token_ll (scanner, token_p, value_p, line_p, position_p);
       
  1173     }
       
  1174   while (((*token_p > 0 && *token_p < 256) &&
       
  1175 	  strchr (scanner->config->cset_skip_characters, *token_p)) ||
       
  1176 	 (*token_p == G_TOKEN_CHAR &&
       
  1177 	  strchr (scanner->config->cset_skip_characters, value_p->v_char)) ||
       
  1178 	 (*token_p == G_TOKEN_COMMENT_MULTI &&
       
  1179 	  scanner->config->skip_comment_multi) ||
       
  1180 	 (*token_p == G_TOKEN_COMMENT_SINGLE &&
       
  1181 	  scanner->config->skip_comment_single));
       
  1182   
       
  1183   switch (*token_p)
       
  1184     {
       
  1185     case G_TOKEN_IDENTIFIER:
       
  1186       if (scanner->config->identifier_2_string)
       
  1187 	*token_p = G_TOKEN_STRING;
       
  1188       break;
       
  1189       
       
  1190     case G_TOKEN_SYMBOL:
       
  1191       if (scanner->config->symbol_2_token)
       
  1192 	*token_p = (GTokenType) value_p->v_symbol;
       
  1193       break;
       
  1194       
       
  1195     case G_TOKEN_BINARY:
       
  1196     case G_TOKEN_OCTAL:
       
  1197     case G_TOKEN_HEX:
       
  1198       if (scanner->config->numbers_2_int)
       
  1199 	*token_p = G_TOKEN_INT;
       
  1200       break;
       
  1201       
       
  1202     default:
       
  1203       break;
       
  1204     }
       
  1205   
       
  1206   if (*token_p == G_TOKEN_INT &&
       
  1207       scanner->config->int_2_float)
       
  1208     {
       
  1209       *token_p = G_TOKEN_FLOAT;
       
  1210       if (scanner->config->store_int64)
       
  1211         {
       
  1212 #ifdef _MSC_VER
       
  1213           /* work around error C2520, see gvaluetransform.c */
       
  1214           value_p->v_float = (__int64)value_p->v_int64;
       
  1215 #else
       
  1216           value_p->v_float = value_p->v_int64;
       
  1217 #endif
       
  1218         }
       
  1219       else
       
  1220 	value_p->v_float = value_p->v_int;
       
  1221     }
       
  1222   
       
  1223   errno = 0;
       
  1224 }
       
  1225 
       
  1226 static void
       
  1227 g_scanner_get_token_ll	(GScanner	*scanner,
       
  1228 			 GTokenType	*token_p,
       
  1229 			 GTokenValue	*value_p,
       
  1230 			 guint		*line_p,
       
  1231 			 guint		*position_p)
       
  1232 {
       
  1233   GScannerConfig *config;
       
  1234   GTokenType	   token;
       
  1235   gboolean	   in_comment_multi;
       
  1236   gboolean	   in_comment_single;
       
  1237   gboolean	   in_string_sq;
       
  1238   gboolean	   in_string_dq;
       
  1239   GString	  *gstring;
       
  1240   GTokenValue	   value;
       
  1241   guchar	   ch;
       
  1242   
       
  1243   config = scanner->config;
       
  1244   (*value_p).v_int64 = 0;
       
  1245   
       
  1246   if ((scanner->text >= scanner->text_end && scanner->input_fd < 0) ||
       
  1247       scanner->token == G_TOKEN_EOF)
       
  1248     {
       
  1249       *token_p = G_TOKEN_EOF;
       
  1250       return;
       
  1251     }
       
  1252   
       
  1253   in_comment_multi = FALSE;
       
  1254   in_comment_single = FALSE;
       
  1255   in_string_sq = FALSE;
       
  1256   in_string_dq = FALSE;
       
  1257   gstring = NULL;
       
  1258   
       
  1259   do /* while (ch != 0) */
       
  1260     {
       
  1261       gboolean dotted_float = FALSE;
       
  1262       
       
  1263       ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1264       
       
  1265       value.v_int64 = 0;
       
  1266       token = G_TOKEN_NONE;
       
  1267       
       
  1268       /* this is *evil*, but needed ;(
       
  1269        * we first check for identifier first character, because	 it
       
  1270        * might interfere with other key chars like slashes or numbers
       
  1271        */
       
  1272       if (config->scan_identifier &&
       
  1273 	  ch && strchr (config->cset_identifier_first, ch))
       
  1274 	goto identifier_precedence;
       
  1275       
       
  1276       switch (ch)
       
  1277 	{
       
  1278 	case 0:
       
  1279 	  token = G_TOKEN_EOF;
       
  1280 	  (*position_p)++;
       
  1281 	  /* ch = 0; */
       
  1282 	  break;
       
  1283 	  
       
  1284 	case '/':
       
  1285 	  if (!config->scan_comment_multi ||
       
  1286 	      g_scanner_peek_next_char (scanner) != '*')
       
  1287 	    goto default_case;
       
  1288 	  g_scanner_get_char (scanner, line_p, position_p);
       
  1289 	  token = G_TOKEN_COMMENT_MULTI;
       
  1290 	  in_comment_multi = TRUE;
       
  1291 	  gstring = g_string_new (NULL);
       
  1292 	  while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
       
  1293 	    {
       
  1294 	      if (ch == '*' && g_scanner_peek_next_char (scanner) == '/')
       
  1295 		{
       
  1296 		  g_scanner_get_char (scanner, line_p, position_p);
       
  1297 		  in_comment_multi = FALSE;
       
  1298 		  break;
       
  1299 		}
       
  1300 	      else
       
  1301 		gstring = g_string_append_c (gstring, ch);
       
  1302 	    }
       
  1303 	  ch = 0;
       
  1304 	  break;
       
  1305 	  
       
  1306 	case '\'':
       
  1307 	  if (!config->scan_string_sq)
       
  1308 	    goto default_case;
       
  1309 	  token = G_TOKEN_STRING;
       
  1310 	  in_string_sq = TRUE;
       
  1311 	  gstring = g_string_new (NULL);
       
  1312 	  while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
       
  1313 	    {
       
  1314 	      if (ch == '\'')
       
  1315 		{
       
  1316 		  in_string_sq = FALSE;
       
  1317 		  break;
       
  1318 		}
       
  1319 	      else
       
  1320 		gstring = g_string_append_c (gstring, ch);
       
  1321 	    }
       
  1322 	  ch = 0;
       
  1323 	  break;
       
  1324 	  
       
  1325 	case '"':
       
  1326 	  if (!config->scan_string_dq)
       
  1327 	    goto default_case;
       
  1328 	  token = G_TOKEN_STRING;
       
  1329 	  in_string_dq = TRUE;
       
  1330 	  gstring = g_string_new (NULL);
       
  1331 	  while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
       
  1332 	    {
       
  1333 	      if (ch == '"')
       
  1334 		{
       
  1335 		  in_string_dq = FALSE;
       
  1336 		  break;
       
  1337 		}
       
  1338 	      else
       
  1339 		{
       
  1340 		  if (ch == '\\')
       
  1341 		    {
       
  1342 		      ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1343 		      switch (ch)
       
  1344 			{
       
  1345 			  guint	i;
       
  1346 			  guint	fchar;
       
  1347 			  
       
  1348 			case 0:
       
  1349 			  break;
       
  1350 			  
       
  1351 			case '\\':
       
  1352 			  gstring = g_string_append_c (gstring, '\\');
       
  1353 			  break;
       
  1354 			  
       
  1355 			case 'n':
       
  1356 			  gstring = g_string_append_c (gstring, '\n');
       
  1357 			  break;
       
  1358 			  
       
  1359 			case 't':
       
  1360 			  gstring = g_string_append_c (gstring, '\t');
       
  1361 			  break;
       
  1362 			  
       
  1363 			case 'r':
       
  1364 			  gstring = g_string_append_c (gstring, '\r');
       
  1365 			  break;
       
  1366 			  
       
  1367 			case 'b':
       
  1368 			  gstring = g_string_append_c (gstring, '\b');
       
  1369 			  break;
       
  1370 			  
       
  1371 			case 'f':
       
  1372 			  gstring = g_string_append_c (gstring, '\f');
       
  1373 			  break;
       
  1374 			  
       
  1375 			case '0':
       
  1376 			case '1':
       
  1377 			case '2':
       
  1378 			case '3':
       
  1379 			case '4':
       
  1380 			case '5':
       
  1381 			case '6':
       
  1382 			case '7':
       
  1383 			  i = ch - '0';
       
  1384 			  fchar = g_scanner_peek_next_char (scanner);
       
  1385 			  if (fchar >= '0' && fchar <= '7')
       
  1386 			    {
       
  1387 			      ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1388 			      i = i * 8 + ch - '0';
       
  1389 			      fchar = g_scanner_peek_next_char (scanner);
       
  1390 			      if (fchar >= '0' && fchar <= '7')
       
  1391 				{
       
  1392 				  ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1393 				  i = i * 8 + ch - '0';
       
  1394 				}
       
  1395 			    }
       
  1396 			  gstring = g_string_append_c (gstring, i);
       
  1397 			  break;
       
  1398 			  
       
  1399 			default:
       
  1400 			  gstring = g_string_append_c (gstring, ch);
       
  1401 			  break;
       
  1402 			}
       
  1403 		    }
       
  1404 		  else
       
  1405 		    gstring = g_string_append_c (gstring, ch);
       
  1406 		}
       
  1407 	    }
       
  1408 	  ch = 0;
       
  1409 	  break;
       
  1410 	  
       
  1411 	case '.':
       
  1412 	  if (!config->scan_float)
       
  1413 	    goto default_case;
       
  1414 	  token = G_TOKEN_FLOAT;
       
  1415 	  dotted_float = TRUE;
       
  1416 	  ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1417 	  goto number_parsing;
       
  1418 	  
       
  1419 	case '$':
       
  1420 	  if (!config->scan_hex_dollar)
       
  1421 	    goto default_case;
       
  1422 	  token = G_TOKEN_HEX;
       
  1423 	  ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1424 	  goto number_parsing;
       
  1425 	  
       
  1426 	case '0':
       
  1427 	  if (config->scan_octal)
       
  1428 	    token = G_TOKEN_OCTAL;
       
  1429 	  else
       
  1430 	    token = G_TOKEN_INT;
       
  1431 	  ch = g_scanner_peek_next_char (scanner);
       
  1432 	  if (config->scan_hex && (ch == 'x' || ch == 'X'))
       
  1433 	    {
       
  1434 	      token = G_TOKEN_HEX;
       
  1435 	      g_scanner_get_char (scanner, line_p, position_p);
       
  1436 	      ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1437 	      if (ch == 0)
       
  1438 		{
       
  1439 		  token = G_TOKEN_ERROR;
       
  1440 		  value.v_error = G_ERR_UNEXP_EOF;
       
  1441 		  (*position_p)++;
       
  1442 		  break;
       
  1443 		}
       
  1444 	      if (g_scanner_char_2_num (ch, 16) < 0)
       
  1445 		{
       
  1446 		  token = G_TOKEN_ERROR;
       
  1447 		  value.v_error = G_ERR_DIGIT_RADIX;
       
  1448 		  ch = 0;
       
  1449 		  break;
       
  1450 		}
       
  1451 	    }
       
  1452 	  else if (config->scan_binary && (ch == 'b' || ch == 'B'))
       
  1453 	    {
       
  1454 	      token = G_TOKEN_BINARY;
       
  1455 	      g_scanner_get_char (scanner, line_p, position_p);
       
  1456 	      ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1457 	      if (ch == 0)
       
  1458 		{
       
  1459 		  token = G_TOKEN_ERROR;
       
  1460 		  value.v_error = G_ERR_UNEXP_EOF;
       
  1461 		  (*position_p)++;
       
  1462 		  break;
       
  1463 		}
       
  1464 	      if (g_scanner_char_2_num (ch, 10) < 0)
       
  1465 		{
       
  1466 		  token = G_TOKEN_ERROR;
       
  1467 		  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
       
  1468 		  ch = 0;
       
  1469 		  break;
       
  1470 		}
       
  1471 	    }
       
  1472 	  else
       
  1473 	    ch = '0';
       
  1474 	  /* fall through */
       
  1475 	case '1':
       
  1476 	case '2':
       
  1477 	case '3':
       
  1478 	case '4':
       
  1479 	case '5':
       
  1480 	case '6':
       
  1481 	case '7':
       
  1482 	case '8':
       
  1483 	case '9':
       
  1484 	number_parsing:
       
  1485 	{
       
  1486           gboolean in_number = TRUE;
       
  1487 	  gchar *endptr;
       
  1488 	  
       
  1489 	  if (token == G_TOKEN_NONE)
       
  1490 	    token = G_TOKEN_INT;
       
  1491 	  
       
  1492 	  gstring = g_string_new (dotted_float ? "0." : "");
       
  1493 	  gstring = g_string_append_c (gstring, ch);
       
  1494 	  
       
  1495 	  do /* while (in_number) */
       
  1496 	    {
       
  1497 	      gboolean is_E;
       
  1498 	      
       
  1499 	      is_E = token == G_TOKEN_FLOAT && (ch == 'e' || ch == 'E');
       
  1500 	      
       
  1501 	      ch = g_scanner_peek_next_char (scanner);
       
  1502 	      
       
  1503 	      if (g_scanner_char_2_num (ch, 36) >= 0 ||
       
  1504 		  (config->scan_float && ch == '.') ||
       
  1505 		  (is_E && (ch == '+' || ch == '-')))
       
  1506 		{
       
  1507 		  ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1508 		  
       
  1509 		  switch (ch)
       
  1510 		    {
       
  1511 		    case '.':
       
  1512 		      if (token != G_TOKEN_INT && token != G_TOKEN_OCTAL)
       
  1513 			{
       
  1514 			  value.v_error = token == G_TOKEN_FLOAT ? G_ERR_FLOAT_MALFORMED : G_ERR_FLOAT_RADIX;
       
  1515 			  token = G_TOKEN_ERROR;
       
  1516 			  in_number = FALSE;
       
  1517 			}
       
  1518 		      else
       
  1519 			{
       
  1520 			  token = G_TOKEN_FLOAT;
       
  1521 			  gstring = g_string_append_c (gstring, ch);
       
  1522 			}
       
  1523 		      break;
       
  1524 		      
       
  1525 		    case '0':
       
  1526 		    case '1':
       
  1527 		    case '2':
       
  1528 		    case '3':
       
  1529 		    case '4':
       
  1530 		    case '5':
       
  1531 		    case '6':
       
  1532 		    case '7':
       
  1533 		    case '8':
       
  1534 		    case '9':
       
  1535 		      gstring = g_string_append_c (gstring, ch);
       
  1536 		      break;
       
  1537 		      
       
  1538 		    case '-':
       
  1539 		    case '+':
       
  1540 		      if (token != G_TOKEN_FLOAT)
       
  1541 			{
       
  1542 			  token = G_TOKEN_ERROR;
       
  1543 			  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
       
  1544 			  in_number = FALSE;
       
  1545 			}
       
  1546 		      else
       
  1547 			gstring = g_string_append_c (gstring, ch);
       
  1548 		      break;
       
  1549 		      
       
  1550 		    case 'e':
       
  1551 		    case 'E':
       
  1552 		      if ((token != G_TOKEN_HEX && !config->scan_float) ||
       
  1553 			  (token != G_TOKEN_HEX &&
       
  1554 			   token != G_TOKEN_OCTAL &&
       
  1555 			   token != G_TOKEN_FLOAT &&
       
  1556 			   token != G_TOKEN_INT))
       
  1557 			{
       
  1558 			  token = G_TOKEN_ERROR;
       
  1559 			  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
       
  1560 			  in_number = FALSE;
       
  1561 			}
       
  1562 		      else
       
  1563 			{
       
  1564 			  if (token != G_TOKEN_HEX)
       
  1565 			    token = G_TOKEN_FLOAT;
       
  1566 			  gstring = g_string_append_c (gstring, ch);
       
  1567 			}
       
  1568 		      break;
       
  1569 		      
       
  1570 		    default:
       
  1571 		      if (token != G_TOKEN_HEX)
       
  1572 			{
       
  1573 			  token = G_TOKEN_ERROR;
       
  1574 			  value.v_error = G_ERR_NON_DIGIT_IN_CONST;
       
  1575 			  in_number = FALSE;
       
  1576 			}
       
  1577 		      else
       
  1578 			gstring = g_string_append_c (gstring, ch);
       
  1579 		      break;
       
  1580 		    }
       
  1581 		}
       
  1582 	      else
       
  1583 		in_number = FALSE;
       
  1584 	    }
       
  1585 	  while (in_number);
       
  1586 	  
       
  1587 	  endptr = NULL;
       
  1588 	  if (token == G_TOKEN_FLOAT)
       
  1589 	    value.v_float = g_strtod (gstring->str, &endptr);
       
  1590 	  else
       
  1591 	    {
       
  1592 	      guint64 ui64 = 0;
       
  1593 	      switch (token)
       
  1594 		{
       
  1595 		case G_TOKEN_BINARY:
       
  1596 		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 2);
       
  1597 		  break;
       
  1598 		case G_TOKEN_OCTAL:
       
  1599 		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 8);
       
  1600 		  break;
       
  1601 		case G_TOKEN_INT:
       
  1602 		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 10);
       
  1603 		  break;
       
  1604 		case G_TOKEN_HEX:
       
  1605 		  ui64 = g_ascii_strtoull (gstring->str, &endptr, 16);
       
  1606 		  break;
       
  1607 		default: ;
       
  1608 		}
       
  1609 	      if (scanner->config->store_int64)
       
  1610 		value.v_int64 = ui64;
       
  1611 	      else
       
  1612 		value.v_int = ui64;
       
  1613 	    }
       
  1614 	  if (endptr && *endptr)
       
  1615 	    {
       
  1616 	      token = G_TOKEN_ERROR;
       
  1617 	      if (*endptr == 'e' || *endptr == 'E')
       
  1618 		value.v_error = G_ERR_NON_DIGIT_IN_CONST;
       
  1619 	      else
       
  1620 		value.v_error = G_ERR_DIGIT_RADIX;
       
  1621 	    }
       
  1622 	  g_string_free (gstring, TRUE);
       
  1623 	  gstring = NULL;
       
  1624 	  ch = 0;
       
  1625 	} /* number_parsing:... */
       
  1626 	break;
       
  1627 	
       
  1628 	default:
       
  1629 	default_case:
       
  1630 	{
       
  1631 	  if (config->cpair_comment_single &&
       
  1632 	      ch == config->cpair_comment_single[0])
       
  1633 	    {
       
  1634 	      token = G_TOKEN_COMMENT_SINGLE;
       
  1635 	      in_comment_single = TRUE;
       
  1636 	      gstring = g_string_new (NULL);
       
  1637 	      ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1638 	      while (ch != 0)
       
  1639 		{
       
  1640 		  if (ch == config->cpair_comment_single[1])
       
  1641 		    {
       
  1642 		      in_comment_single = FALSE;
       
  1643 		      ch = 0;
       
  1644 		      break;
       
  1645 		    }
       
  1646 		  
       
  1647 		  gstring = g_string_append_c (gstring, ch);
       
  1648 		  ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1649 		}
       
  1650 	      /* ignore a missing newline at EOF for single line comments */
       
  1651 	      if (in_comment_single &&
       
  1652 		  config->cpair_comment_single[1] == '\n')
       
  1653 		in_comment_single = FALSE;
       
  1654 	    }
       
  1655 	  else if (config->scan_identifier && ch &&
       
  1656 		   strchr (config->cset_identifier_first, ch))
       
  1657 	    {
       
  1658 	    identifier_precedence:
       
  1659 	      
       
  1660 	      if (config->cset_identifier_nth && ch &&
       
  1661 		  strchr (config->cset_identifier_nth,
       
  1662 			  g_scanner_peek_next_char (scanner)))
       
  1663 		{
       
  1664 		  token = G_TOKEN_IDENTIFIER;
       
  1665 		  gstring = g_string_new (NULL);
       
  1666 		  gstring = g_string_append_c (gstring, ch);
       
  1667 		  do
       
  1668 		    {
       
  1669 		      ch = g_scanner_get_char (scanner, line_p, position_p);
       
  1670 		      gstring = g_string_append_c (gstring, ch);
       
  1671 		      ch = g_scanner_peek_next_char (scanner);
       
  1672 		    }
       
  1673 		  while (ch && strchr (config->cset_identifier_nth, ch));
       
  1674 		  ch = 0;
       
  1675 		}
       
  1676 	      else if (config->scan_identifier_1char)
       
  1677 		{
       
  1678 		  token = G_TOKEN_IDENTIFIER;
       
  1679 		  value.v_identifier = g_new0 (gchar, 2);
       
  1680 		  value.v_identifier[0] = ch;
       
  1681 		  ch = 0;
       
  1682 		}
       
  1683 	    }
       
  1684 	  if (ch)
       
  1685 	    {
       
  1686 	      if (config->char_2_token)
       
  1687 		token = ch;
       
  1688 	      else
       
  1689 		{
       
  1690 		  token = G_TOKEN_CHAR;
       
  1691 		  value.v_char = ch;
       
  1692 		}
       
  1693 	      ch = 0;
       
  1694 	    }
       
  1695 	} /* default_case:... */
       
  1696 	break;
       
  1697 	}
       
  1698       g_assert (ch == 0 && token != G_TOKEN_NONE); /* paranoid */
       
  1699     }
       
  1700   while (ch != 0);
       
  1701   
       
  1702   if (in_comment_multi || in_comment_single ||
       
  1703       in_string_sq || in_string_dq)
       
  1704     {
       
  1705       token = G_TOKEN_ERROR;
       
  1706       if (gstring)
       
  1707 	{
       
  1708 	  g_string_free (gstring, TRUE);
       
  1709 	  gstring = NULL;
       
  1710 	}
       
  1711       (*position_p)++;
       
  1712       if (in_comment_multi || in_comment_single)
       
  1713 	value.v_error = G_ERR_UNEXP_EOF_IN_COMMENT;
       
  1714       else /* (in_string_sq || in_string_dq) */
       
  1715 	value.v_error = G_ERR_UNEXP_EOF_IN_STRING;
       
  1716     }
       
  1717   
       
  1718   if (gstring)
       
  1719     {
       
  1720       value.v_string = gstring->str;
       
  1721       g_string_free (gstring, FALSE);
       
  1722       gstring = NULL;
       
  1723     }
       
  1724   
       
  1725   if (token == G_TOKEN_IDENTIFIER)
       
  1726     {
       
  1727       if (config->scan_symbols)
       
  1728 	{
       
  1729 	  GScannerKey *key;
       
  1730 	  guint scope_id;
       
  1731 	  
       
  1732 	  scope_id = scanner->scope_id;
       
  1733 	  key = g_scanner_lookup_internal (scanner, scope_id, value.v_identifier);
       
  1734 	  if (!key && scope_id && scanner->config->scope_0_fallback)
       
  1735 	    key = g_scanner_lookup_internal (scanner, 0, value.v_identifier);
       
  1736 	  
       
  1737 	  if (key)
       
  1738 	    {
       
  1739 	      g_free (value.v_identifier);
       
  1740 	      token = G_TOKEN_SYMBOL;
       
  1741 	      value.v_symbol = key->value;
       
  1742 	    }
       
  1743 	}
       
  1744       
       
  1745       if (token == G_TOKEN_IDENTIFIER &&
       
  1746 	  config->scan_identifier_NULL &&
       
  1747 	  strlen (value.v_identifier) == 4)
       
  1748 	{
       
  1749 	  gchar *null_upper = "NULL";
       
  1750 	  gchar *null_lower = "null";
       
  1751 	  
       
  1752 	  if (scanner->config->case_sensitive)
       
  1753 	    {
       
  1754 	      if (value.v_identifier[0] == null_upper[0] &&
       
  1755 		  value.v_identifier[1] == null_upper[1] &&
       
  1756 		  value.v_identifier[2] == null_upper[2] &&
       
  1757 		  value.v_identifier[3] == null_upper[3])
       
  1758 		token = G_TOKEN_IDENTIFIER_NULL;
       
  1759 	    }
       
  1760 	  else
       
  1761 	    {
       
  1762 	      if ((value.v_identifier[0] == null_upper[0] ||
       
  1763 		   value.v_identifier[0] == null_lower[0]) &&
       
  1764 		  (value.v_identifier[1] == null_upper[1] ||
       
  1765 		   value.v_identifier[1] == null_lower[1]) &&
       
  1766 		  (value.v_identifier[2] == null_upper[2] ||
       
  1767 		   value.v_identifier[2] == null_lower[2]) &&
       
  1768 		  (value.v_identifier[3] == null_upper[3] ||
       
  1769 		   value.v_identifier[3] == null_lower[3]))
       
  1770 		token = G_TOKEN_IDENTIFIER_NULL;
       
  1771 	    }
       
  1772 	}
       
  1773     }
       
  1774   
       
  1775   *token_p = token;
       
  1776   *value_p = value;
       
  1777 }
       
  1778 
       
  1779 #define __G_SCANNER_C__
       
  1780 #include "galiasdef.c"