home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
octave-1.1.1p1-src.tgz
/
tar.out
/
fsf
/
octave
/
src
/
lex.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
81KB
|
3,440 lines
/* A lexical scanner generated by flex */
/* Scanner skeleton version:
* $Header: flex.skl,v 1.2 94/01/04 14:33:15 vern Exp $
*/
#define FLEX_SCANNER
#include <stdio.h>
/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
#ifdef c_plusplus
#ifndef __cplusplus
#define __cplusplus
#endif
#endif
#ifdef __cplusplus
#include <stdlib.h>
#include <unistd.h>
/* Use prototypes in function declarations. */
#define YY_USE_PROTOS
/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST
#else /* ! __cplusplus */
#ifdef __STDC__
#define YY_USE_PROTOS
#define YY_USE_CONST
#endif /* __STDC__ */
#endif /* ! __cplusplus */
#ifdef __TURBOC__
#define YY_USE_CONST
#endif
#ifndef YY_USE_CONST
#ifndef const
#define const
#endif
#endif
#ifdef YY_USE_PROTOS
#define YY_PROTO(proto) proto
#else
#define YY_PROTO(proto) ()
#endif
/* Returned upon end-of-file. */
#define YY_NULL 0
/* Promotes a possibly negative, possibly signed char to an unsigned
* integer for use as an array index. If the signed char is negative,
* we want to instead treat it as an 8-bit unsigned char, hence the
* double cast.
*/
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
/* Enter a start condition. This macro really ought to take a parameter,
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
*/
#define BEGIN yy_start = 1 + 2 *
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state.
*/
#define YY_START ((yy_start - 1) / 2)
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
/* Special action meaning "start processing a new file". Now included
* only for backward compatibility with previous versions of flex.
*/
#define YY_NEW_FILE yyrestart( yyin )
#define YY_END_OF_BUFFER_CHAR 0
/* Size of default input buffer. */
#define YY_BUF_SIZE 16384
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern int yyleng;
extern FILE *yyin, *yyout;
#ifdef __cplusplus
extern "C" {
#endif
extern int yywrap YY_PROTO(( void ));
#ifdef __cplusplus
}
#endif
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
/* The funky do-while in the following #define is used to turn the definition
* int a single C statement (which needs a semi-colon terminator). This
* avoids problems with code like:
*
* if ( condition_holds )
* yyless( 5 );
* else
* do_something_else();
*
* Prior to using the do-while the compiler would get upset at the
* "else" because it interpreted the "if" statement as being all
* done when it reached the ';' after the yyless() call.
*/
/* Return all but the first 'n' matched characters back to the input stream. */
#define yyless(n) \
do \
{ \
/* Undo effects of setting up yytext. */ \
*yy_cp = yy_hold_char; \
yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
#define unput(c) yyunput( c, yytext_ptr )
struct yy_buffer_state
{
FILE *yy_input_file;
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
int yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
int yy_n_chars;
/* Whether this is an "interactive" input source; if so, and
* if we're using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
/* Whether we've seen an EOF on this buffer. */
int yy_eof_status;
#define EOF_NOT_SEEN 0
/* "Pending" happens when the EOF has been seen but there's still
* some text to process. Note that when we actually see the EOF,
* we switch the status back to "not seen" (via yyrestart()), so
* that the user can continue scanning by just pointing yyin at
* a new input file.
*/
#define EOF_PENDING 1
};
static YY_BUFFER_STATE yy_current_buffer = 0;
/* We provide macros for accessing buffer states in case in the
* future we want to put the buffer states in a more general
* "scanner state".
*/
#define YY_CURRENT_BUFFER yy_current_buffer
/* yy_hold_char holds the character lost when yytext is formed. */
static char yy_hold_char;
static int yy_n_chars; /* number of characters read into yy_ch_buf */
int yyleng;
/* Points to current character in buffer. */
static char *yy_c_buf_p = (char *) 0;
static int yy_init = 1; /* whether we need to initialize */
static int yy_start = 0; /* start state number */
/* Flag which is used to allow yywrap()'s to do buffer switches
* instead of setting up a fresh yyin. A bit of a hack ...
*/
static int yy_did_buffer_switch_on_eof;
static void yyunput YY_PROTO(( int c, char *buf_ptr ));
void yyrestart YY_PROTO(( FILE *input_file ));
void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
void yy_load_buffer_state YY_PROTO(( void ));
YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
static int yy_start_stack_ptr = 0;
static int yy_start_stack_depth = 0;
static int *yy_start_stack = 0;
static void yy_push_state YY_PROTO(( int new_state ));
static void yy_pop_state YY_PROTO(( void ));
static int yy_top_state YY_PROTO(( void ));
#ifndef yytext_ptr
static void yy_flex_strcpy YY_PROTO(( char *, const char * ));
#endif
static void *yy_flex_alloc YY_PROTO(( unsigned int ));
static void *yy_flex_realloc YY_PROTO(( void *ptr, unsigned int ));
static void yy_flex_free YY_PROTO(( void * ));
#define yy_new_buffer yy_create_buffer
#define INITIAL 0
#define HELP_FCN 1
#define TEXT_FCN 2
#define MATRIX 3
typedef unsigned char YY_CHAR;
typedef int yy_state_type;
FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
extern char *yytext;
#define yytext_ptr yytext
#ifdef __cplusplus
static int yyinput YY_PROTO(( void ));
#else
static int input YY_PROTO(( void ));
#endif
static yy_state_type yy_get_previous_state YY_PROTO(( void ));
static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
static int yy_get_next_buffer YY_PROTO(( void ));
static void yy_fatal_error YY_PROTO(( const char msg[] ));
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
*/
#define YY_DO_BEFORE_ACTION \
yytext_ptr = yy_bp; \
yyleng = yy_cp - yy_bp; \
yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yy_c_buf_p = yy_cp;
#define YY_END_OF_BUFFER 58
static const short int yy_accept[179] =
{ 0,
17, 17, 5, 5, 6, 6, 17, 17, 58, 56,
17, 22, 51, 24, 26, 39, 23, 54, 55, 42,
52, 46, 53, 56, 43, 16, 25, 45, 40, 48,
41, 21, 12, 44, 13, 47, 38, 51, 5, 5,
1, 6, 6, 2, 6, 4, 6, 6, 4, 6,
6, 6, 6, 3, 6, 6, 6, 6, 6, 3,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
9, 11, 26, 8, 10, 7, 17, 36, 50, 47,
32, 33, 31, 27, 52, 53, 0, 28, 16, 29,
30, 16, 16, 0, 14, 34, 35, 37, 21, 21,
12, 0, 18, 0, 49, 5, 5, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 9, 11, 0,
8, 10, 7, 11, 11, 0, 0, 0, 8, 10,
0, 7, 20, 0, 15, 16, 0, 16, 0, 19,
6, 6, 6, 6, 6, 6, 6, 6, 0, 11,
11, 0, 0, 16, 6, 6, 11, 0
} ;
static const int yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 4, 5, 6, 1, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 18, 19, 20,
21, 22, 1, 1, 23, 23, 23, 24, 24, 23,
23, 23, 25, 25, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
26, 27, 28, 29, 23, 1, 23, 23, 23, 24,
24, 23, 23, 23, 25, 25, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 1, 30, 1, 31, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1
} ;
static const int yy_meta[32] =
{ 0,
1, 2, 3, 1, 1, 1, 1, 4, 1, 1,
4, 1, 5, 1, 1, 4, 6, 1, 5, 1,
1, 1, 2, 6, 6, 1, 4, 1, 4, 1,
1
} ;
static const short int yy_base[189] =
{ 0,
0, 0, 30, 32, 35, 0, 65, 92, 341, 405,
337, 405, 317, 405, 405, 330, 405, 405, 405, 325,
323, 405, 320, 113, 405, 55, 405, 405, 52, 312,
311, 329, 328, 79, 405, 405, 299, 307, 325, 324,
405, 320, 319, 405, 67, 318, 317, 84, 316, 315,
313, 81, 75, 405, 87, 141, 311, 169, 310, 405,
88, 94, 95, 193, 309, 97, 308, 307, 74, 105,
217, 244, 305, 305, 111, 304, 303, 405, 405, 405,
405, 405, 405, 293, 405, 405, 288, 405, 114, 405,
405, 120, 148, 134, 405, 405, 405, 405, 300, 297,
295, 116, 405, 291, 405, 291, 290, 289, 288, 287,
284, 283, 282, 281, 279, 278, 121, 275, 274, 132,
272, 152, 269, 266, 271, 299, 173, 265, 264, 263,
262, 259, 323, 258, 158, 178, 247, 0, 0, 230,
211, 176, 207, 0, 0, 200, 193, 186, 181, 196,
171, 160, 198, 194, 405, 142, 119, 116, 109, 405,
219, 212, 106, 210, 133, 226, 229, 235, 103, 238,
250, 99, 58, 190, 237, 253, 256, 405, 348, 353,
359, 365, 371, 374, 380, 386, 392, 398
} ;
static const short int yy_def[189] =
{ 0,
178, 1, 179, 179, 178, 5, 1, 1, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
178, 180, 178, 178, 178, 178, 178, 178, 181, 178,
178, 182, 178, 178, 182, 182, 182, 182, 182, 182,
182, 182, 182, 178, 182, 182, 182, 182, 182, 178,
182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
178, 178, 183, 178, 178, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
178, 184, 178, 178, 178, 178, 178, 178, 178, 180,
178, 178, 178, 185, 178, 181, 178, 182, 178, 178,
182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
182, 178, 182, 178, 178, 186, 182, 71, 72, 183,
178, 178, 178, 72, 72, 187, 183, 178, 178, 178,
188, 178, 178, 178, 178, 178, 178, 178, 185, 178,
182, 182, 182, 182, 182, 182, 186, 185, 187, 178,
178, 188, 178, 178, 182, 182, 178, 0, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178
} ;
static const short int yy_nxt[437] =
{ 0,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 32, 32, 33, 34, 35, 36, 37,
38, 40, 41, 40, 41, 42, 43, 44, 45, 46,
47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64, 64, 64,
65, 66, 67, 68, 69, 70, 71, 72, 109, 92,
73, 93, 96, 78, 174, 109, 109, 74, 94, 95,
102, 103, 109, 75, 104, 109, 114, 111, 109, 109,
112, 113, 76, 71, 72, 109, 109, 73, 135, 103,
115, 150, 136, 137, 74, 170, 109, 109, 129, 111,
75, 160, 150, 150, 130, 131, 151, 102, 103, 76,
83, 104, 109, 84, 85, 111, 86, 87, 88, 89,
89, 124, 158, 109, 109, 158, 156, 154, 95, 90,
95, 91, 109, 94, 95, 157, 161, 157, 116, 166,
158, 117, 118, 109, 119, 120, 121, 122, 156, 135,
103, 152, 92, 104, 93, 94, 95, 123, 122, 124,
109, 94, 95, 150, 109, 162, 128, 150, 150, 168,
160, 151, 149, 125, 165, 126, 165, 148, 171, 166,
159, 140, 127, 128, 132, 148, 159, 150, 150, 102,
103, 151, 170, 104, 142, 173, 174, 173, 152, 133,
174, 109, 149, 109, 95, 133, 133, 133, 138, 139,
135, 103, 140, 175, 136, 175, 164, 109, 176, 141,
168, 160, 148, 127, 128, 142, 168, 160, 109, 170,
177, 159, 166, 146, 143, 144, 145, 159, 109, 146,
128, 170, 177, 176, 109, 146, 142, 170, 177, 134,
132, 146, 142, 109, 109, 109, 109, 109, 142, 176,
109, 143, 109, 109, 142, 109, 109, 128, 163, 109,
109, 163, 109, 109, 109, 109, 163, 164, 110, 109,
109, 107, 107, 160, 127, 128, 101, 163, 99, 163,
109, 99, 153, 91, 77, 152, 149, 148, 109, 109,
134, 109, 109, 125, 109, 126, 109, 109, 109, 109,
110, 109, 127, 128, 132, 107, 107, 78, 105, 101,
99, 98, 97, 82, 81, 80, 79, 78, 77, 133,
178, 178, 178, 178, 178, 133, 133, 133, 39, 39,
39, 39, 39, 39, 100, 178, 178, 178, 100, 106,
106, 178, 106, 106, 106, 108, 108, 178, 108, 178,
108, 147, 147, 147, 147, 147, 147, 155, 178, 155,
159, 159, 159, 159, 159, 159, 167, 167, 167, 167,
167, 167, 169, 169, 169, 169, 169, 169, 172, 172,
172, 172, 172, 172, 9, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178
} ;
static const short int yy_chk[437] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 3, 3, 4, 4, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 7, 7, 45, 26,
7, 26, 29, 29, 173, 69, 53, 7, 26, 26,
34, 34, 52, 7, 34, 48, 53, 45, 55, 61,
48, 52, 7, 8, 8, 62, 63, 8, 66, 66,
55, 172, 66, 69, 8, 169, 70, 163, 61, 61,
8, 159, 75, 75, 62, 63, 75, 102, 102, 8,
24, 102, 117, 24, 24, 70, 24, 24, 24, 24,
89, 117, 158, 120, 165, 157, 92, 89, 89, 24,
158, 24, 56, 92, 92, 94, 120, 94, 56, 165,
94, 56, 56, 122, 56, 56, 56, 56, 156, 135,
135, 152, 93, 135, 93, 156, 156, 56, 122, 56,
58, 93, 93, 151, 127, 122, 122, 142, 142, 136,
136, 142, 149, 58, 127, 58, 127, 148, 148, 127,
136, 148, 58, 58, 64, 147, 136, 150, 150, 153,
153, 150, 146, 153, 148, 154, 174, 154, 143, 64,
154, 164, 141, 162, 174, 64, 64, 64, 71, 71,
161, 161, 71, 162, 161, 162, 164, 166, 162, 71,
167, 167, 140, 164, 164, 71, 168, 168, 175, 170,
170, 167, 166, 170, 71, 72, 72, 167, 137, 72,
166, 171, 171, 175, 176, 171, 170, 177, 177, 134,
132, 177, 72, 131, 130, 129, 128, 124, 171, 176,
123, 72, 125, 121, 177, 119, 118, 176, 125, 116,
115, 125, 114, 113, 112, 111, 125, 125, 110, 109,
108, 107, 106, 104, 125, 125, 101, 125, 100, 125,
126, 99, 87, 84, 77, 76, 74, 73, 68, 67,
65, 59, 57, 126, 51, 126, 50, 49, 47, 46,
43, 42, 126, 126, 133, 40, 39, 38, 37, 33,
32, 31, 30, 23, 21, 20, 16, 13, 11, 133,
9, 0, 0, 0, 0, 133, 133, 133, 179, 179,
179, 179, 179, 179, 180, 0, 0, 0, 180, 181,
181, 0, 181, 181, 181, 182, 182, 0, 182, 0,
182, 183, 183, 183, 183, 183, 183, 184, 0, 184,
185, 185, 185, 185, 185, 185, 186, 186, 186, 186,
186, 186, 187, 187, 187, 187, 187, 187, 188, 188,
188, 188, 188, 188, 178, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
178, 178, 178, 178, 178, 178
} ;
static yy_state_type yy_last_accepting_state;
static char *yy_last_accepting_cpos;
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
*/
#define REJECT reject_used_but_not_detected
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
char *yytext;
# line 1 "lex.l"
/* lex.l -*- C++ -*-
Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
This file is part of Octave.
Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to the Free
Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
# line 28 "lex.l"
#define SHORT_CIRCUIT_LOGICALS 1
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <strstream.h>
#include <ctype.h>
#include <string.h>
#include "input.h"
#include "token.h"
#include "SLStack.h"
// Stack to hold tokens so that we can delete them when the parser is
// reset and avoid growing forever just because we are stashing some
// information. This has to appear before lex.h is included, because
// one of the macros defined there uses token_stack.
static SLStack <token*> token_stack;
#include "user-prefs.h"
#include "variables.h"
#include "octave.h"
#include "symtab.h"
#include "error.h"
#include "utils.h"
#include "tree-base.h"
#include "tree-expr.h"
#include "tree-cmd.h"
#include "tree-misc.h"
#include "tree-plot.h"
#include "tree-const.h"
#include "y.tab.h"
#include "parse.h"
#include "lex.h"
// Nonzero means we think we are looking at a set command.
static int doing_set = 0;
// GAG. Stupid kludge so that [[1,2][3,4]] will work.
static do_comma_insert = 0;
// Brace level count.
static int braceflag = 0;
// Return transpose or start a string?
int quote_is_transpose = 0;
// Nonzero means we thing we are looking at the beginning of a
// function definition.
int beginning_of_function = 0;
// Nonzero means that we should convert spaces to a comma inside a
// matrix definition.
static int convert_spaces_to_comma = 1;
// Another context hack, this time for the plot command's `using',
// `title', and `with' keywords.
static int cant_be_identifier = 0;
#define BRACE 1
#define PAREN 2
// Did eat_whitespace() eat a space or tab, or a newline, or both?
#define ATE_SPACE_OR_TAB 1
#define ATE_NEWLINE 2
// Is the closest nesting level a square brace or a paren?
//
// BRACE -> spaces are important (they can turn into commas)
// new lines are important (they can turn into semicolons)
//
// PAREN -> spaces and new lines are not important
static SLStack <int> nesting_level;
// Forward declarations for functions defined at the bottom of this
// file.
static void do_string_escapes (char *s);
static void fixup_column_count (char *s);
static void do_comma_insert_check (void);
static int is_plot_keyword (char *s);
static int is_keyword (char *s);
static char *plot_style_token (char *s);
static symbol_record *lookup_identifier (char *s);
static void grab_help_text (void);
static int match_any (char c, char *s);
static int next_token_is_bin_op (int spc_prev, char *yytext);
static int next_token_is_postfix_unary_op (int spc_prev, char *yytext);
static char *strip_trailing_whitespace (char *s);
static void handle_number (char *yytext);
static int handle_string (char delim, int text_style = 0);
static int handle_close_brace (int spc_gobbled);
static int handle_identifier (char *tok, int spc_gobbled);
static int have_continuation (int trailing_comments_ok = 1);
static int have_ellipsis_continuation (int trailing_comments_ok = 1);
static int eat_whitespace (void);
static int eat_continuation (void);
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
#ifdef YY_MALLOC_DECL
YY_MALLOC_DECL
#else
#if __STDC__
#ifndef __cplusplus
#include <stdlib.h>
#endif
#else
/* Just try to get by without declaring the routines. This will fail
* miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
* or sizeof(void*) != sizeof(int).
*/
#endif
#endif
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#define YY_READ_BUF_SIZE 8192
#endif
/* Copy whatever the last rule matched to the standard output. */
#ifndef ECHO
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
* is returned in "result".
*/
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
if ( yy_current_buffer->yy_is_interactive ) \
{ \
int c = getc( yyin ); \
result = c == EOF ? 0 : 1; \
buf[0] = (char) c; \
} \
else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
&& ferror( yyin ) ) \
YY_FATAL_ERROR( "input in flex scanner failed" );
#endif
/* No semi-colon after return; correct usage is to write "yyterminate();" -
* we don't want an extra ';' after the "return" because that will cause
* some compilers to complain about unreachable statements.
*/
#ifndef yyterminate
#define yyterminate() return YY_NULL
#endif
/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif
/* Report a fatal error. */
#ifndef YY_FATAL_ERROR
#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
#endif
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL int yylex YY_PROTO(( void ))
#endif
/* Code executed at the beginning of each rule, after yytext and yyleng
* have been set up.
*/
#ifndef YY_USER_ACTION
#define YY_USER_ACTION
#endif
/* Code executed at the end of each rule. */
#ifndef YY_BREAK
#define YY_BREAK break;
#endif
YY_DECL
{
register yy_state_type yy_current_state;
register char *yy_cp, *yy_bp;
register int yy_act;
# line 151 "lex.l"
// Help and other text-style functions are a pain in the ass. This
// stuff needs to be simplified. May require some changes in the
// parser too.
if ( yy_init )
{
#ifdef YY_USER_INIT
YY_USER_INIT;
#endif
if ( ! yy_start )
yy_start = 1; /* first start state */
if ( ! yyin )
yyin = stdin;
if ( ! yyout )
yyout = stdout;
if ( yy_current_buffer )
yy_init_buffer( yy_current_buffer, yyin );
else
yy_current_buffer =
yy_create_buffer( yyin, YY_BUF_SIZE );
yy_load_buffer_state();
yy_init = 0;
}
while ( 1 ) /* loops until end-of-file is reached */
{
yy_cp = yy_c_buf_p;
/* Support of yytext. */
*yy_cp = yy_hold_char;
/* yy_bp points to the position in yy_ch_buf of the start of
* the current run.
*/
yy_bp = yy_cp;
yy_current_state = yy_start;
yy_match:
do
{
register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
yy_last_accepting_state = yy_current_state;
yy_last_accepting_cpos = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 179 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 405 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
YY_DO_BEFORE_ACTION;
do_action: /* This label is used only to access EOF actions. */
switch ( yy_act )
{ /* beginning of action switch */
case 0: /* must back up */
/* undo the effects of YY_DO_BEFORE_ACTION */
*yy_cp = yy_hold_char;
yy_cp = yy_last_accepting_cpos;
yy_current_state = yy_last_accepting_state;
goto yy_find_action;
case 1:
YY_USER_ACTION
# line 160 "lex.l"
case 2:
YY_USER_ACTION
# line 160 "lex.l"
{
BEGIN 0;
current_input_column = 1;
quote_is_transpose = 0;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
return '\n';
}
YY_BREAK
case 3:
YY_USER_ACTION
# line 169 "lex.l"
{
if (doing_set && strcmp (yytext, ",") == 0)
{
TOK_PUSH_AND_RETURN (yytext, TEXT);
}
else
{
BEGIN 0;
if (strcmp (yytext, ",") == 0)
TOK_RETURN (',');
else
TOK_RETURN (';');
}
}
YY_BREAK
case 4:
YY_USER_ACTION
# line 184 "lex.l"
{
current_input_column++;
return handle_string (yytext[0], 1);
}
YY_BREAK
case 5:
YY_USER_ACTION
# line 190 "lex.l"
case 6:
YY_USER_ACTION
# line 190 "lex.l"
{
static char *tok = 0;
delete [] tok;
tok = strip_trailing_whitespace (yytext);
TOK_PUSH_AND_RETURN (tok, TEXT);
}
YY_BREAK
// For this and the next two rules, we're looking at ']', and we
// need to know if the next token is `=' or `=='.
//
// It would have been so much easier if the delimiters were simply
// different for the expression on the left hand side of the equals
// operator.
//
// It's also a pain in the ass to decide whether to insert a comma
// after seeing a ']' character...
case 7:
YY_USER_ACTION
# line 209 "lex.l"
{
fixup_column_count (yytext);
int c = yytext[yyleng-1];
int cont_is_spc = eat_continuation ();
int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
return handle_close_brace (spc_gobbled);
}
YY_BREAK
// Commas are element separators in matrix constants. If we don't
// check for continuations here we can end up inserting too many
// commas.
case 8:
YY_USER_ACTION
# line 223 "lex.l"
{
current_input_column += yyleng;
int tmp = eat_continuation ();
quote_is_transpose = 0;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
if (user_pref.whitespace_in_literal_matrix != 2
&& (tmp & ATE_NEWLINE) == ATE_NEWLINE)
unput (';');
return (',');
}
YY_BREAK
// In some cases, spaces in matrix constants can turn into commas.
// If commas are required, spaces are not important in matrix
// constants so we just eat them. If we don't check for continuations
// here we can end up inserting too many commas.
case 9:
YY_USER_ACTION
# line 242 "lex.l"
{
current_input_column += yyleng;
if (user_pref.whitespace_in_literal_matrix != 2)
{
int tmp = eat_continuation ();
int bin_op = next_token_is_bin_op (1, yytext);
int postfix_un_op = next_token_is_postfix_unary_op (1, yytext);
if (! (postfix_un_op || bin_op || nesting_level.empty ())
&& nesting_level.top () == BRACE
&& convert_spaces_to_comma)
{
quote_is_transpose = 0;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
if ((tmp & ATE_NEWLINE) == ATE_NEWLINE)
unput (';');
return (',');
}
}
}
YY_BREAK
// Semicolons are handled as row seprators in matrix constants. If we
// don't eat whitespace here we can end up inserting too many
// semicolons.
case 10:
YY_USER_ACTION
# line 270 "lex.l"
{
fixup_column_count (yytext);
eat_whitespace ();
quote_is_transpose = 0;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
return ';';
}
YY_BREAK
// In some cases, new lines can also become row separators. If we
// don't eat whitespace here we can end up inserting too many
// semicolons.
case 11:
YY_USER_ACTION
# line 285 "lex.l"
{
fixup_column_count (yytext);
eat_whitespace ();
if (user_pref.whitespace_in_literal_matrix != 2)
{
quote_is_transpose = 0;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
if (nesting_level.empty ())
return LEXICAL_ERROR;
if (nesting_level.top () == BRACE)
return ';';
}
}
YY_BREAK
// Open and close brace are handled differently if we are in the range
// part of a plot command.
//
case 12:
YY_USER_ACTION
# line 308 "lex.l"
{
nesting_level.push (BRACE);
current_input_column += yyleng;
quote_is_transpose = 0;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
promptflag--;
eat_whitespace ();
if (plotting && ! past_plot_range)
{
in_plot_range = 1;
return OPEN_BRACE;
}
else
{
mlnm.push (1);
braceflag++;
BEGIN MATRIX;
return '[';
}
}
YY_BREAK
case 13:
YY_USER_ACTION
# line 333 "lex.l"
{
if (! nesting_level.empty ())
nesting_level.pop ();
if (plotting && ! past_plot_range)
{
in_plot_range = 0;
TOK_RETURN (CLOSE_BRACE);
}
else
TOK_RETURN (']');
}
YY_BREAK
// Imaginary numbers.
case 14:
YY_USER_ACTION
# line 350 "lex.l"
{
handle_number (yytext);
return IMAG_NUM;
}
YY_BREAK
// Real numbers. Don't grab the `.' part of a dot operator as part of
// the constant.
case 15:
*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
yy_c_buf_p = yy_cp -= 2;
YY_DO_BEFORE_ACTION; /* set up yytext again */
YY_USER_ACTION
# line 361 "lex.l"
case 16:
YY_USER_ACTION
# line 361 "lex.l"
{
handle_number (yytext);
return NUM;
}
YY_BREAK
// Eat whitespace. Whitespace inside matrix constants is handled by
// the <MATRIX> start state code above.
case 17:
YY_USER_ACTION
# line 371 "lex.l"
{
current_input_column += yyleng;
}
YY_BREAK
// Continuation lines. Allow comments after continuations.
case 18:
YY_USER_ACTION
# line 380 "lex.l"
case 19:
YY_USER_ACTION
# line 380 "lex.l"
{
promptflag--;
current_input_column = 1;
}
YY_BREAK
// An ellipsis not at the end of a line is not a continuation, but
// does have another meaning.
case 20:
YY_USER_ACTION
# line 390 "lex.l"
{
return ELLIPSIS;
}
YY_BREAK
// End of file.
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(HELP_FCN):
case YY_STATE_EOF(TEXT_FCN):
case YY_STATE_EOF(MATRIX):
# line 398 "lex.l"
{
TOK_RETURN (END_OF_INPUT);
}
YY_BREAK
// Identifiers. Truncate the token at the first space or tab but
// don't write directly on yytext.
case 21:
YY_USER_ACTION
# line 407 "lex.l"
{
static char *tok = 0;
delete [] tok;
tok = strip_trailing_whitespace (yytext);
int c = yytext[yyleng-1];
int cont_is_spc = eat_continuation ();
int spc_gobbled = (cont_is_spc || c == ' ' || c == '\t');
return handle_identifier (tok, spc_gobbled);
}
YY_BREAK
// A new line character. New line characters inside matrix constants
// are handled by the <MATRIX> start state code above. If closest
// nesting is inside parentheses, don't return a row separator.
case 22:
YY_USER_ACTION
# line 423 "lex.l"
{
quote_is_transpose = 0;
cant_be_identifier = 0;
current_input_column = 1;
convert_spaces_to_comma = 1;
if (nesting_level.empty ())
return '\n';
if (nesting_level.top () == BRACE)
return LEXICAL_ERROR;
}
YY_BREAK
// Single quote can either be the beginning of a string or a transpose
// operator.
case 23:
YY_USER_ACTION
# line 441 "lex.l"
{
current_input_column++;
convert_spaces_to_comma = 1;
if (quote_is_transpose)
{
do_comma_insert_check ();
return QUOTE;
}
else
return handle_string ('\'');
}
YY_BREAK
// Double quotes always begin strings.
case 24:
YY_USER_ACTION
# line 458 "lex.l"
{
current_input_column++;
return handle_string ('"');
}
YY_BREAK
// The colon operator is handled differently if we are in the range
// part of a plot command.
case 25:
YY_USER_ACTION
# line 468 "lex.l"
{
if (plotting && (in_plot_range || in_plot_using))
BIN_OP_RETURN (COLON, 1);
else
BIN_OP_RETURN (':', 0);
}
YY_BREAK
// Gobble comments. If closest nesting is inside parentheses, don't
// return a new line.
case 26:
YY_USER_ACTION
# line 480 "lex.l"
{
if (! help_buf && beginning_of_function && nesting_level.empty ())
{
grab_help_text ();
beginning_of_function = 0;
}
else
{
int c;
while ((c = yyinput ()) != EOF && c != '\n')
; // Eat comment.
}
quote_is_transpose = 0;
cant_be_identifier = 0;
current_input_column = 1;
convert_spaces_to_comma = 1;
if (nesting_level.empty () || nesting_level.top () == BRACE)
return '\n';
}
YY_BREAK
// Other operators.
case 27:
YY_USER_ACTION
# line 506 "lex.l"
{ BIN_OP_RETURN (EMUL, 0); }
YY_BREAK
case 28:
YY_USER_ACTION
# line 507 "lex.l"
{ BIN_OP_RETURN (EDIV, 0); }
YY_BREAK
case 29:
YY_USER_ACTION
# line 508 "lex.l"
{ BIN_OP_RETURN (ELEFTDIV, 0); }
YY_BREAK
case 30:
YY_USER_ACTION
# line 509 "lex.l"
{ BIN_OP_RETURN (EPOW, 0); }
YY_BREAK
case 31:
YY_USER_ACTION
# line 510 "lex.l"
{ do_comma_insert_check (); BIN_OP_RETURN (TRANSPOSE, 1); }
YY_BREAK
case 32:
YY_USER_ACTION
# line 511 "lex.l"
{ do_comma_insert_check (); BIN_OP_RETURN (PLUS_PLUS, 1); }
YY_BREAK
case 33:
YY_USER_ACTION
# line 512 "lex.l"
{ do_comma_insert_check (); BIN_OP_RETURN (MINUS_MINUS, 1); }
YY_BREAK
case 34:
YY_USER_ACTION
# line 513 "lex.l"
{ BIN_OP_RETURN (EXPR_LE, 0); }
YY_BREAK
case 35:
YY_USER_ACTION
# line 514 "lex.l"
{ BIN_OP_RETURN (EXPR_EQ, 0); }
YY_BREAK
case 36:
YY_USER_ACTION
# line 515 "lex.l"
{ BIN_OP_RETURN (EXPR_NE, 0); }
YY_BREAK
case 37:
YY_USER_ACTION
# line 516 "lex.l"
{ BIN_OP_RETURN (EXPR_GE, 0); }
YY_BREAK
case 38:
YY_USER_ACTION
# line 517 "lex.l"
{ BIN_OP_RETURN (EXPR_OR, 0); }
YY_BREAK
case 39:
YY_USER_ACTION
# line 518 "lex.l"
{ BIN_OP_RETURN (EXPR_AND, 0); }
YY_BREAK
case 40:
YY_USER_ACTION
# line 519 "lex.l"
{ BIN_OP_RETURN (EXPR_LT, 0); }
YY_BREAK
case 41:
YY_USER_ACTION
# line 520 "lex.l"
{ BIN_OP_RETURN (EXPR_GT, 0); }
YY_BREAK
case 42:
YY_USER_ACTION
# line 521 "lex.l"
{ BIN_OP_RETURN ('*', 0); }
YY_BREAK
case 43:
YY_USER_ACTION
# line 522 "lex.l"
{ BIN_OP_RETURN ('/', 0); }
YY_BREAK
case 44:
YY_USER_ACTION
# line 523 "lex.l"
{ BIN_OP_RETURN (LEFTDIV, 0); }
YY_BREAK
case 45:
YY_USER_ACTION
# line 524 "lex.l"
{ BIN_OP_RETURN (';', 1); }
YY_BREAK
case 46:
YY_USER_ACTION
# line 525 "lex.l"
{ BIN_OP_RETURN (',', 1); }
YY_BREAK
case 47:
YY_USER_ACTION
# line 526 "lex.l"
{ BIN_OP_RETURN (POW, 0); }
YY_BREAK
case 48:
YY_USER_ACTION
# line 527 "lex.l"
{ BIN_OP_RETURN ('=', 1); }
YY_BREAK
case 49:
YY_USER_ACTION
# line 529 "lex.l"
{
#ifdef SHORT_CIRCUIT_LOGICALS
BIN_OP_RETURN (EXPR_OR_OR, 0);
#else
BIN_OP_RETURN (EXPR_OR, 0);
#endif
}
YY_BREAK
case 50:
YY_USER_ACTION
# line 537 "lex.l"
{
#ifdef SHORT_CIRCUIT_LOGICALS
BIN_OP_RETURN (EXPR_AND_AND, 0);
#else
BIN_OP_RETURN (EXPR_AND, 0);
#endif
}
YY_BREAK
case 51:
YY_USER_ACTION
# line 545 "lex.l"
{
if (plotting && ! in_plot_range)
past_plot_range = 1;
BIN_OP_RETURN (EXPR_NOT, 0);
}
YY_BREAK
case 52:
YY_USER_ACTION
# line 551 "lex.l"
{
if (plotting && ! in_plot_range)
past_plot_range = 1;
BIN_OP_RETURN ('+', 0);
}
YY_BREAK
case 53:
YY_USER_ACTION
# line 557 "lex.l"
{
if (plotting && ! in_plot_range)
past_plot_range = 1;
BIN_OP_RETURN ('-', 0);
}
YY_BREAK
case 54:
YY_USER_ACTION
# line 563 "lex.l"
{
if (plotting && ! in_plot_range)
past_plot_range = 1;
nesting_level.push (PAREN);
promptflag--;
TOK_RETURN ('(');
}
YY_BREAK
case 55:
YY_USER_ACTION
# line 571 "lex.l"
{
if (! nesting_level.empty ())
nesting_level.pop ();
current_input_column++;
cant_be_identifier = 1;
quote_is_transpose = 1;
convert_spaces_to_comma = (! nesting_level.empty ()
&& nesting_level.top () == BRACE);
do_comma_insert_check ();
return ')';
}
YY_BREAK
// We return everything else as single character tokens, which should
// eventually result in a parse error.
case 56:
YY_USER_ACTION
# line 589 "lex.l"
{ TOK_RETURN (yytext[0]); }
YY_BREAK
case 57:
YY_USER_ACTION
# line 591 "lex.l"
ECHO;
YY_BREAK
case YY_END_OF_BUFFER:
{
/* Amount of text matched not including the EOB char. */
int yy_amount_of_matched_text = yy_cp - yytext_ptr - 1;
/* Undo the effects of YY_DO_BEFORE_ACTION. */
*yy_cp = yy_hold_char;
if ( yy_current_buffer->yy_input_file != yyin )
{
/* This can happen if we scan a file, yywrap() returns
* 1, and then later the user points yyin at a new
* file to resume scanning. We have to assure
* consistency between yy_current_buffer and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
* back-up) that will match for the new input file.
*/
yy_current_buffer->yy_input_file = yyin;
yy_n_chars = yy_current_buffer->yy_n_chars;
}
/* Note that here we test for yy_c_buf_p "<=" to the position
* of the first EOB in the buffer, since yy_c_buf_p will
* already have been incremented past the NUL character
* (since all states make transitions on EOB to the
* end-of-buffer state). Contrast this with the test
* in input().
*/
if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
{ /* This was really a NUL. */
yy_state_type yy_next_state;
yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
yy_current_state = yy_get_previous_state();
/* Okay, we're now positioned to make the NUL
* transition. We couldn't have
* yy_get_previous_state() go ahead and do it
* for us because it doesn't know how to deal
* with the possibility of jamming (and we don't
* want to build jamming into it because then it
* will run more slowly).
*/
yy_next_state = yy_try_NUL_trans( yy_current_state );
yy_bp = yytext_ptr + YY_MORE_ADJ;
if ( yy_next_state )
{
/* Consume the NUL. */
yy_cp = ++yy_c_buf_p;
yy_current_state = yy_next_state;
goto yy_match;
}
else
{
goto yy_find_action;
}
}
else switch ( yy_get_next_buffer() )
{
case EOB_ACT_END_OF_FILE:
{
yy_did_buffer_switch_on_eof = 0;
if ( yywrap() )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
* yytext, we can now set up
* yy_c_buf_p so that if some total
* hoser (like flex itself) wants to
* call the scanner after we return the
* YY_NULL, it'll still work - another
* YY_NULL will get returned.
*/
yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
yy_act = YY_STATE_EOF(YY_START);
goto do_action;
}
else
{
if ( ! yy_did_buffer_switch_on_eof )
YY_NEW_FILE;
}
break;
}
case EOB_ACT_CONTINUE_SCAN:
yy_c_buf_p =
yytext_ptr + yy_amount_of_matched_text;
yy_current_state = yy_get_previous_state();
yy_cp = yy_c_buf_p;
yy_bp = yytext_ptr + YY_MORE_ADJ;
goto yy_match;
case EOB_ACT_LAST_MATCH:
yy_c_buf_p =
&yy_current_buffer->yy_ch_buf[yy_n_chars];
yy_current_state = yy_get_previous_state();
yy_cp = yy_c_buf_p;
yy_bp = yytext_ptr + YY_MORE_ADJ;
goto yy_find_action;
}
break;
}
default:
YY_FATAL_ERROR(
"fatal flex scanner internal error--no action found" );
} /* end of action switch */
} /* end of scanning one token */
} /* end of yylex */
/* yy_get_next_buffer - try to read in a new buffer
*
* Returns a code representing an action:
* EOB_ACT_LAST_MATCH -
* EOB_ACT_CONTINUE_SCAN - continue scanning from current position
* EOB_ACT_END_OF_FILE - end of file
*/
static int yy_get_next_buffer()
{
register char *dest = yy_current_buffer->yy_ch_buf;
register char *source = yytext_ptr - 1; /* copy prev. char, too */
register int number_to_move, i;
int ret_val;
if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
YY_FATAL_ERROR(
"fatal flex scanner internal error--end of buffer missed" );
if ( yy_current_buffer->yy_fill_buffer == 0 )
{ /* Don't try to fill the buffer, so this is an EOF. */
if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
{
/* We matched a singled characater, the EOB, so
* treat this as a final EOF.
*/
return EOB_ACT_END_OF_FILE;
}
else
{
/* We matched some text prior to the EOB, first
* process it.
*/
return EOB_ACT_LAST_MATCH;
}
}
/* Try to read more data. */
/* First move last chars to start of buffer. */
number_to_move = yy_c_buf_p - yytext_ptr;
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
if ( yy_current_buffer->yy_eof_status != EOF_NOT_SEEN )
/* don't do the read, it's not guaranteed to return an EOF,
* just force an EOF
*/
yy_n_chars = 0;
else
{
int num_to_read =
yy_current_buffer->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */
#ifdef YY_USES_REJECT
YY_FATAL_ERROR(
"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
#else
/* just a shorter name for the current buffer */
YY_BUFFER_STATE b = yy_current_buffer;
int yy_c_buf_p_offset = yy_c_buf_p - b->yy_ch_buf;
b->yy_buf_size *= 2;
b->yy_ch_buf = (char *)
yy_flex_realloc( (void *) b->yy_ch_buf,
b->yy_buf_size );
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR(
"fatal error - scanner input buffer overflow" );
yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
num_to_read = yy_current_buffer->yy_buf_size -
number_to_move - 1;
#endif
}
if ( num_to_read > YY_READ_BUF_SIZE )
num_to_read = YY_READ_BUF_SIZE;
/* Read in more data. */
YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
yy_n_chars, num_to_read );
}
if ( yy_n_chars == 0 )
{
if ( number_to_move - YY_MORE_ADJ == 1 )
{
ret_val = EOB_ACT_END_OF_FILE;
yyrestart( yyin );
}
else
{
ret_val = EOB_ACT_LAST_MATCH;
yy_current_buffer->yy_eof_status = EOF_PENDING;
}
}
else
ret_val = EOB_ACT_CONTINUE_SCAN;
yy_n_chars += number_to_move;
yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
/* yytext begins at the second character in yy_ch_buf; the first
* character is the one which preceded it before reading in the latest
* buffer; it needs to be kept around in case it's a newline, so
* yy_get_previous_state() will have with '^' rules active.
*/
yytext_ptr = &yy_current_buffer->yy_ch_buf[1];
return ret_val;
}
/* yy_get_previous_state - get the state just before the EOB char was reached */
static yy_state_type yy_get_previous_state()
{
register yy_state_type yy_current_state;
register char *yy_cp;
yy_current_state = yy_start;
for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
{
register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yy_last_accepting_state = yy_current_state;
yy_last_accepting_cpos = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 179 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
}
return yy_current_state;
}
/* yy_try_NUL_trans - try to make a transition on the NUL character
*
* synopsis
* next_state = yy_try_NUL_trans( current_state );
*/
#ifdef YY_USE_PROTOS
static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
#else
static yy_state_type yy_try_NUL_trans( yy_current_state )
yy_state_type yy_current_state;
#endif
{
register int yy_is_jam;
register char *yy_cp = yy_c_buf_p;
register YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yy_last_accepting_state = yy_current_state;
yy_last_accepting_cpos = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 179 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
yy_is_jam = (yy_current_state == 178);
return yy_is_jam ? 0 : yy_current_state;
}
#ifdef YY_USE_PROTOS
static void yyunput( int c, register char *yy_bp )
#else
static void yyunput( c, yy_bp )
int c;
register char *yy_bp;
#endif
{
register char *yy_cp = yy_c_buf_p;
/* undo effects of setting up yytext */
*yy_cp = yy_hold_char;
if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
register int number_to_move = yy_n_chars + 2;
register char *dest = &yy_current_buffer->yy_ch_buf[
yy_current_buffer->yy_buf_size + 2];
register char *source =
&yy_current_buffer->yy_ch_buf[number_to_move];
while ( source > yy_current_buffer->yy_ch_buf )
*--dest = *--source;
yy_cp += dest - source;
yy_bp += dest - source;
yy_n_chars = yy_current_buffer->yy_buf_size;
if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
YY_FATAL_ERROR( "flex scanner push-back overflow" );
}
if ( yy_cp > yy_bp && yy_cp[-1] == '\n' )
yy_cp[-2] = '\n';
*--yy_cp = (char) c;
/* Note: the formal parameter *must* be called "yy_bp" for this
* macro to now work correctly.
*/
YY_DO_BEFORE_ACTION; /* set up yytext again */
}
#ifdef __cplusplus
static int yyinput()
#else
static int input()
#endif
{
int c;
*yy_c_buf_p = yy_hold_char;
if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
{
/* yy_c_buf_p now points to the character we want to return.
* If this occurs *before* the EOB characters, then it's a
* valid NUL; if not, then we've hit the end of the buffer.
*/
if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
/* This was really a NUL. */
*yy_c_buf_p = '\0';
else
{ /* need more input */
yytext_ptr = yy_c_buf_p;
++yy_c_buf_p;
switch ( yy_get_next_buffer() )
{
case EOB_ACT_END_OF_FILE:
{
if ( yywrap() )
{
yy_c_buf_p =
yytext_ptr + YY_MORE_ADJ;
return EOF;
}
YY_NEW_FILE;
#ifdef __cplusplus
return yyinput();
#else
return input();
#endif
}
case EOB_ACT_CONTINUE_SCAN:
yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
break;
case EOB_ACT_LAST_MATCH:
#ifdef __cplusplus
YY_FATAL_ERROR(
"unexpected last match in yyinput()" );
#else
YY_FATAL_ERROR(
"unexpected last match in input()" );
#endif
}
}
}
c = *yy_c_buf_p;
*yy_c_buf_p = '\0'; /* preserve yytext */
yy_hold_char = *++yy_c_buf_p;
return c;
}
#ifdef YY_USE_PROTOS
void yyrestart( FILE *input_file )
#else
void yyrestart( input_file )
FILE *input_file;
#endif
{
if ( ! yy_current_buffer )
yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
yy_init_buffer( yy_current_buffer, input_file );
yy_load_buffer_state();
}
#ifdef YY_USE_PROTOS
void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
#else
void yy_switch_to_buffer( new_buffer )
YY_BUFFER_STATE new_buffer;
#endif
{
if ( yy_current_buffer == new_buffer )
return;
if ( yy_current_buffer )
{
/* Flush out information for old buffer. */
*yy_c_buf_p = yy_hold_char;
yy_current_buffer->yy_buf_pos = yy_c_buf_p;
yy_current_buffer->yy_n_chars = yy_n_chars;
}
yy_current_buffer = new_buffer;
yy_load_buffer_state();
/* We don't actually know whether we did this switch during
* EOF (yywrap()) processing, but the only time this flag
* is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
yy_did_buffer_switch_on_eof = 1;
}
#ifdef YY_USE_PROTOS
void yy_load_buffer_state( void )
#else
void yy_load_buffer_state()
#endif
{
yy_n_chars = yy_current_buffer->yy_n_chars;
yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
yyin = yy_current_buffer->yy_input_file;
yy_hold_char = *yy_c_buf_p;
}
#ifdef YY_USE_PROTOS
YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
#else
YY_BUFFER_STATE yy_create_buffer( file, size )
FILE *file;
int size;
#endif
{
YY_BUFFER_STATE b;
b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
b->yy_buf_size = size;
/* yy_ch_buf has to be 2 characters longer than the size given because
* we need to put in 2 end-of-buffer characters.
*/
b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
yy_init_buffer( b, file );
return b;
}
#ifdef YY_USE_PROTOS
void yy_delete_buffer( YY_BUFFER_STATE b )
#else
void yy_delete_buffer( b )
YY_BUFFER_STATE b;
#endif
{
if ( b == yy_current_buffer )
yy_current_buffer = (YY_BUFFER_STATE) 0;
yy_flex_free( (void *) b->yy_ch_buf );
yy_flex_free( (void *) b );
}
#ifdef YY_USE_PROTOS
void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
#else
void yy_init_buffer( b, file )
YY_BUFFER_STATE b;
FILE *file;
#endif
{
b->yy_input_file = file;
/* We put in the '\n' and start reading from [1] so that an
* initial match-at-newline will be true.
*/
b->yy_ch_buf[0] = '\n';
b->yy_n_chars = 1;
/* We always need two end-of-buffer characters. The first causes
* a transition to the end-of-buffer state. The second causes
* a jam in that state.
*/
b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
b->yy_ch_buf[2] = YY_END_OF_BUFFER_CHAR;
b->yy_buf_pos = &b->yy_ch_buf[1];
b->yy_is_interactive = file ? isatty( fileno(file) ) : 0;
b->yy_fill_buffer = 1;
b->yy_eof_status = EOF_NOT_SEEN;
}
#ifdef YY_USE_PROTOS
static void yy_push_state( int new_state )
#else
static void yy_push_state( new_state )
int new_state;
#endif
{
if ( yy_start_stack_ptr >= yy_start_stack_depth )
{
int new_size;
yy_start_stack_depth += YY_START_STACK_INCR;
new_size = yy_start_stack_depth * sizeof( int );
if ( ! yy_start_stack )
yy_start_stack = (int *) yy_flex_alloc( new_size );
else
yy_start_stack = (int *) yy_flex_realloc(
(void *) yy_start_stack, new_size );
if ( ! yy_start_stack )
YY_FATAL_ERROR(
"out of memory expanding start-condition stack" );
}
yy_start_stack[yy_start_stack_ptr++] = YY_START;
BEGIN(new_state);
}
static void yy_pop_state()
{
if ( --yy_start_stack_ptr < 0 )
YY_FATAL_ERROR( "start-condition stack underflow" );
BEGIN(yy_start_stack[yy_start_stack_ptr]);
}
static int yy_top_state()
{
return yy_start_stack[yy_start_stack_ptr - 1];
}
#ifdef YY_USE_PROTOS
static void yy_fatal_error( const char msg[] )
#else
static void yy_fatal_error( msg )
char msg[];
#endif
{
(void) fprintf( stderr, "%s\n", msg );
exit( 1 );
}
/* Redefine yyless() so it works in section 3 code. */
#undef yyless
#define yyless(n) \
do \
{ \
/* Undo effects of setting up yytext. */ \
yytext[yyleng] = yy_hold_char; \
yy_c_buf_p = yytext + n - YY_MORE_ADJ; \
yy_hold_char = *yy_c_buf_p; \
*yy_c_buf_p = '\0'; \
yyleng = n; \
} \
while ( 0 )
/* Internal utility routines. */
#ifndef yytext_ptr
#ifdef YY_USE_PROTOS
static void yy_flex_strcpy( char *s1, const char *s2 )
#else
static void yy_flex_strcpy( s1, s2 )
char *s1;
const char *s2;
#endif
{
while ( (*(s1++) = *(s2++)) )
;
}
#endif
#ifdef YY_USE_PROTOS
static void *yy_flex_alloc( unsigned int size )
#else
static void *yy_flex_alloc( size )
unsigned int size;
#endif
{
return (void *) malloc( size );
}
#ifdef YY_USE_PROTOS
static void *yy_flex_realloc( void *ptr, unsigned int size )
#else
static void *yy_flex_realloc( ptr, size )
void *ptr;
unsigned int size;
#endif
{
return (void *) realloc( ptr, size );
}
#ifdef YY_USE_PROTOS
static void yy_flex_free( void *ptr )
#else
static void yy_flex_free( ptr )
void *ptr;
#endif
{
free( ptr );
}
# line 591 "lex.l"
// GAG.
//
// If we're reading a matrix and the next character is '[', make sure
// that we insert a comma ahead of it.
void
do_comma_insert_check (void)
{
int spc_gobbled = eat_continuation ();
int c = yyinput ();
yyunput (c, yytext);
if (spc_gobbled)
yyunput (' ', yytext);
do_comma_insert = (braceflag && c == '[');
}
// Fix things up for errors or interrupts. The parser is never called
// recursively, so it is always safe to reinitialize its state before
// doing any parsing.
void
reset_parser (void)
{
// Start off on the right foot.
BEGIN 0;
error_state = 0;
// We do want a prompt by default.
promptflag = 1;
// Not initially screwed by `function [...] = f (...)' syntax.
maybe_screwed = 0;
maybe_screwed_again = 0;
// Not initially inside a loop or if statement.
looping = 0;
iffing = 0;
// Quote marks strings intially.
quote_is_transpose = 0;
// Next token can be identifier.
cant_be_identifier = 0;
// No need to do comma insert or convert spaces to comma at beginning
// of input.
do_comma_insert = 0;
convert_spaces_to_comma = 1;
// Not initially defining a function.
beginning_of_function = 0;
defining_func = 0;
// Not initially doing any plotting or setting of plot attributes.
plotting = 0;
in_plot_range = 0;
past_plot_range = 0;
in_plot_using = 0;
in_plot_style = 0;
doing_set = 0;
// Not initially looking at indirect references.
looking_at_indirect_ref = 0;
// Error may have occurred inside some parentheses or braces.
nesting_level.clear ();
// Not initially defining a matrix list.
braceflag = 0;
ml.clear ();
mlnm.clear ();
// Clear out the stack of token info used to track line and column
// numbers.
while (! token_stack.empty ())
delete token_stack.pop ();
// Can be reset by defining a function.
if (! (reading_script_file || reading_fcn_file))
{
current_input_column = 1;
input_line_number = current_command_number - 1;
}
// Only ask for input from stdin if we are expecting interactive
// input.
if (interactive && ! (reading_fcn_file || get_input_from_eval_string))
yyrestart (stdin);
// Delete the buffer for help text.
delete [] help_buf;
help_buf = 0;
}
// Replace backslash escapes in a string with the real values.
static void
do_string_escapes (char *s)
{
char *p1 = s;
char *p2 = s;
while (*p2 != '\0')
{
if (*p2 == '\\' && *(p2+1) != '\0')
{
switch (*++p2)
{
case 'a':
*p1 = '\a';
break;
case 'b': // backspace
*p1 = '\b';
break;
case 'f': // formfeed
*p1 = '\f';
break;
case 'n': // newline
*p1 = '\n';
break;
case 'r': // carriage return
*p1 = '\r';
break;
case 't': // horizontal tab
*p1 = '\t';
break;
case 'v': // vertical tab
*p1 = '\v';
break;
case '\\': // backslash
*p1 = '\\';
break;
case '\'': // quote
*p1 = '\'';
break;
case '"': // double quote
*p1 = '"';
break;
default:
warning ("unrecognized escape sequence `\\%c' --\
converting to `%c'", *p2, *p2);
*p1 = *p2;
break;
}
}
else
{
*p1 = *p2;
}
p1++;
p2++;
}
*p1 = '\0';
}
// If we read some newlines, we need figure out what column we're
// really looking at.
static void
fixup_column_count (char *s)
{
char c;
while ((c = *s++) != '\0')
{
if (c == '\n')
current_input_column = 1;
else
current_input_column++;
}
}
// Include these so that we don't have to link to libfl.a.
#ifdef yywrap
#undef yywrap
#endif
static int
yywrap (void)
{
return 1;
}
// These are not needed with flex-2.4.6, but may be needed with
// earlier 2.4.x versions.
#if 0
static void *
yy_flex_alloc (int size)
{
return (void *) malloc ((unsigned) size);
}
static void *
yy_flex_realloc (void *ptr, int size)
{
return (void *) realloc (ptr, (unsigned) size);
}
static void
yy_flex_free (void *ptr)
{
free (ptr);
}
#endif
// Tell us all what the current buffer is.
YY_BUFFER_STATE
current_buffer (void)
{
return YY_CURRENT_BUFFER;
}
// Create a new buffer.
YY_BUFFER_STATE
create_buffer (FILE *f)
{
return yy_create_buffer (f, YY_BUF_SIZE);
}
// Start reading a new buffer.
void
switch_to_buffer (YY_BUFFER_STATE buf)
{
yy_switch_to_buffer (buf);
}
// Delete a buffer.
void
delete_buffer (YY_BUFFER_STATE buf)
{
yy_delete_buffer (buf);
}
// Restore a buffer (for unwind-prot).
void
restore_input_buffer (void *buf)
{
switch_to_buffer ((YY_BUFFER_STATE) buf);
}
// Delete a buffer (for unwind-prot).
void
delete_input_buffer (void *buf)
{
delete_buffer ((YY_BUFFER_STATE) buf);
}
// Check to see if a character string matches any of the possible line
// styles for plots.
static char *
plot_style_token (char *s)
{
static char *plot_styles[] =
{
"boxes",
"boxerrorbars",
"dots",
"errorbars",
"impulses",
"lines",
"linespoints",
"points",
"steps",
0,
};
char **tmp = plot_styles;
while (*tmp)
{
if (almost_match (*tmp, s))
return *tmp;
tmp++;
}
return 0;
}
// Check to see if a character string matches any one of the plot
// option keywords. Don't match abbreviations for clear, since that's
// not a gnuplot keyword (users will probably only expect to be able
// to abbreviate actual gnuplot keywords).
static int
is_plot_keyword (char *s)
{
if (almost_match ("title", s))
{
return TITLE;
}
else if (almost_match ("using", s))
{
in_plot_using = 1;
return USING;
}
else if (almost_match ("with", s))
{
in_plot_style = 1;
return WITH;
}
else if (strcmp ("clear", s) == 0)
{
return CLEAR;
}
else
{
return 0;
}
}
// Handle keywords. Could probably be more efficient...
static int
is_keyword (char *s)
{
if (plotting && in_plot_style)
{
char *sty = plot_style_token (s);
if (sty)
{
in_plot_style = 0;
yylval.tok_val = new token (sty);
token_stack.push (yylval.tok_val);
return STYLE;
}
}
int l = input_line_number;
int c = current_input_column;
// XXX FIXME XXX -- this has really become too large a list to search
// like this...
int end_found = 0;
if (strcmp ("break", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return BREAK;
}
else if (strcmp ("continue", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return CONTINUE;
}
else if (strcmp ("else", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return ELSE;
}
else if (strcmp ("elseif", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return ELSEIF;
}
else if (strcmp ("end", s) == 0)
{
end_found = 1;
yylval.tok_val = new token (token::simple_end, l, c);
token_stack.push (yylval.tok_val);
}
else if (strcmp ("endfor", s) == 0)
{
end_found = 1;
yylval.tok_val = new token (token::for_end, l, c);
token_stack.push (yylval.tok_val);
}
else if (strcmp ("endfunction", s) == 0)
{
end_found = 1;
yylval.tok_val = new token (token::function_end, l, c);
token_stack.push (yylval.tok_val);
}
else if (strcmp ("endif", s) == 0)
{
end_found = 1;
yylval.tok_val = new token (token::if_end, l, c);
token_stack.push (yylval.tok_val);
}
else if (strcmp ("endwhile", s) == 0)
{
end_found = 1;
yylval.tok_val = new token (token::while_end, l, c);
token_stack.push (yylval.tok_val);
}
else if (strcmp ("for", s) == 0)
{
promptflag--;
looping++;
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return FOR;
}
else if (strcmp ("function", s) == 0)
{
if (defining_func)
{
error ("function keyword invalid within a function body");
if ((reading_fcn_file || reading_script_file)
&& curr_fcn_file_name)
error ("defining new function near line %d of file `%s.m'",
input_line_number, curr_fcn_file_name);
else
error ("defining new function near line %d", input_line_number);
return LEXICAL_ERROR;
}
else
{
tmp_local_sym_tab = new symbol_table ();
curr_sym_tab = tmp_local_sym_tab;
defining_func = 1;
promptflag--;
beginning_of_function = 1;
if (! (reading_fcn_file || reading_script_file))
input_line_number = 1;
return FCN;
}
}
else if (strcmp ("global", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return GLOBAL;
}
else if (strcmp ("gplot", s) == 0)
{
plotting = 1;
yylval.tok_val = new token (token::two_dee, l, c);
token_stack.push (yylval.tok_val);
return PLOT;
}
else if (strcmp ("gsplot", s) == 0)
{
plotting = 1;
yylval.tok_val = new token (token::three_dee, l, c);
token_stack.push (yylval.tok_val);
return PLOT;
}
else if (strcmp ("replot", s) == 0)
{
plotting = 1;
yylval.tok_val = new token (token::replot, l, c);
token_stack.push (yylval.tok_val);
return PLOT;
}
else if (strcmp ("if", s) == 0)
{
iffing++;
promptflag--;
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return IF;
}
else if (strcmp ("return", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return FUNC_RET;
}
else if (strcmp ("while", s) == 0)
{
promptflag--;
looping++;
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return WHILE;
}
else if (strcmp ("unwind_protect", s) == 0)
{
promptflag--;
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return UNWIND;
}
else if (strcmp ("unwind_protect_cleanup", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return CLEANUP;
}
else if (strcmp ("end_unwind_protect", s) == 0)
{
end_found = 1;
yylval.tok_val = new token (token::unwind_protect_end, l, c);
token_stack.push (yylval.tok_val);
}
else if (strcmp ("all_va_args", s) == 0)
{
yylval.tok_val = new token (l, c);
token_stack.push (yylval.tok_val);
return ALL_VA_ARGS;
}
if (end_found)
return END;
return 0;
}
// Try to find an identifier. All binding to global or builtin
// variables occurs when expressions are evaluated.
static symbol_record *
lookup_identifier (char *name)
{
return curr_sym_tab->lookup (name, 1, 0);
}
// Grab the help text from an function file. Always overwrites the
// current contents of help_buf.
static void
grab_help_text (void)
{
delete [] help_buf;
help_buf = 0;
ostrstream buf;
int in_comment = 1;
int c = 0;
while ((c = yyinput ()) != EOF)
{
if (in_comment)
{
buf << (char) c;
if (c == '\n')
in_comment = 0;
}
else
{
switch (c)
{
case '%':
case '#':
in_comment = 1;
break;
case ' ':
case '\t':
break;
default:
goto done;
}
}
}
done:
if (c)
yyunput (c, yytext);
buf << ends;
help_buf = buf.str ();
if (! help_buf || ! *help_buf)
{
delete [] help_buf;
help_buf = 0;
}
}
// Return 1 if the given character matches any character in the given
// string.
static int
match_any (char c, char *s)
{
char tmp;
while ((tmp = *s++) != '\0')
{
if (c == tmp)
return 1;
}
return 0;
}
// Given information about the spacing surrounding an operator,
// return 1 if it looks like it should be treated as a binary
// operator. For example,
//
// [ 1 + 2 ] or [ 1+ 2] or [ 1+2 ] ==> binary
static int
looks_like_bin_op (int spc_prev, int spc_next)
{
return ((spc_prev && spc_next) || ! spc_prev);
}
// Duh.
static int
next_char_is_space (void)
{
int c = yyinput ();
yyunput (c, yytext);
return (c == ' ' || c == '\t');
}
// Try to determine if the next token should be treated as a postfix
// unary operator. This is ugly, but it seems to do the right thing.
static int
next_token_is_postfix_unary_op (int spc_prev, char *yytext)
{
int un_op = 0;
int c0 = yyinput ();
int c1 = yyinput ();
yyunput (c1, yytext);
yyunput (c0, yytext);
int transpose = (c0 == '.' && c1 == '\'');
int hermitian = (c0 == '\'');
un_op = (transpose || (hermitian && ! spc_prev));
return un_op;
}
// Try to determine if the next token should be treated as a binary
// operator. This is even uglier, but it also seems to do the right
// thing.
static int
next_token_is_bin_op (int spc_prev, char *yytext)
{
int bin_op = 0;
int spc_next = 0;
int c0 = yyinput ();
int c1 = yyinput ();
switch (c0)
{
case '+':
case '-':
case '/':
case ':':
case '\\':
case '^':
spc_next = (c1 == ' ' || c1 == '\t');
break;
case '&':
if (c1 == '&')
spc_next = next_char_is_space ();
else
spc_next = (c1 == ' ' || c1 == '\t');
break;
case '*':
if (c1 == '*')
spc_next = next_char_is_space ();
else
spc_next = (c1 == ' ' || c1 == '\t');
break;
case '|':
if (c1 == '|')
spc_next = next_char_is_space ();
else
spc_next = (c1 == ' ' || c1 == '\t');
break;
case '<':
if (c1 == '=' || c1 == '>')
spc_next = next_char_is_space ();
else
spc_next = (c1 == ' ' || c1 == '\t');
break;
case '>':
if (c1 == '=')
spc_next = next_char_is_space ();
else
spc_next = (c1 == ' ' || c1 == '\t');
break;
case '~':
case '!':
case '=':
if (c1 == '=')
spc_next = next_char_is_space ();
else
goto done;
break;
case '.':
if (c1 == '*')
{
int c2 = yyinput ();
if (c2 == '*')
spc_next = next_char_is_space ();
else
spc_next = (c2 == ' ' || c2 == '\t');
yyunput (c2, yytext);
}
else if (c1 == '/' || c1 == '\\' || c1 == '^')
spc_next = next_char_is_space ();
else
goto done;
break;
default:
goto done;
}
bin_op = looks_like_bin_op (spc_prev, spc_next);
done:
yyunput (c1, yytext);
yyunput (c0, yytext);
return bin_op;
}
// Used to delete trailing white space from tokens.
static char *
strip_trailing_whitespace (char *s)
{
char *retval = strsave (s);
char *t = strchr (retval, ' ');
if (t)
*t = '\0';
t = strchr (retval, '\t');
if (t)
*t = '\0';
return retval;
}
// Discard whitespace, including comments and continuations.
//
// Return value is logical OR of the following values:
//
// ATE_SPACE_OR_TAB : space or tab in input
// ATE_NEWLINE : bare new line in input
static int
eat_whitespace (void)
{
int retval = 0;
int in_comment = 0;
int c;
while ((c = yyinput ()) != EOF)
{
current_input_column++;
switch (c)
{
case ' ':
case '\t':
retval |= ATE_SPACE_OR_TAB;
break;
case '\n':
retval |= ATE_NEWLINE;
in_comment = 0;
current_input_column = 0;
break;
case '#':
case '%':
in_comment = 1;
break;
case '.':
if (in_comment)
break;
else
{
if (have_ellipsis_continuation ())
break;
else
goto done;
}
case '\\':
if (in_comment)
break;
else
{
if (have_continuation ())
break;
else
goto done;
}
default:
if (in_comment)
break;
else
goto done;
}
}
done:
yyunput (c, yytext);
current_input_column--;
return retval;
}
static void
handle_number (char *yytext)
{
double value;
int nread = sscanf (yytext, "%lf", &value);
// If yytext doesn't contain a valid number, we are in deep doo doo.
assert (nread == 1);
quote_is_transpose = 1;
cant_be_identifier = 1;
convert_spaces_to_comma = 1;
if (plotting && ! in_plot_range)
past_plot_range = 1;
yylval.tok_val = new token (value, yytext, input_line_number,
current_input_column);
token_stack.push (yylval.tok_val);
current_input_column += yyleng;
do_comma_insert_check ();
}
// We have seen a backslash and need to find out if it should be
// treated as a continuation character. If so, this eats it, up to
// and including the new line character.
//
// Match whitespace only, followed by a comment character or newline.
// Once a comment character is found, discard all input until newline.
// If non-whitespace characters are found before comment
// characters, return 0. Otherwise, return 1.
static int
have_continuation (int trailing_comments_ok)
{
ostrstream buf;
int in_comment = 0;
char c;
while ((c = yyinput ()) != EOF)
{
buf << (char) c;
switch (c)
{
case ' ':
case '\t':
break;
case '%':
case '#':
if (trailing_comments_ok)
in_comment = 1;
else
goto cleanup;
break;
case '\n':
current_input_column = 0;
promptflag--;
return 1;
default:
if (! in_comment)
goto cleanup;
break;
}
}
yyunput (c, yytext);
return 0;
cleanup:
buf << ends;
char *s = buf.str ();
if (s)
{
int len = strlen (s);
while (len--)
yyunput (s[len], yytext);
}
delete [] s;
return 0;
}
// We have seen a `.' and need to see if it is the start of a
// continuation. If so, this eats it, up to and including the new
// line character.
static int
have_ellipsis_continuation (int trailing_comments_ok)
{
char c1 = yyinput ();
if (c1 == '.')
{
char c2 = yyinput ();
if (c2 == '.' && have_continuation (trailing_comments_ok))
return 1;
else
{
yyunput (c2, yytext);
yyunput (c1, yytext);
}
}
else
yyunput (c1, yytext);
return 0;
}
// See if we have a continuation line. If so, eat it and the leading
// whitespace on the next line.
//
// Return value is the same as described for eat_whitespace().
static int
eat_continuation (void)
{
int retval = 0;
int c = yyinput ();
if ((c == '.' && have_ellipsis_continuation ())
|| (c == '\\' && have_continuation ()))
retval = eat_whitespace ();
else
yyunput (c, yytext);
return retval;
}
static int
handle_string (char delim, int text_style)
{
ostrstream buf;
int c;
int escape_pending = 0;
while ((c = yyinput ()) != EOF)
{
current_input_column++;
if (c == '\\')
{
if (escape_pending)
{
buf << (char) c;
escape_pending = 0;
}
else
{
if (have_continuation (0))
escape_pending = 0;
else
{
buf << (char) c;
escape_pending = 1;
}
}
continue;
}
else if (c == '.')
{
if (! have_ellipsis_continuation (0))
buf << (char) c;
}
else if (c == '\n')
{
error ("unterminated string constant");
break;
}
else if (c == delim)
{
if (escape_pending)
buf << (char) c;
else
{
c = yyinput ();
if (c == delim)
buf << (char) c;
else
{
yyunput (c, yytext);
buf << ends;
char *tok = buf.str ();
do_string_escapes (tok);
if (text_style && doing_set)
{
if (tok)
{
int len = strlen (tok) + 3;
char *tmp = tok;
tok = new char [len];
tok[0] = delim;
strcpy (tok+1, tmp);
tok[len-2] = delim;
tok[len-1] = '\0';
delete [] tmp;
}
}
else
{
quote_is_transpose = 1;
cant_be_identifier = 1;
convert_spaces_to_comma = 1;
}
yylval.tok_val = new token (tok);
delete [] tok;
token_stack.push (yylval.tok_val);
return TEXT;
}
}
}
else
{
buf << (char) c;
}
escape_pending = 0;
}
return LEXICAL_ERROR;
}
static int
handle_close_brace (int spc_gobbled)
{
if (! nesting_level.empty ())
{
nesting_level.pop ();
braceflag--;
}
if (braceflag == 0)
BEGIN 0;
int c1 = yyinput ();
if (c1 == '=')
{
quote_is_transpose = 0;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
int c2 = yyinput ();
unput (c2);
unput (c1);
if (c2 != '=' && maybe_screwed_again)
return SCREW_TWO;
else
return ']';
}
else
{
unput (c1);
if (braceflag && user_pref.whitespace_in_literal_matrix != 2)
{
int bin_op = next_token_is_bin_op (spc_gobbled, yytext);
int postfix_un_op = next_token_is_postfix_unary_op
(spc_gobbled, yytext);
int other_op = match_any (c1, ",;\n]");
if (! (postfix_un_op || bin_op || other_op
|| nesting_level.empty ())
&& nesting_level.top () == BRACE
&& convert_spaces_to_comma)
{
unput (',');
return ']';
}
}
}
quote_is_transpose = 1;
cant_be_identifier = 0;
convert_spaces_to_comma = 1;
return ']';
}
static void
maybe_unput_comma (int spc_gobbled)
{
if (user_pref.whitespace_in_literal_matrix != 2
&& ! nesting_level.empty ()
&& nesting_level.top () == BRACE)
{
int bin_op = next_token_is_bin_op (spc_gobbled, yytext);
int postfix_un_op = next_token_is_postfix_unary_op (spc_gobbled,
yytext);
int c1 = yyinput ();
int c2 = yyinput ();
unput (c2);
unput (c1);
int sep_op = match_any (c1, ",;\n]");
int dot_op = (c1 == '.'
&& (isalpha (c2) || isspace (c2) || c2 == '_'));
int index_op = (c1 == '('
&& (user_pref.whitespace_in_literal_matrix == 0
|| ! spc_gobbled));
if (! (postfix_un_op || bin_op || sep_op || dot_op || index_op))
unput (',');
}
}
// Figure out exactly what kind of token to return when we have seen
// an identifier. Handles keywords.
static int
handle_identifier (char *tok, int spc_gobbled)
{
// It is almost always an error for an identifier to be followed
// directly by another identifier. Special cases are handled below.
cant_be_identifier = 1;
// If we are expecting a structure element, we just want to return
// TEXT_ID, which is a string that is also a valid identifier. But
// first, we have to decide whether to insert a comma.
if (looking_at_indirect_ref)
{
maybe_unput_comma (spc_gobbled);
TOK_PUSH_AND_RETURN (tok, TEXT_ID);
}
// If we have a regular keyword, or a plot STYLE, return it. Keywords
// can be followed by identifiers (TOK_RETURN handles that).
int kw_token = is_keyword (tok);
if (kw_token)
{
if (kw_token == STYLE)
{
current_input_column += yyleng;
quote_is_transpose = 0;
convert_spaces_to_comma = 1;
return kw_token;
}
else
TOK_RETURN (kw_token);
}
// See if we have a plot keyword (title, using, with, or clear).
if (plotting)
{
// Yes, we really do need both of these plot_range variables. One
// is used to mark when we are past all possiblity of a plot range,
// the other is used to mark when we are actually between the square
// brackets that surround the range.
if (! in_plot_range)
past_plot_range = 1;
int plot_option_kw = is_plot_keyword (tok);
if (cant_be_identifier && plot_option_kw)
TOK_RETURN (plot_option_kw);
}
// If we are looking at a text style function, set up to gobble its
// arguments. These are also reserved words, but only because it
// would be very difficult to do anything intelligent with them if
// they were not reserved.
if (is_text_function_name (tok))
{
BEGIN TEXT_FCN;
if (strcmp (tok, "help") == 0)
BEGIN HELP_FCN;
else if (strcmp (tok, "set") == 0)
doing_set = 1;
}
int c = yyinput ();
yyunput (c, yytext);
int next_tok_is_eq = (c == '=');
// Make sure we put the return values of a function in the symbol
// table that is local to the function.
if (next_tok_is_eq && defining_func && maybe_screwed)
curr_sym_tab = tmp_local_sym_tab;
// Find the token in the symbol table.
yylval.tok_val = new token (lookup_identifier (tok),
input_line_number,
current_input_column);
token_stack.push (yylval.tok_val);
// After seeing an identifer, it is ok to convert spaces to a comma
// (if needed).
convert_spaces_to_comma = 1;
// If we are defining a function and we have not seen the parameter
// list yet and the next token is `=', return a token that represents
// the only return value for the function. For example,
//
// function SCREW = f (args);
//
// The variable maybe_screwed is reset in parse.y.
if (next_tok_is_eq)
{
current_input_column += yyleng;
if (defining_func && maybe_screwed)
return SCREW;
else
return NAME;
}
// At this point, we are only dealing with identifiers that are not
// followed by `=' (if the next token is `=', there is no need to
// check to see if we should insert a comma (invalid syntax), or allow
// a following `'' to be treated as a transpose (the next token is
// `=', so it can't be `''.
quote_is_transpose = 1;
do_comma_insert_check ();
maybe_unput_comma (spc_gobbled);
current_input_column += yyleng;
return NAME;
}
// Print a warning if a function file that defines a function has
// anything other than comments and whitespace following the END token
// that matches the FUNCTION statement.
void
check_for_garbage_after_fcn_def (void)
{
// By making a newline be the next character to be read, we will force
// the parser to return after reading the function. Calling yyunput
// with EOF seems not to work...
int in_comment = 0;
int lineno = input_line_number;
int c;
while ((c = yyinput ()) != EOF)
{
switch (c)
{
case ' ':
case '\t':
case ';':
case ',':
break;
case '\n':
if (in_comment)
in_comment = 0;
break;
case '%':
case '#':
in_comment = 1;
break;
default:
if (in_comment)
break;
else
{
warning ("ignoring trailing garbage after end of function\n\
near line %d of file `%s.m'", lineno, curr_fcn_file_name);
yyunput ('\n', yytext);
return;
}
}
}
yyunput ('\n', yytext);
}
/*
Maybe someday...
"+=" return ADD_EQ;
"-=" return SUB_EQ;
"*=" return MUL_EQ;
"/=" return DIV_EQ;
"\\=" return LEFTDIV_EQ;
".+=" return ADD_EQ;
".-=" return SUB_EQ;
".*=" return EMUL_EQ;
"./=" return EDIV_EQ;
".\\=" return ELEFTDIV_EQ;
*/